diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5cbad6c87e..087471ba79 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,7 +24,7 @@ jobs: timeout-minutes: 20 steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python uses: actions/setup-python@v5.2.0 @@ -86,7 +86,7 @@ jobs: python-key: ${{ steps.generate-python-key.outputs.key }} steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Set up Python ${{ matrix.python-version }} id: python uses: actions/setup-python@v5.2.0 @@ -146,7 +146,7 @@ jobs: # Workaround to set correct temp directory on Windows # https://github.com/actions/virtual-environments/issues/712 - name: Check out code from GitHub - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Set up Python ${{ matrix.python-version }} id: python uses: actions/setup-python@v5.2.0 @@ -197,7 +197,7 @@ jobs: python-version: ["pypy3.9", "pypy3.10"] steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Set up Python ${{ matrix.python-version }} id: python uses: actions/setup-python@v5.2.0 @@ -244,7 +244,7 @@ jobs: needs: ["tests-linux", "tests-windows", "tests-pypy"] steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Set up Python 3.12 id: python uses: actions/setup-python@v5.2.0 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fc639bf325..8402c938a9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -46,7 +46,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/release-tests.yml b/.github/workflows/release-tests.yml index fb1d9086e4..7538d6039e 100644 --- a/.github/workflows/release-tests.yml +++ b/.github/workflows/release-tests.yml @@ -13,7 +13,7 @@ jobs: timeout-minutes: 5 steps: - name: Check out code from GitHub - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Set up Python 3.9 id: python uses: actions/setup-python@v5.2.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3c6d841ea..862436c781 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: url: https://pypi.org/project/astroid/ steps: - name: Check out code from Github - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python uses: actions/setup-python@v5.2.0 diff --git a/ChangeLog b/ChangeLog index e318ff62b4..56d97ad391 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,7 @@ astroid's ChangeLog =================== -What's New in astroid 3.4.0? +What's New in astroid 4.0.0? ============================ Release date: TBA @@ -17,18 +17,6 @@ Release date: TBA Closes pylint-dev/astroid/issues/1490 -* Fix regression with f-string inference. - - Closes pylint-dev/pylint#9947 - -* Fix bug with ``manager.clear_cache()`` not fully clearing cache - - Refs https://github.com/pylint-dev/pylint/pull/9932#issuecomment-2364985551 - -* Fix a crash from inferring empty format specs. - - Closes pylint-dev/pylint#9945 - What's New in astroid 3.3.4? ============================ @@ -38,7 +26,7 @@ Release date: 2024-09-23 Closes pylint-dev/pylint#9947 -* Fix bug with ``manager.clear_cache()`` not fully clearing cache +* Fix bug with ``manager.clear_cache()`` not fully clearing cache. Refs https://github.com/pylint-dev/pylint/pull/9932#issuecomment-2364985551 diff --git a/astroid/__pkginfo__.py b/astroid/__pkginfo__.py index 6707429079..18f0d9b196 100644 --- a/astroid/__pkginfo__.py +++ b/astroid/__pkginfo__.py @@ -2,5 +2,5 @@ # For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE # Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt -__version__ = "3.4.0-dev0" +__version__ = "4.0.0-dev0" version = __version__ diff --git a/astroid/bases.py b/astroid/bases.py index 7611a77c0d..d91a4c9faf 100644 --- a/astroid/bases.py +++ b/astroid/bases.py @@ -679,7 +679,7 @@ class Generator(BaseInstance): # We defer initialization of special_attributes to the __init__ method since the constructor # of GeneratorModel requires the raw_building to be complete # TODO: This should probably be refactored. - special_attributes: objectmodel.GeneratorModel + special_attributes: objectmodel.GeneratorBaseModel def __init__( self, diff --git a/astroid/brain/brain_numpy_core_function_base.py b/astroid/brain/brain_numpy_core_function_base.py index 17e1ad11d2..2bfe97080c 100644 --- a/astroid/brain/brain_numpy_core_function_base.py +++ b/astroid/brain/brain_numpy_core_function_base.py @@ -7,8 +7,8 @@ import functools from astroid.brain.brain_numpy_utils import ( - attribute_looks_like_numpy_member, - infer_numpy_member, + attribute_name_looks_like_numpy_member, + infer_numpy_attribute, ) from astroid.inference_tip import inference_tip from astroid.manager import AstroidManager @@ -25,10 +25,11 @@ def register(manager: AstroidManager) -> None: - for func_name, func_src in METHODS_TO_BE_INFERRED.items(): - inference_function = functools.partial(infer_numpy_member, func_src) - manager.register_transform( - Attribute, - inference_tip(inference_function), - functools.partial(attribute_looks_like_numpy_member, func_name), - ) + manager.register_transform( + Attribute, + inference_tip(functools.partial(infer_numpy_attribute, METHODS_TO_BE_INFERRED)), + functools.partial( + attribute_name_looks_like_numpy_member, + frozenset(METHODS_TO_BE_INFERRED.keys()), + ), + ) diff --git a/astroid/brain/brain_numpy_core_multiarray.py b/astroid/brain/brain_numpy_core_multiarray.py index 16cdd6f918..95ef0a3402 100644 --- a/astroid/brain/brain_numpy_core_multiarray.py +++ b/astroid/brain/brain_numpy_core_multiarray.py @@ -8,9 +8,10 @@ from astroid import nodes from astroid.brain.brain_numpy_utils import ( - attribute_looks_like_numpy_member, - infer_numpy_member, - name_looks_like_numpy_member, + attribute_name_looks_like_numpy_member, + infer_numpy_attribute, + infer_numpy_name, + member_name_looks_like_numpy_member, ) from astroid.brain.helpers import register_module_extender from astroid.builder import parse @@ -92,15 +93,15 @@ def register(manager: AstroidManager) -> None: manager, "numpy.core.multiarray", numpy_core_multiarray_transform ) - for method_name, function_src in METHODS_TO_BE_INFERRED.items(): - inference_function = functools.partial(infer_numpy_member, function_src) - manager.register_transform( - Attribute, - inference_tip(inference_function), - functools.partial(attribute_looks_like_numpy_member, method_name), - ) - manager.register_transform( - Name, - inference_tip(inference_function), - functools.partial(name_looks_like_numpy_member, method_name), - ) + method_names = frozenset(METHODS_TO_BE_INFERRED.keys()) + + manager.register_transform( + Attribute, + inference_tip(functools.partial(infer_numpy_attribute, METHODS_TO_BE_INFERRED)), + functools.partial(attribute_name_looks_like_numpy_member, method_names), + ) + manager.register_transform( + Name, + inference_tip(functools.partial(infer_numpy_name, METHODS_TO_BE_INFERRED)), + functools.partial(member_name_looks_like_numpy_member, method_names), + ) diff --git a/astroid/brain/brain_numpy_core_numeric.py b/astroid/brain/brain_numpy_core_numeric.py index df4ae0cbb1..72d4cc9c14 100644 --- a/astroid/brain/brain_numpy_core_numeric.py +++ b/astroid/brain/brain_numpy_core_numeric.py @@ -8,8 +8,8 @@ from astroid import nodes from astroid.brain.brain_numpy_utils import ( - attribute_looks_like_numpy_member, - infer_numpy_member, + attribute_name_looks_like_numpy_member, + infer_numpy_attribute, ) from astroid.brain.helpers import register_module_extender from astroid.builder import parse @@ -41,10 +41,11 @@ def register(manager: AstroidManager) -> None: manager, "numpy.core.numeric", numpy_core_numeric_transform ) - for method_name, function_src in METHODS_TO_BE_INFERRED.items(): - inference_function = functools.partial(infer_numpy_member, function_src) - manager.register_transform( - Attribute, - inference_tip(inference_function), - functools.partial(attribute_looks_like_numpy_member, method_name), - ) + manager.register_transform( + Attribute, + inference_tip(functools.partial(infer_numpy_attribute, METHODS_TO_BE_INFERRED)), + functools.partial( + attribute_name_looks_like_numpy_member, + frozenset(METHODS_TO_BE_INFERRED.keys()), + ), + ) diff --git a/astroid/brain/brain_numpy_utils.py b/astroid/brain/brain_numpy_utils.py index 47f24433bd..8ce7144372 100644 --- a/astroid/brain/brain_numpy_utils.py +++ b/astroid/brain/brain_numpy_utils.py @@ -34,6 +34,21 @@ def _get_numpy_version() -> tuple[str, str, str]: return ("0", "0", "0") +def infer_numpy_name( + sources: dict[str, str], node: Name, context: InferenceContext | None = None +): + extracted_node = extract_node(sources[node.name]) + return extracted_node.infer(context=context) + + +def infer_numpy_attribute( + sources: dict[str, str], node: Attribute, context: InferenceContext | None = None +): + extracted_node = extract_node(sources[node.attrname]) + return extracted_node.infer(context=context) + + +# TODO: Deprecate and remove this function def infer_numpy_member(src, node, context: InferenceContext | None = None): node = extract_node(src) return node.infer(context=context) @@ -61,6 +76,29 @@ def _is_a_numpy_module(node: Name) -> bool: ) +def member_name_looks_like_numpy_member( + member_names: frozenset[str], node: Name +) -> bool: + """ + Returns True if the Name node's name matches a member name from numpy + """ + return node.name in member_names and node.root().name.startswith("numpy") + + +def attribute_name_looks_like_numpy_member( + member_names: frozenset[str], node: Attribute +) -> bool: + """ + Returns True if the Attribute node's name matches a member name from numpy + """ + return ( + node.attrname in member_names + and isinstance(node.expr, Name) + and _is_a_numpy_module(node.expr) + ) + + +# TODO: Deprecate and remove this function def name_looks_like_numpy_member(member_name: str, node: Name) -> bool: """ Returns True if the Name is a member of numpy whose @@ -69,6 +107,7 @@ def name_looks_like_numpy_member(member_name: str, node: Name) -> bool: return node.name == member_name and node.root().name.startswith("numpy") +# TODO: Deprecate and remove this function def attribute_looks_like_numpy_member(member_name: str, node: Attribute) -> bool: """ Returns True if the Attribute is a member of numpy whose diff --git a/astroid/interpreter/objectmodel.py b/astroid/interpreter/objectmodel.py index 7532db5edb..fd8c0c051b 100644 --- a/astroid/interpreter/objectmodel.py +++ b/astroid/interpreter/objectmodel.py @@ -694,12 +694,10 @@ def attr___self__(self): return self._instance.bound -class GeneratorModel(FunctionModel, ContextManagerModel): - def __init__(self): - # Append the values from the GeneratorType unto this object. +class GeneratorBaseModel(FunctionModel, ContextManagerModel): + def __init__(self, gen_module: nodes.Module): super().__init__() - generator = AstroidManager().builtins_module["generator"] - for name, values in generator.locals.items(): + for name, values in gen_module.locals.items(): method = values[0] if isinstance(method, nodes.FunctionDef): method = bases.BoundMethod(method, _get_bound_node(self)) @@ -723,21 +721,14 @@ def attr___doc__(self): ) -class AsyncGeneratorModel(GeneratorModel): +class GeneratorModel(GeneratorBaseModel): def __init__(self): - # Append the values from the AGeneratorType unto this object. - super().__init__() - astroid_builtins = AstroidManager().builtins_module - generator = astroid_builtins["async_generator"] - for name, values in generator.locals.items(): - method = values[0] - if isinstance(method, nodes.FunctionDef): - method = bases.BoundMethod(method, _get_bound_node(self)) + super().__init__(AstroidManager().builtins_module["generator"]) - def patched(cls, meth=method): - return meth - setattr(type(self), IMPL_PREFIX + name, property(patched)) +class AsyncGeneratorModel(GeneratorBaseModel): + def __init__(self): + super().__init__(AstroidManager().builtins_module["async_generator"]) class InstanceModel(ObjectModel): diff --git a/tbump.toml b/tbump.toml index 2001b94c79..0c98eaefb5 100644 --- a/tbump.toml +++ b/tbump.toml @@ -1,7 +1,7 @@ github_url = "https://github.com/pylint-dev/astroid" [version] -current = "3.4.0-dev0" +current = "4.0.0-dev0" regex = ''' ^(?P0|[1-9]\d*) \.