Skip to content

Commit 46dfcf8

Browse files
authored
Add TCH/T10/FA lints and sync conda.deprecations (#5178)
1 parent ec50bdf commit 46dfcf8

33 files changed

+230
-80
lines changed

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ ci:
55
# ignore patches/diffs since slight reformatting can break them
66
exclude: |
77
(?x)^(
8+
conda_build/version.py |
89
tests/(
910
archives |
1011
index_data |
@@ -47,7 +48,6 @@ repos:
4748
- id: insert-license
4849
files: \.py$
4950
args: [--license-filepath, .github/disclaimer.txt, --no-extra-eol]
50-
exclude: ^conda_build/version.py
5151
- repo: https://github.com/asottile/blacken-docs
5252
rev: 1.16.0
5353
hooks:

conda_build/cli/main_build.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,17 @@
66
import logging
77
import sys
88
import warnings
9-
from argparse import Namespace
109
from glob import glob
1110
from itertools import chain
1211
from os.path import abspath, expanduser, expandvars
1312
from pathlib import Path
14-
from typing import Sequence
13+
from typing import TYPE_CHECKING
1514

1615
from conda.auxlib.ish import dals
1716
from conda.common.io import dashlist
1817

1918
from .. import api, build, source, utils
20-
from ..conda_interface import (
21-
ArgumentParser,
22-
add_parser_channels,
23-
binstar_upload,
24-
cc_conda_build,
25-
)
19+
from ..conda_interface import add_parser_channels, binstar_upload, cc_conda_build
2620
from ..config import (
2721
get_channel_urls,
2822
get_or_merge_config,
@@ -32,6 +26,12 @@
3226
from .actions import KeyValueAction
3327
from .main_render import get_render_parser
3428

29+
if TYPE_CHECKING:
30+
from argparse import Namespace
31+
from typing import Sequence
32+
33+
from ..conda_interface import ArgumentParser
34+
3535

3636
def parse_args(args: Sequence[str] | None) -> tuple[ArgumentParser, Namespace]:
3737
parser = get_render_parser()

conda_build/cli/main_convert.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
from __future__ import annotations
44

55
import logging
6-
from argparse import Namespace
76
from os.path import abspath, expanduser
8-
from typing import Sequence
7+
from typing import TYPE_CHECKING
98

109
from .. import api
1110
from ..conda_interface import ArgumentParser
1211

12+
if TYPE_CHECKING:
13+
from argparse import Namespace
14+
from typing import Sequence
15+
1316
logging.basicConfig(level=logging.INFO)
1417

1518
epilog = """

conda_build/cli/main_debug.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44

55
import logging
66
import sys
7-
from argparse import ArgumentParser
8-
from typing import Sequence
7+
from typing import TYPE_CHECKING
98

109
from .. import api
1110
from ..utils import on_win
1211
from . import validators as valid
1312
from .main_render import get_render_parser
1413

14+
if TYPE_CHECKING:
15+
from argparse import ArgumentParser
16+
from typing import Sequence
17+
1518
logging.basicConfig(level=logging.INFO)
1619

1720

conda_build/cli/main_develop.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
from __future__ import annotations
44

55
import logging
6-
from argparse import Namespace
7-
from typing import Sequence
6+
from typing import TYPE_CHECKING
87

98
from conda.base.context import context, determine_target_prefix
109

1110
from .. import api
1211
from ..conda_interface import ArgumentParser, add_parser_prefix
1312

13+
if TYPE_CHECKING:
14+
from argparse import Namespace
15+
from typing import Sequence
16+
1417
logging.basicConfig(level=logging.INFO)
1518

1619

conda_build/cli/main_inspect.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@
44

55
import logging
66
import sys
7-
from argparse import Namespace
87
from os.path import expanduser
98
from pprint import pprint
10-
from typing import Sequence
9+
from typing import TYPE_CHECKING
1110

1211
from conda.base.context import context, determine_target_prefix
1312

1413
from .. import api
1514
from ..conda_interface import ArgumentParser, add_parser_prefix
1615

16+
if TYPE_CHECKING:
17+
from argparse import Namespace
18+
from typing import Sequence
19+
1720
logging.basicConfig(level=logging.INFO)
1821

1922

conda_build/cli/main_metapackage.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
import argparse
66
import logging
7-
from argparse import Namespace
8-
from typing import Sequence
7+
from typing import TYPE_CHECKING
98

109
from .. import api
1110
from ..conda_interface import ArgumentParser, add_parser_channels, binstar_upload
1211

12+
if TYPE_CHECKING:
13+
from argparse import Namespace
14+
from typing import Sequence
15+
1316
logging.basicConfig(level=logging.INFO)
1417

1518

conda_build/cli/main_render.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44

55
import argparse
66
import logging
7-
from argparse import Namespace
87
from pprint import pprint
9-
from typing import Sequence
8+
from typing import TYPE_CHECKING
109

1110
import yaml
1211
from yaml.parser import ParserError
@@ -18,6 +17,10 @@
1817
from ..utils import LoggingContext
1918
from ..variants import get_package_variants, set_language_env_vars
2019

20+
if TYPE_CHECKING:
21+
from argparse import Namespace
22+
from typing import Sequence
23+
2124
log = logging.getLogger(__name__)
2225

2326

conda_build/cli/main_skeleton.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
import os
88
import pkgutil
99
import sys
10-
from argparse import Namespace
11-
from typing import Sequence
10+
from typing import TYPE_CHECKING
1211

1312
from .. import api
1413
from ..conda_interface import ArgumentParser
1514
from ..config import Config
1615

16+
if TYPE_CHECKING:
17+
from argparse import Namespace
18+
from typing import Sequence
19+
1720
thisdir = os.path.dirname(os.path.abspath(__file__))
1821
logging.basicConfig(level=logging.INFO)
1922

conda_build/config.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import time
1414
from collections import namedtuple
1515
from os.path import abspath, expanduser, expandvars, join
16-
from pathlib import Path
16+
from typing import TYPE_CHECKING
1717

1818
from .conda_interface import (
1919
binstar_upload,
@@ -33,6 +33,9 @@
3333
)
3434
from .variants import get_default_variant
3535

36+
if TYPE_CHECKING:
37+
from pathlib import Path
38+
3639
invocation_time = ""
3740

3841

conda_build/create_test.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99
import os
1010
from os.path import basename, exists, isfile, join
1111
from pathlib import Path
12+
from typing import TYPE_CHECKING
1213

13-
from .metadata import MetaData
1414
from .utils import copy_into, ensure_list, on_win, rm_rf
1515

16+
if TYPE_CHECKING:
17+
from .metadata import MetaData
18+
1619

1720
def create_files(m: MetaData, test_dir: Path) -> bool:
1821
"""

conda_build/deprecations.py

+70-18
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55

66
import sys
77
import warnings
8-
from argparse import Action
98
from functools import wraps
109
from types import ModuleType
11-
from typing import Any, Callable
10+
from typing import TYPE_CHECKING
1211

13-
from packaging.version import Version, parse
12+
if TYPE_CHECKING:
13+
from argparse import Action
14+
from typing import Any, Callable
15+
16+
from packaging.version import Version
1417

1518
from . import __version__
1619

@@ -22,17 +25,52 @@ class DeprecatedError(RuntimeError):
2225
# inspired by deprecation (https://deprecation.readthedocs.io/en/latest/) and
2326
# CPython's warnings._deprecated
2427
class DeprecationHandler:
25-
_version: Version
28+
_version: str | None
29+
_version_tuple: tuple[int, ...] | None
30+
_version_object: Version | None
2631

27-
def __init__(self, version: Version | str):
32+
def __init__(self, version: str):
2833
"""Factory to create a deprecation handle for the specified version.
2934
3035
:param version: The version to compare against when checking deprecation statuses.
3136
"""
37+
self._version = version
38+
# Try to parse the version string as a simple tuple[int, ...] to avoid
39+
# packaging.version import and costlier version comparisons.
40+
self._version_tuple = self._get_version_tuple(version)
41+
self._version_object = None
42+
43+
@staticmethod
44+
def _get_version_tuple(version: str) -> tuple[int, ...] | None:
45+
"""Return version as non-empty tuple of ints if possible, else None.
46+
47+
:param version: Version string to parse.
48+
"""
3249
try:
33-
self._version = parse(version)
34-
except TypeError:
35-
self._version = parse("0.0.0.dev0+placeholder")
50+
return tuple(int(part) for part in version.strip().split(".")) or None
51+
except (AttributeError, ValueError):
52+
return None
53+
54+
def _version_less_than(self, version: str) -> bool:
55+
"""Test whether own version is less than the given version.
56+
57+
:param version: Version string to compare against.
58+
"""
59+
if self._version_tuple:
60+
if version_tuple := self._get_version_tuple(version):
61+
return self._version_tuple < version_tuple
62+
63+
# If self._version or version could not be represented by a simple
64+
# tuple[int, ...], do a more elaborate version parsing and comparison.
65+
# Avoid this import otherwise to reduce import time for conda activate.
66+
from packaging.version import parse
67+
68+
if self._version_object is None:
69+
try:
70+
self._version_object = parse(self._version)
71+
except TypeError:
72+
self._version_object = parse("0.0.0.dev0+placeholder")
73+
return self._version_object < parse(version)
3674

3775
def __call__(
3876
self,
@@ -281,16 +319,33 @@ def _get_module(self, stack: int) -> tuple[ModuleType, str]:
281319
:param stack: The stacklevel increment.
282320
:return: The module and module name.
283321
"""
284-
import inspect # expensive
285-
286322
try:
287323
frame = sys._getframe(2 + stack)
288-
module = inspect.getmodule(frame)
289-
if module is not None:
290-
return (module, module.__name__)
291324
except IndexError:
292325
# IndexError: 2 + stack is out of range
293326
pass
327+
else:
328+
# Shortcut finding the module by manually inspecting loaded modules.
329+
try:
330+
filename = frame.f_code.co_filename
331+
except AttributeError:
332+
# AttributeError: frame.f_code.co_filename is undefined
333+
pass
334+
else:
335+
for module in sys.modules.values():
336+
if not isinstance(module, ModuleType):
337+
continue
338+
if not hasattr(module, "__file__"):
339+
continue
340+
if module.__file__ == filename:
341+
return (module, module.__name__)
342+
343+
# If above failed, do an expensive import and costly getmodule call.
344+
import inspect
345+
346+
module = inspect.getmodule(frame)
347+
if module is not None:
348+
return (module, module.__name__)
294349

295350
raise DeprecatedError("unable to determine the calling module")
296351

@@ -309,14 +364,11 @@ def _generate_message(
309364
:param addendum: Additional messaging. Useful to indicate what to do instead.
310365
:return: The warning category (if applicable) and the message.
311366
"""
312-
deprecate_version = parse(deprecate_in)
313-
remove_version = parse(remove_in)
314-
315367
category: type[Warning] | None
316-
if self._version < deprecate_version:
368+
if self._version_less_than(deprecate_in):
317369
category = PendingDeprecationWarning
318370
warning = f"is pending deprecation and will be removed in {remove_in}."
319-
elif self._version < remove_version:
371+
elif self._version_less_than(remove_in):
320372
category = DeprecationWarning
321373
warning = f"is deprecated and will be removed in {remove_in}."
322374
else:

conda_build/inspect_pkg.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from os.path import abspath, basename, dirname, exists, join, normcase
1212
from pathlib import Path
1313
from tempfile import TemporaryDirectory
14-
from typing import Iterable, Literal
14+
from typing import TYPE_CHECKING
1515

1616
from conda.api import Solver
1717
from conda.core.index import get_index
@@ -40,6 +40,9 @@
4040
package_has_file,
4141
)
4242

43+
if TYPE_CHECKING:
44+
from typing import Iterable, Literal
45+
4346
log = get_logger(__name__)
4447

4548

0 commit comments

Comments
 (0)