Skip to content

Commit 897df83

Browse files
authored
feat: make dask optional so osw imports without it (#219)
- move dask into a new `parallel` extra and import it lazily. util.py is imported unconditionally by core, wtsite and wiki_tools, so a missing dask broke `import osw` outright - which ruled out Pyodide, where there is no dask build.
1 parent 98320d1 commit 897df83

3 files changed

Lines changed: 32 additions & 9 deletions

File tree

‎pyproject.toml‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ dependencies = [
4747
# used in custom_types.py on py3.10; was missing before (latent
4848
# ImportError on 3.10), surfaced by ty/deptry during the migration
4949
'backports.strenum; python_version < "3.11"',
50-
"dask",
5150
"tqdm",
5251
"pybars3-wheel",
5352
# the osw CLI (src/osw/cli); a base dependency, not an extra, so `pip
@@ -71,6 +70,10 @@ Download = "https://pypi.org/project/osw/#files"
7170

7271
[project.optional-dependencies]
7372
wikitext = ["mwparserfromhell"]
73+
# Only osw.utils.util.async_parallelize needs it, and nothing in the package calls
74+
# that. Keeping it in the base dependencies made `import osw` impossible anywhere
75+
# dask is unavailable - notably Pyodide, which has no dask build.
76+
parallel = ["dask"]
7477
DB = [
7578
"psycopg2",
7679
"sqlalchemy",
@@ -106,7 +109,7 @@ workflow = [
106109
"anyio>=4.9,<4.14",
107110
]
108111
tutorial = ["osw[dataimport]"]
109-
all = ["osw[dataimport,DB,UI,S3,wikitext,mcp]"]
112+
all = ["osw[dataimport,DB,UI,S3,wikitext,mcp,parallel]"]
110113

111114
[project.scripts]
112115
# command-line access to a live OSL instance, built from the same

‎src/osw/utils/util.py‎

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
from pathlib import Path
1313
from typing import IO, Callable, Dict, Iterable, List, Optional, Union
1414

15-
import dask
16-
from dask.diagnostics import ProgressBar
1715
from tqdm.asyncio import tqdm
1816

1917
_logger = logging.getLogger(__name__)
@@ -585,7 +583,21 @@ def file_in_paths(
585583

586584

587585
def async_parallelize(func: Callable, iterable: Iterable, **kwargs):
588-
"""Work in progress"""
586+
"""Work in progress. Requires the optional ``parallel`` extra.
587+
588+
dask is imported here rather than at module scope because this is the only
589+
thing in osw that uses it. At module scope it made ``import osw`` fail
590+
outright wherever dask is unavailable - util.py is imported unconditionally
591+
by core, wtsite and wiki_tools - which rules out Pyodide, where there is no
592+
dask build at all.
593+
"""
594+
# ty cannot resolve these: dask is the `parallel` extra and is deliberately
595+
# absent from the dev environment, which is the condition this import exists to
596+
# tolerate. Adding the extra to the dev group would make it resolve - that is what
597+
# pyproject does for mcp - but it would install dask everywhere to type check the
598+
# one place that is allowed to run without it.
599+
import dask # ty: ignore[unresolved-import]
600+
from dask.diagnostics import ProgressBar # ty: ignore[unresolved-import]
589601

590602
async def inner(func_, iterable_, **kwargs_):
591603
async with AsyncMessageBuffer() as msg_buf:
@@ -646,6 +658,11 @@ def wrapped_function(*args, **kwargs):
646658
from datetime import datetime
647659
from time import sleep
648660

661+
# Only the demo helpers below use dask; see async_parallelize for why it is
662+
# not imported at module scope. Needs the optional `parallel` extra.
663+
import dask # ty: ignore[unresolved-import]
664+
from dask.diagnostics import ProgressBar # ty: ignore[unresolved-import]
665+
649666
print("Redirecting print messages to a buffer.")
650667
message_buffer = MessageBuffer()
651668
io_buffer = StringIO()

‎uv.lock‎

Lines changed: 7 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)