Skip to content

Commit

Permalink
Merge pull request #664 from hippo91/bug_pylint_2721
Browse files Browse the repository at this point in the history
Deep rework of the numpy brain.

The original brain has been split into numerous one. Each numpy brain module corresponds to
a numpyone. There are:

brain_numpy_core_fromnumeric => numpy.core.fromnumeric
brain_numpy_core_function_base => numpy.core.function_base
brain_numpy_core_multiarray => numpy.core.multiarray
brain_numpy_core_numeric => numpy.core.numeric
brain_core_numerictypes => numpy.core.numerictypes
brain_core_umath => numpy.core.umath
brain_numpy_random_mtrand => numpy.random.mtrand
Last but not least, the numpy.ndarray class has its corresponding astroid's brain (brain_numpy_ndarray).

The major improvement, besides a clearer organisation, is the fact that each method of the ndarray class should now be correctly inferred. Especially those returning ndarray objects.

It has been made possible by ensuring that the return type of those methods is inferred as ndarray and nothing else. To achieve this, the inference_tip function has been used.

When a numpy callable may return two different kinds of objects, for example bool or ndarray, the choice to prefer ndarray has been made in the corresponding astroid brain method.
  • Loading branch information
PCManticore authored Jun 2, 2019
2 parents edd79cf + f818d1a commit 33065ec
Show file tree
Hide file tree
Showing 20 changed files with 1,874 additions and 1,217 deletions.
19 changes: 19 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ What's New in astroid 2.3.0?
============================
Release Date: TBA

* Numpy brain support is improved.

Numpy's fundamental type ``numpy.ndarray`` has its own brain : ``brain_numpy_ndarray`` and
each numpy module that necessitates brain action has now its own numpy brain :

- ``numpy.core.numeric``
- ``numpy.core.function_base``
- ``numpy.core.multiarray``
- ``numpy.core.numeric``
- ``numpy.core.numerictypes``
- ``numpy.core.umath``
- ``numpy.random.mtrand``

Close PyCQA/pylint#2865
Close PyCQA/pylint#2747
Close PyCQA/pylint#2721
Close PyCQA/pylint#2326
Close PyCQA/pylint#2021

* Add support for Python 3.8's `NamedExpr` nodes, which is part of assignment expressions.

Close #674
Expand Down
557 changes: 0 additions & 557 deletions astroid/brain/brain_numpy.py

This file was deleted.

23 changes: 23 additions & 0 deletions astroid/brain/brain_numpy_core_fromnumeric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (c) 2018-2019 hippo91 <guillaume.peillex@gmail.com>

# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER


"""Astroid hooks for numpy.core.fromnumeric module."""

import astroid


def numpy_core_fromnumeric_transform():
return astroid.parse(
"""
def sum(a, axis=None, dtype=None, out=None, keepdims=None, initial=None):
return numpy.ndarray([0, 0])
"""
)


astroid.register_module_extender(
astroid.MANAGER, "numpy.core.fromnumeric", numpy_core_fromnumeric_transform
)
29 changes: 29 additions & 0 deletions astroid/brain/brain_numpy_core_function_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright (c) 2018-2019 hippo91 <guillaume.peillex@gmail.com>

# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER


"""Astroid hooks for numpy.core.function_base module."""

import functools
import astroid
from brain_numpy_utils import looks_like_numpy_member, infer_numpy_member


METHODS_TO_BE_INFERRED = {
"linspace": """def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0):
return numpy.ndarray([0, 0])""",
"logspace": """def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0):
return numpy.ndarray([0, 0])""",
"geomspace": """def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
return numpy.ndarray([0, 0])""",
}

for func_name, func_src in METHODS_TO_BE_INFERRED.items():
inference_function = functools.partial(infer_numpy_member, func_src)
astroid.MANAGER.register_transform(
astroid.Attribute,
astroid.inference_tip(inference_function),
functools.partial(looks_like_numpy_member, func_name),
)
55 changes: 55 additions & 0 deletions astroid/brain/brain_numpy_core_multiarray.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright (c) 2018-2019 hippo91 <guillaume.peillex@gmail.com>

# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER


"""Astroid hooks for numpy.core.multiarray module."""

import functools
import astroid
from brain_numpy_utils import looks_like_numpy_member, infer_numpy_member


def numpy_core_multiarray_transform():
return astroid.parse(
"""
# different functions defined in multiarray.py
def inner(a, b):
return numpy.ndarray([0, 0])
def vdot(a, b):
return numpy.ndarray([0, 0])
"""
)


astroid.register_module_extender(
astroid.MANAGER, "numpy.core.multiarray", numpy_core_multiarray_transform
)


METHODS_TO_BE_INFERRED = {
"array": """def array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0):
return numpy.ndarray([0, 0])""",
"dot": """def dot(a, b, out=None):
return numpy.ndarray([0, 0])""",
"empty_like": """def empty_like(a, dtype=None, order='K', subok=True):
return numpy.ndarray((0, 0))""",
"concatenate": """def concatenate(arrays, axis=None, out=None):
return numpy.ndarray((0, 0))""",
"where": """def where(condition, x=None, y=None):
return numpy.ndarray([0, 0])""",
"empty": """def empty(shape, dtype=float, order='C'):
return numpy.ndarray([0, 0])""",
"zeros": """def zeros(shape, dtype=float, order='C'):
return numpy.ndarray([0, 0])""",
}

for method_name, function_src in METHODS_TO_BE_INFERRED.items():
inference_function = functools.partial(infer_numpy_member, function_src)
astroid.MANAGER.register_transform(
astroid.Attribute,
astroid.inference_tip(inference_function),
functools.partial(looks_like_numpy_member, method_name),
)
43 changes: 43 additions & 0 deletions astroid/brain/brain_numpy_core_numeric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright (c) 2018-2019 hippo91 <guillaume.peillex@gmail.com>

# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER


"""Astroid hooks for numpy.core.numeric module."""

import functools
import astroid
from brain_numpy_utils import looks_like_numpy_member, infer_numpy_member


def numpy_core_numeric_transform():
return astroid.parse(
"""
# different functions defined in numeric.py
import numpy
def zeros_like(a, dtype=None, order='K', subok=True): return numpy.ndarray((0, 0))
def ones_like(a, dtype=None, order='K', subok=True): return numpy.ndarray((0, 0))
def full_like(a, fill_value, dtype=None, order='K', subok=True): return numpy.ndarray((0, 0))
"""
)


astroid.register_module_extender(
astroid.MANAGER, "numpy.core.numeric", numpy_core_numeric_transform
)


METHODS_TO_BE_INFERRED = {
"ones": """def ones(shape, dtype=None, order='C'):
return numpy.ndarray([0, 0])"""
}


for method_name, function_src in METHODS_TO_BE_INFERRED.items():
inference_function = functools.partial(infer_numpy_member, function_src)
astroid.MANAGER.register_transform(
astroid.Attribute,
astroid.inference_tip(inference_function),
functools.partial(looks_like_numpy_member, method_name),
)
Loading

0 comments on commit 33065ec

Please sign in to comment.