Skip to content

Commit 059e43f

Browse files
committed
types: rename dvc/types.py to dvc/_types.py to remove stdlib shadow
The previous two attempts at #11035 (53d6d6b: `-m dvc`, then 26b5514: `-c "from dvc.cli import main; ..."`) both broke `tests/func/experiments/test_experiments.py::test_run_celery` on every Python version (3.9-3.14) on Windows. Master is green for that test including 3.14, so the Windows-specific celery worker spawn path genuinely depends on the script form -- changing the launch shape is not a viable fix even when both alternatives keep sys.path[0] empty. Address the root cause structurally instead: rename the internal `dvc/types.py` module (containing `StrPath`, `DictStrAny`, `TargetType`, etc.) to `dvc/_types.py`. The leading underscore both signals "private" and -- more importantly -- removes any name collision with stdlib `types`, so no matter how the daemon worker is launched (script form, `-m dvc`, `-c`, pipx-installed shim, ...) no entry on sys.path can shadow stdlib `types` via the dvc package. Daemon launch shape is reverted to the original script form (`python <site-packages>/dvc/__main__.py ...`) -- identical to master. This is what kept the Windows celery worker test green for years, and is what we want to keep working. The `dvc/_types.py` rename is what fixes the underlying Python 3.14 shadow risk for the user-reported case (#11035 reporter installs via pipx). Files updated: - dvc/types.py -> dvc/_types.py (rename, content unchanged) - 19 internal call sites: `from dvc.types import X` -> `from dvc._types import X` - dvc/daemon.py: revert _get_dvc_args to master's script form - tests/unit/test_daemon.py: regression test asserting `dvc/types.py` does not exist and that stdlib `types` is not resolved to a dvc module. This guards against someone reintroducing the file later. The rename is a backward-incompatible internal API change in principle, but `dvc/types.py` was undocumented and the aliases are only meant for internal use (see imports across the codebase -- all internal). No external consumers are likely to depend on `from dvc.types import ...` because the public type surface is exposed via `dvc.api`, `dvc.repo`, etc., not via the type-alias module.
1 parent 51f513d commit 059e43f

23 files changed

Lines changed: 51 additions & 77 deletions

File tree

File renamed without changes.

dvc/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
if TYPE_CHECKING:
1919
from dvc.fs import FileSystem
20-
from dvc.types import DictStrAny
20+
from dvc._types import DictStrAny
2121

2222
logger = logger.getChild(__name__)
2323

dvc/daemon.py

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -59,29 +59,9 @@ def _win_detached_subprocess(args: Sequence[str], **kwargs) -> int:
5959
def _get_dvc_args() -> list[str]:
6060
args = [sys.executable]
6161
if not is_binary():
62-
# Launch via `python -c "<bootstrap>"` rather than
63-
# `python .../dvc/__main__.py`. Running a script directly puts the
64-
# script's directory at sys.path[0] (PEP 338), which makes
65-
# dvc/types.py shadow the stdlib `types` module -- fatal on
66-
# Python 3.14+ where stdlib re/enum import from `types` early
67-
# during interpreter startup, before any user code runs.
68-
#
69-
# `-m dvc` would also avoid the script-dir-on-sys.path problem,
70-
# but it sets `__main__.__spec__.name = "dvc.__main__"`, which on
71-
# Windows changes how billiard / celery's main-module fixup picks
72-
# up the parent module in spawned children and crashes the celery
73-
# worker that backs `dvc queue start` (see #11037 CI). `-c` keeps
74-
# `__main__` script-shaped (no `__spec__`) so billiard's existing
75-
# main-module path is preserved, while still leaving sys.path[0]
76-
# empty so dvc/types.py never shadows stdlib `types`.
77-
#
78-
# daemonize() prepends site-packages to PYTHONPATH (see below),
79-
# so `from dvc.cli import main` resolves without script-dir
80-
# injection. Fixes https://github.com/iterative/dvc/issues/11035.
81-
args += [
82-
"-c",
83-
"import sys; from dvc.cli import main; sys.exit(main(sys.argv[1:]))",
84-
]
62+
root_dir = os.path.abspath(os.path.dirname(__file__))
63+
main_entrypoint = os.path.join(root_dir, "__main__.py")
64+
args.append(main_entrypoint)
8565
return args
8666

8767

dvc/database.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from dvc import env
1313
from dvc.exceptions import DvcException
1414
from dvc.log import logger
15-
from dvc.types import StrOrBytesPath
15+
from dvc._types import StrOrBytesPath
1616
from dvc.utils import env2bool
1717

1818
if TYPE_CHECKING:

dvc/dvcfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
if TYPE_CHECKING:
1919
from dvc.repo import Repo
20-
from dvc.types import StrOrBytesPath
20+
from dvc._types import StrOrBytesPath
2121

2222
from .parsing import DataResolver
2323
from .stage import Stage

dvc/fs/dvc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from contextlib import AbstractContextManager
2323

2424
from dvc.repo import Repo
25-
from dvc.types import DictStrAny, StrPath
25+
from dvc._types import DictStrAny, StrPath
2626

2727
from .callbacks import Callback
2828

dvc/parsing/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from typing import NoReturn
3333

3434
from dvc.repo import Repo
35-
from dvc.types import DictStrAny
35+
from dvc._types import DictStrAny
3636

3737
from .context import SeqOrMap
3838

dvc/render/converter/image.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from . import Converter
88

99
if TYPE_CHECKING:
10-
from dvc.types import StrPath
10+
from dvc._types import StrPath
1111

1212

1313
class ImageConverter(Converter):

dvc/render/match.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from .convert import _get_converter
1313

1414
if TYPE_CHECKING:
15-
from dvc.types import StrPath
15+
from dvc._types import StrPath
1616
from dvc_render.base import Renderer
1717

1818

dvc/repo/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from dvc.output import Output
2424
from dvc.scm import Git, NoSCM
2525
from dvc.stage import Stage
26-
from dvc.types import DictStrAny
26+
from dvc._types import DictStrAny
2727
from dvc_data.hashfile.state import StateBase
2828
from dvc_data.index import DataIndex, DataIndexEntry
2929

0 commit comments

Comments
 (0)