Codebase list astroid / 48eb29f
New upstream version 2.5 Sandro Tosi 3 years ago
146 changed file(s) with 1496 addition(s) and 1182 deletion(s). Raw diff Collapse all Expand all
00 ===================
11 astroid's ChangeLog
22 ===================
3
4 What's New in astroid 2.5?
5 ============================
6 Release Date: 2021-02-15
7
8 * Adds `attr_fset` in the `PropertyModel` class.
9
10 Fixes PyCQA/pylint#3480
11
12 * Remove support for Python 3.5.
13 * Remove the runtime dependency on ``six``. The ``six`` brain remains in
14 astroid.
15
16 Fixes PyCQA/astroid#863
17
18 * Enrich the ``brain_collection`` module so that ``__class_getitem__`` method is added to `deque` for
19 ``python`` version above 3.9.
20
21 * The ``context.path`` is now a ``dict`` and the ``context.push`` method
22 returns ``True`` if the node has been visited a certain amount of times.
23
24 Close #669
25
26 * Adds a brain for type object so that it is possible to write `type[int]` in annotation.
27
28 Fixes PyCQA/pylint#4001
29
30 * Add ``__class_getitem__`` method to ``subprocess.Popen`` brain under Python 3.9 so that it is seen as subscriptable by pylint.
31
32 Fixes PyCQA/pylint#4034
33
34
35 * Adds `degrees`, `radians`, which are `numpy ufunc` functions, in the `numpy` brain. Adds `random` function in the `numpy.random` brain.
36
37 Fixes PyCQA/pylint#3856
38
39 * Fix deprecated importlib methods
40
41 Closes #703
42
43 * Fix a crash in inference caused by `Uninferable` container elements
44
45 Close #866
46
47 * Add `python 3.9` support.
48
49 * The flat attribute of ``numpy.ndarray`` is now inferred as an ``numpy.ndarray`` itself.
50 It should be a ``numpy.flatiter`` instance, but this class is not yet available in the numpy brain.
51
52 Fixes PyCQA/pylint#3640
53
54 * Fix a bug for dunder methods inference of function objects
55
56 Fixes #819
57
58 * Fixes a bug in the signature of the ``ndarray.__or__`` method,
59 in the ``brain_numpy_ndarray.py`` module.
60
61 Fixes #815
62
63 * Fixes a to-list cast bug in ``starred_assigned_stmts`` method,
64 in the ``protocols.py` module.
65
66 * Added a brain for ``hypothesis.strategies.composite``
67
68 * The transpose of a ``numpy.ndarray`` is also a ``numpy.ndarray``
69
70 Fixes PyCQA/pylint#3387
71
72 * Added a brain for ``sqlalchemy.orm.session``
73
74 * Separate string and bytes classes patching
75
76 Fixes PyCQA/pylint#3599
77
78 * Prevent recursion error for self referential length calls
79
80 Close #777
81
82 * Added missing methods to the brain for ``mechanize``, to fix pylint false positives
83
84 Close #793
85
86 * Added more supported parameters to ``subprocess.check_output``
87
88 * Fix recursion errors with pandas
89
90 Fixes PyCQA/pylint#2843
91 Fixes PyCQA/pylint#2811
92
93 * Added exception inference for `UnicodeDecodeError`
94
95 Close PyCQA/pylint#3639
96
97 * `FunctionDef.is_generator` properly handles `yield` nodes in `If` tests
98
99 Close PyCQA/pylint#3583
100
101 * Fixed exception-chaining error messages.
102
103 * Fix failure to infer base class type with multiple inheritance and qualified names
104
105 Fixes #843
106
107 * Fix interpretation of ``six.with_metaclass`` class definitions.
108
109 Fixes #713
110
111 * Reduce memory usage of astroid's module cache.
112
113 * Remove dependency on `imp`.
114
115 Close #594
116 Close #681
117
118 * Do not crash when encountering starred assignments in enums.
119
120 Close #835
121
122 * Fix a crash in functools.partial inference when the arguments cannot be determined
123
124 Close PyCQA/pylint#3776
125
126 * Fix a crash caused by a lookup of a monkey-patched method
127
128 Close PyCQA/pylint#3686
129
130 * ``is_generator`` correctly considers `Yield` nodes in `AugAssign` nodes
131
132 This fixes a false positive with the `assignment-from-no-return` pylint check.
133
134 Close PyCQA/pylint#3904
135
136 * Corrected the parent of function type comment nodes.
137
138 These nodes used to be parented to their original ast.FunctionDef parent
139 but are now correctly parented to their astroid.FunctionDef parent.
140
141 Close PyCQA/astroid#851
142
3143
4144 What's New in astroid 2.4.2?
5145 ============================
00 Metadata-Version: 1.2
11 Name: astroid
2 Version: 2.4.2
2 Version: 2.5
33 Summary: An abstract syntax tree for Python with inference support.
44 Home-page: https://github.com/PyCQA/astroid
55 Author: Python Code Quality Authority
8686 ---------------
8787
8888 astroid 2.0 is currently available for Python 3 only. If you want Python 2
89 support, older versions of astroid will still supported until 2020.
89 support, use an older version of astroid (though note that these versions
90 are no longer supported).
9091
9192 Test
9293 ----
102103 Classifier: Topic :: Software Development :: Quality Assurance
103104 Classifier: Programming Language :: Python
104105 Classifier: Programming Language :: Python :: 3
105 Classifier: Programming Language :: Python :: 3.5
106106 Classifier: Programming Language :: Python :: 3.6
107107 Classifier: Programming Language :: Python :: 3.7
108108 Classifier: Programming Language :: Python :: 3.8
109 Classifier: Programming Language :: Python :: 3.9
109110 Classifier: Programming Language :: Python :: Implementation :: CPython
110111 Classifier: Programming Language :: Python :: Implementation :: PyPy
111 Requires-Python: >=3.5
112 Requires-Python: >=3.6
7878 ---------------
7979
8080 astroid 2.0 is currently available for Python 3 only. If you want Python 2
81 support, older versions of astroid will still supported until 2020.
81 support, use an older version of astroid (though note that these versions
82 are no longer supported).
8283
8384 Test
8485 ----
00 # Copyright (c) 2006-2013, 2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
11 # Copyright (c) 2014 Google, Inc.
22 # Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
3 # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
3 # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
44 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
55 # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
66 # Copyright (c) 2016 Moises Lopez <moylop260@vauxoo.com>
77 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
88 # Copyright (c) 2019 Nick Drozd <nicholasdrozd@gmail.com>
9 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
910
1011 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1112 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # -*- coding: utf-8 -*-
11 # Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
2 # Copyright (c) 2014-2019 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2014 Google, Inc.
44 # Copyright (c) 2015-2017 Ceridwen <ceridwenv@gmail.com>
55 # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
1313 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
1414 # Copyright (c) 2019 Uilian Ries <uilianries@gmail.com>
1515 # Copyright (c) 2019 Thomas Hisch <t.hisch@gmail.com>
16 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
17 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
18 # Copyright (c) 2020 Konrad Weihmann <kweihmann@outlook.com>
19 # Copyright (c) 2020 Felix Mölder <felix.moelder@uni-due.de>
1620 # Copyright (c) 2020 Michael <michael-k@users.noreply.github.com>
1721
1822 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2024
2125 """astroid packaging information"""
2226
23 version = "2.4.2"
27 version = "2.5"
2428 numversion = tuple(int(elem) for elem in version.split(".") if elem.isdigit())
2529
2630 extras_require = {}
2731 install_requires = [
28 "lazy_object_proxy==1.4.*",
29 "six~=1.12",
30 "wrapt~=1.11",
32 "lazy_object_proxy>=1.4.0",
33 "wrapt>=1.11,<1.13",
3134 'typed-ast>=1.4.0,<1.5;implementation_name== "cpython" and python_version<"3.8"',
3235 ]
3336
4649 "Topic :: Software Development :: Quality Assurance",
4750 "Programming Language :: Python",
4851 "Programming Language :: Python :: 3",
49 "Programming Language :: Python :: 3.5",
5052 "Programming Language :: Python :: 3.6",
5153 "Programming Language :: Python :: 3.7",
5254 "Programming Language :: Python :: 3.8",
55 "Programming Language :: Python :: 3.9",
5356 "Programming Language :: Python :: Implementation :: CPython",
5457 "Programming Language :: Python :: Implementation :: PyPy",
5558 ]
22 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
33 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
44 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
5 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
56
67 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
78 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
172173
173174 # Too many arguments given and no variable arguments.
174175 if len(self.positional_arguments) > len(funcnode.args.args):
175 if not funcnode.args.vararg:
176 if not funcnode.args.vararg and not funcnode.args.posonlyargs:
176177 raise exceptions.InferenceError(
177178 "Too many positional arguments "
178179 "passed to {func!r} that does "
291292 except exceptions.NoDefault:
292293 pass
293294 raise exceptions.InferenceError(
294 "No value found for argument {name} to " "{func!r}",
295 "No value found for argument {arg} to {func!r}",
295296 call_site=self,
296297 func=funcnode,
297298 arg=name,
00 # -*- coding: utf-8 -*-
1 # Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2014-2021 Claudiu Popa <pcmanticore@gmail.com>
22 # Copyright (c) 2014-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
33 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
44 # Copyright (c) 2015 Rene Zhang <rz99@cornell.edu>
55 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
66 # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
7 # Copyright (c) 2019-2020 Bryce Guinta <bryce.guinta@protonmail.com>
78 # Copyright (c) 2019 Stanislav Levin <slev@altlinux.org>
89 # Copyright (c) 2019 David Liu <david@cs.toronto.edu>
9 # Copyright (c) 2019 Bryce Guinta <bryce.guinta@protonmail.com>
1010 # Copyright (c) 2019 Frédéric Chapoton <fchapoton2@gmail.com>
11 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
12 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
13 # Copyright (c) 2020 Ram Rachum <ram@rachum.com>
1114
1215 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1316 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1720 from functools import partial
1821 from textwrap import dedent
1922
20 import six
2123 from astroid import (
2224 MANAGER,
2325 UseInferenceDefault,
3941
4042 OBJECT_DUNDER_NEW = "object.__new__"
4143
42
43 def _extend_str(class_node, rvalue):
44 STR_CLASS = """
45 class whatever(object):
46 def join(self, iterable):
47 return {rvalue}
48 def replace(self, old, new, count=None):
49 return {rvalue}
50 def format(self, *args, **kwargs):
51 return {rvalue}
52 def encode(self, encoding='ascii', errors=None):
53 return b''
54 def decode(self, encoding='ascii', errors=None):
55 return u''
56 def capitalize(self):
57 return {rvalue}
58 def title(self):
59 return {rvalue}
60 def lower(self):
61 return {rvalue}
62 def upper(self):
63 return {rvalue}
64 def swapcase(self):
65 return {rvalue}
66 def index(self, sub, start=None, end=None):
67 return 0
68 def find(self, sub, start=None, end=None):
69 return 0
70 def count(self, sub, start=None, end=None):
71 return 0
72 def strip(self, chars=None):
73 return {rvalue}
74 def lstrip(self, chars=None):
75 return {rvalue}
76 def rstrip(self, chars=None):
77 return {rvalue}
78 def rjust(self, width, fillchar=None):
79 return {rvalue}
80 def center(self, width, fillchar=None):
81 return {rvalue}
82 def ljust(self, width, fillchar=None):
83 return {rvalue}
84 """
85
86
87 BYTES_CLASS = """
88 class whatever(object):
89 def join(self, iterable):
90 return {rvalue}
91 def replace(self, old, new, count=None):
92 return {rvalue}
93 def decode(self, encoding='ascii', errors=None):
94 return u''
95 def capitalize(self):
96 return {rvalue}
97 def title(self):
98 return {rvalue}
99 def lower(self):
100 return {rvalue}
101 def upper(self):
102 return {rvalue}
103 def swapcase(self):
104 return {rvalue}
105 def index(self, sub, start=None, end=None):
106 return 0
107 def find(self, sub, start=None, end=None):
108 return 0
109 def count(self, sub, start=None, end=None):
110 return 0
111 def strip(self, chars=None):
112 return {rvalue}
113 def lstrip(self, chars=None):
114 return {rvalue}
115 def rstrip(self, chars=None):
116 return {rvalue}
117 def rjust(self, width, fillchar=None):
118 return {rvalue}
119 def center(self, width, fillchar=None):
120 return {rvalue}
121 def ljust(self, width, fillchar=None):
122 return {rvalue}
123 """
124
125
126 def _extend_string_class(class_node, code, rvalue):
44127 """function to extend builtin str/unicode class"""
45 code = dedent(
46 """
47 class whatever(object):
48 def join(self, iterable):
49 return {rvalue}
50 def replace(self, old, new, count=None):
51 return {rvalue}
52 def format(self, *args, **kwargs):
53 return {rvalue}
54 def encode(self, encoding='ascii', errors=None):
55 return ''
56 def decode(self, encoding='ascii', errors=None):
57 return u''
58 def capitalize(self):
59 return {rvalue}
60 def title(self):
61 return {rvalue}
62 def lower(self):
63 return {rvalue}
64 def upper(self):
65 return {rvalue}
66 def swapcase(self):
67 return {rvalue}
68 def index(self, sub, start=None, end=None):
69 return 0
70 def find(self, sub, start=None, end=None):
71 return 0
72 def count(self, sub, start=None, end=None):
73 return 0
74 def strip(self, chars=None):
75 return {rvalue}
76 def lstrip(self, chars=None):
77 return {rvalue}
78 def rstrip(self, chars=None):
79 return {rvalue}
80 def rjust(self, width, fillchar=None):
81 return {rvalue}
82 def center(self, width, fillchar=None):
83 return {rvalue}
84 def ljust(self, width, fillchar=None):
85 return {rvalue}
86 """
87 )
88128 code = code.format(rvalue=rvalue)
89129 fake = AstroidBuilder(MANAGER).string_build(code)["whatever"]
90130 for method in fake.mymethods():
105145
106146 _extend_builtins(
107147 {
108 "bytes": partial(_extend_str, rvalue="b''"),
109 "str": partial(_extend_str, rvalue="''"),
148 "bytes": partial(_extend_string_class, code=BYTES_CLASS, rvalue="b''"),
149 "str": partial(_extend_string_class, code=STR_CLASS, rvalue="''"),
110150 }
111151 )
112152
164204 if not transformed:
165205 try:
166206 inferred = next(arg.infer(context=context))
167 except (InferenceError, StopIteration):
168 raise UseInferenceDefault()
207 except (InferenceError, StopIteration) as exc:
208 raise UseInferenceDefault from exc
169209 if inferred is util.Uninferable:
170 raise UseInferenceDefault()
210 raise UseInferenceDefault
171211 transformed = transform(inferred)
172212 if not transformed or transformed is util.Uninferable:
173 raise UseInferenceDefault()
213 raise UseInferenceDefault
174214 return transformed
175215
176216
184224 # TODO: Does not handle deduplication for sets.
185225 elts = []
186226 for element in arg.elts:
227 if not element:
228 continue
187229 inferred = helpers.safe_infer(element, context=context)
188230 if inferred:
189231 evaluated_object = nodes.EvaluatedObject(
195237 if not all(isinstance(elt[0], nodes.Const) for elt in arg.items):
196238 raise UseInferenceDefault()
197239 elts = [item[0].value for item in arg.items]
198 elif isinstance(arg, nodes.Const) and isinstance(
199 arg.value, (six.string_types, six.binary_type)
200 ):
240 elif isinstance(arg, nodes.Const) and isinstance(arg.value, (str, bytes)):
201241 elts = arg.value
202242 else:
203243 return
266306 is_iterable = lambda n: isinstance(n, (nodes.List, nodes.Tuple, nodes.Set))
267307 try:
268308 inferred = next(arg.infer(context))
269 except (InferenceError, NameInferenceError):
270 raise UseInferenceDefault()
309 except (InferenceError, NameInferenceError) as exc:
310 raise UseInferenceDefault from exc
271311 if isinstance(inferred, nodes.Dict):
272312 items = inferred.items
273313 elif is_iterable(inferred):
370410 else:
371411 try:
372412 mro_pointer = next(node.args[0].infer(context=context))
373 except InferenceError:
374 raise UseInferenceDefault
413 except InferenceError as exc:
414 raise UseInferenceDefault from exc
375415 try:
376416 mro_type = next(node.args[1].infer(context=context))
377 except InferenceError:
378 raise UseInferenceDefault
417 except InferenceError as exc:
418 raise UseInferenceDefault from exc
379419
380420 if mro_pointer is util.Uninferable or mro_type is util.Uninferable:
381421 # No way we could understand this.
396436 try:
397437 obj = next(node.args[0].infer(context=context))
398438 attr = next(node.args[1].infer(context=context))
399 except InferenceError:
400 raise UseInferenceDefault
439 except InferenceError as exc:
440 raise UseInferenceDefault from exc
401441
402442 if obj is util.Uninferable or attr is util.Uninferable:
403443 # If one of the arguments is something we can't infer,
405445 # which is unknown.
406446 return util.Uninferable, util.Uninferable
407447
408 is_string = isinstance(attr, nodes.Const) and isinstance(
409 attr.value, six.string_types
410 )
448 is_string = isinstance(attr, nodes.Const) and isinstance(attr.value, str)
411449 if not is_string:
412450 raise UseInferenceDefault
413451
436474 # Try to infer the default and return it instead.
437475 try:
438476 return next(node.args[2].infer(context=context))
439 except InferenceError:
440 raise UseInferenceDefault
477 except InferenceError as exc:
478 raise UseInferenceDefault from exc
441479
442480 raise UseInferenceDefault
443481
504542 getter = node.args[0]
505543 try:
506544 inferred = next(getter.infer(context=context))
507 except InferenceError:
508 raise UseInferenceDefault
545 except InferenceError as exc:
546 raise UseInferenceDefault from exc
509547
510548 if not isinstance(inferred, (nodes.FunctionDef, nodes.Lambda)):
511549 raise UseInferenceDefault
672710 class_container = _class_or_tuple_to_container(
673711 class_or_tuple_node, context=context
674712 )
675 except InferenceError:
676 raise UseInferenceDefault
713 except InferenceError as exc:
714 raise UseInferenceDefault from exc
677715 try:
678716 isinstance_bool = helpers.object_isinstance(obj_node, class_container, context)
679717 except AstroidTypeError as exc:
680 raise UseInferenceDefault("TypeError: " + str(exc))
718 raise UseInferenceDefault("TypeError: " + str(exc)) from exc
681719 except MroError as exc:
682720 raise UseInferenceDefault from exc
683721 if isinstance_bool is util.Uninferable:
720758 "({len}) given".format(len=len(call.positional_arguments))
721759 )
722760 [argument_node] = call.positional_arguments
761
723762 try:
724763 return nodes.Const(helpers.object_len(argument_node, context=context))
725764 except (AstroidTypeError, InferenceError) as exc:
00 # -*- coding: utf-8 -*-
1 # Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
22 # Copyright (c) 2016-2017 Łukasz Rogalski <rogalski.91@gmail.com>
33 # Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com>
44 # Copyright (c) 2018 Ioana Tagirta <ioana.tagirta@gmail.com>
55 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
6 # Copyright (c) 2020-2021 hippo91 <guillaume.peillex@gmail.com>
67
78 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
89 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
910 import sys
1011
1112 import astroid
13
14
15 PY39 = sys.version_info >= (3, 9)
1216
1317
1418 def _collections_transform():
6064 def __mul__(self, other): pass
6165 def __imul__(self, other): pass
6266 def __rmul__(self, other): pass"""
67 if PY39:
68 base_deque_class += """
69 @classmethod
70 def __class_getitem__(self, item): pass"""
6371 return base_deque_class
6472
6573
0 # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2015 raylu <lurayl@gmail.com>
22 # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
3 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # Copyright (c) 2017-2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2017-2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
2 # Copyright (c) 2020 Karthikeyan Singaravelan <tir.karthi@gmail.com>
13
24 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
35 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
4 import collections
6 import collections.abc
57 import sys
68
79 import astroid
1820 new_node = cls(**init_params)
1921 if hasattr(node, "postinit") and _astroid_fields:
2022 for param, child in postinit_params.items():
21 if child and not isinstance(child, collections.Sequence):
23 if child and not isinstance(child, collections.abc.Sequence):
2224 cloned_child = _clone_node_with_lineno(
2325 node=child, lineno=new_node.lineno, parent=new_node
2426 )
8585
8686 # Determine if the passed keywords into the callsite are supported
8787 # by the wrapped function.
88 function_parameters = chain(
89 inferred_wrapped_function.args.args or (),
90 inferred_wrapped_function.args.posonlyargs or (),
91 inferred_wrapped_function.args.kwonlyargs or (),
92 )
88 if not inferred_wrapped_function.args:
89 function_parameters = []
90 else:
91 function_parameters = chain(
92 inferred_wrapped_function.args.args or (),
93 inferred_wrapped_function.args.posonlyargs or (),
94 inferred_wrapped_function.args.kwonlyargs or (),
95 )
9396 parameter_names = set(
9497 param.name
9598 for param in function_parameters
11 # Copyright (c) 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
22 # Copyright (c) 2014 Google, Inc.
33 # Copyright (c) 2014 Cole Robinson <crobinso@redhat.com>
4 # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
4 # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
55 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
66 # Copyright (c) 2015 David Shea <dshea@redhat.com>
77 # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
88 # Copyright (c) 2016 Giuseppe Scrivano <gscrivan@redhat.com>
99 # Copyright (c) 2018 Christoph Reiter <reiter.christoph@gmail.com>
1010 # Copyright (c) 2019 Philipp Hörist <philipp@hoerist.com>
11 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
1112
1213 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1314 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2018 David Poirier <david-poirier-csn@users.noreply.github.com>
22 # Copyright (c) 2018 wgehalo <wgehalo@gmail.com>
33 # Copyright (c) 2018 Ioana Tagirta <ioana.tagirta@gmail.com>
4 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
5 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
46
57 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
68 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
79 import sys
8
9 import six
1010
1111 import astroid
1212
5454 {"blake2b": blake2b_signature, "blake2s": blake2s_signature}
5555 )
5656 classes = "".join(
57 template
58 % {
59 "name": hashfunc,
60 "digest": 'b""' if six.PY3 else '""',
61 "signature": signature,
62 }
57 template % {"name": hashfunc, "digest": 'b""', "signature": signature}
6358 for hashfunc, signature in algorithms_with_signature.items()
6459 )
6560 return astroid.parse(classes)
0 # Copyright (c) 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2019-2020 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
2 """
3 Astroid hook for the Hypothesis library.
4
5 Without this hook pylint reports no-value-for-parameter for use of strategies
6 defined using the `@hypothesis.strategies.composite` decorator. For example:
7
8 from hypothesis import strategies as st
9
10 @st.composite
11 def a_strategy(draw):
12 return draw(st.integers())
13
14 a_strategy()
15
16 """
17
18 import astroid
19
20 COMPOSITE_NAMES = (
21 "composite",
22 "st.composite",
23 "strategies.composite",
24 "hypothesis.strategies.composite",
25 )
26
27
28 def is_decorated_with_st_composite(node):
29 """Return True if a decorated node has @st.composite applied."""
30 if node.decorators and node.args.args and node.args.args[0].name == "draw":
31 for decorator_attribute in node.decorators.nodes:
32 if decorator_attribute.as_string() in COMPOSITE_NAMES:
33 return True
34 return False
35
36
37 def remove_draw_parameter_from_composite_strategy(node):
38 """Given that the FunctionDef is decorated with @st.composite, remove the
39 first argument (`draw`) - it's always supplied by Hypothesis so we don't
40 need to emit the no-value-for-parameter lint.
41 """
42 del node.args.args[0]
43 del node.args.annotations[0]
44 del node.args.type_comment_args[0]
45 return node
46
47
48 astroid.MANAGER.register_transform(
49 node_class=astroid.FunctionDef,
50 transform=remove_draw_parameter_from_composite_strategy,
51 predicate=is_decorated_with_st_composite,
52 )
0 # Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # Copyright (c) 2012-2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
11 # Copyright (c) 2014 Google, Inc.
2 # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
4 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
5 # Copyright (c) 2020 Peter Kolbus <peter.kolbus@gmail.com>
46
57 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
68 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1416 """
1517
1618 class Browser(object):
19 def __getattr__(self, name):
20 return None
21 def __getitem__(self, name):
22 return None
23 def __setitem__(self, name, val):
24 return None
25 def back(self, n=1):
26 return None
27 def clear_history(self):
28 return None
29 def click(self, *args, **kwds):
30 return None
31 def click_link(self, link=None, **kwds):
32 return None
33 def close(self):
34 return None
35 def encoding(self):
36 return None
37 def find_link(self, text=None, text_regex=None, name=None, name_regex=None, url=None, url_regex=None, tag=None, predicate=None, nr=0):
38 return None
39 def follow_link(self, link=None, **kwds):
40 return None
41 def forms(self):
42 return None
43 def geturl(self):
44 return None
45 def global_form(self):
46 return None
47 def links(self, **kwds):
48 return None
49 def open_local_file(self, filename):
50 return None
1751 def open(self, url, data=None, timeout=None):
1852 return None
1953 def open_novisit(self, url, data=None, timeout=None):
2054 return None
2155 def open_local_file(self, filename):
2256 return None
23
57 def reload(self):
58 return None
59 def response(self):
60 return None
61 def select_form(self, name=None, predicate=None, nr=None, **attrs):
62 return None
63 def set_cookie(self, cookie_string):
64 return None
65 def set_handle_referer(self, handle):
66 return None
67 def set_header(self, header, value=None):
68 return None
69 def set_html(self, html, url="http://example.com/"):
70 return None
71 def set_response(self, response):
72 return None
73 def set_simple_cookie(self, name, value, domain, path='/'):
74 return None
75 def submit(self, *args, **kwds):
76 return None
77 def title(self):
78 return None
79 def viewing_html(self):
80 return None
81 def visit_response(self, response, request=None):
82 return None
2483 """
2584 )
2685
0 # Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
2 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
3 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
24
35 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
46 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
5355 import array
5456 import threading
5557 import multiprocessing.pool as pool
56
57 import six
58 import queue
5859
5960 class Namespace(object):
6061 pass
7576 return array.array(typecode, sequence)
7677
7778 class SyncManager(object):
78 Queue = JoinableQueue = six.moves.queue.Queue
79 Queue = JoinableQueue = queue.Queue
7980 Event = threading.Event
8081 RLock = threading.RLock
8182 BoundedSemaphore = threading.BoundedSemaphore
1212 # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
1313 # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
1414 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
15 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
16 # Copyright (c) 2020 Ram Rachum <ram@rachum.com>
1517
1618 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1719 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
5052 raise UseInferenceDefault()
5153 else:
5254 return value
53 except StopIteration:
54 raise InferenceError()
55 except StopIteration as exc:
56 raise InferenceError from exc
5557
5658
5759 def _find_func_form_arguments(node, context):
8789 name, names = _find_func_form_arguments(node, context)
8890 try:
8991 attributes = names.value.replace(",", " ").split()
90 except AttributeError:
92 except AttributeError as exc:
9193 if not enum:
9294 attributes = [
9395 _infer_first(const, context).value for const in names.elts
116118 _infer_first(const, context).value for const in names.elts
117119 ]
118120 else:
119 raise AttributeError
121 raise AttributeError from exc
120122 if not attributes:
121 raise AttributeError
122 except (AttributeError, exceptions.InferenceError):
123 raise UseInferenceDefault()
123 raise AttributeError from exc
124 except (AttributeError, exceptions.InferenceError) as exc:
125 raise UseInferenceDefault from exc
124126
125127 attributes = [attr for attr in attributes if " " not in attr]
126128
311313 if any(not isinstance(value, nodes.AssignName) for value in values):
312314 continue
313315
314 targets = []
315316 stmt = values[0].statement()
316317 if isinstance(stmt, nodes.Assign):
317318 if isinstance(stmt.targets[0], nodes.Tuple):
335336
336337 new_targets = []
337338 for target in targets:
339 if isinstance(target, nodes.Starred):
340 continue
338341 # Replace all the assignments with our mocked class.
339342 classdef = dedent(
340343 """
398401 return iter((generated_class_node,))
399402
400403
404 def infer_typing_namedtuple_function(node, context=None):
405 """
406 Starting with python3.9, NamedTuple is a function of the typing module.
407 The class NamedTuple is build dynamically through a call to `type` during
408 initialization of the `_NamedTuple` variable.
409 """
410 klass = extract_node(
411 """
412 from typing import _NamedTuple
413 _NamedTuple
414 """
415 )
416 return klass.infer(context)
417
418
401419 def infer_typing_namedtuple(node, context=None):
402420 """Infer a typing.NamedTuple(...) call."""
403421 # This is essentially a namedtuple with different arguments
404422 # so we extract the args and infer a named tuple.
405423 try:
406424 func = next(node.func.infer())
407 except InferenceError:
408 raise UseInferenceDefault
425 except InferenceError as exc:
426 raise UseInferenceDefault from exc
409427
410428 if func.qname() != "typing.NamedTuple":
411429 raise UseInferenceDefault
450468 nodes.ClassDef, inference_tip(infer_typing_namedtuple_class), _has_namedtuple_base
451469 )
452470 MANAGER.register_transform(
471 nodes.FunctionDef,
472 inference_tip(infer_typing_namedtuple_function),
473 lambda node: node.name == "NamedTuple" and node.parent.name == "typing",
474 )
475 MANAGER.register_transform(
453476 nodes.Call, inference_tip(infer_typing_namedtuple), _looks_like_typing_namedtuple
454477 )
0 # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
2 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
23
34 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
45 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
0 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
0 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
0 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1920 # different types defined in numerictypes.py
2021 class generic(object):
2122 def __init__(self, value):
22 self.T = None
23 self.T = np.ndarray([0, 0])
2324 self.base = None
2425 self.data = None
2526 self.dtype = None
2627 self.flags = None
27 self.flat = None
28 # Should be a numpy.flatiter instance but not available for now
29 # Putting an array instead so that iteration and indexing are authorized
30 self.flat = np.ndarray([0, 0])
2831 self.imag = None
2932 self.itemsize = None
3033 self.nbytes = None
0 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
0 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
45
5
6 #  Note: starting with version 1.18 numpy module has `__getattr__` method which prevent `pylint` to emit `no-member` message for
7 #  all numpy's attributes. (see pylint's module typecheck in `_emit_no_member` function)
68 """Astroid hooks for numpy.core.umath module."""
79
810 import astroid
7577 conjugate = FakeUfuncOneArg()
7678 cosh = FakeUfuncOneArg()
7779 deg2rad = FakeUfuncOneArg()
80 degrees = FakeUfuncOneArg()
7881 exp2 = FakeUfuncOneArg()
7982 expm1 = FakeUfuncOneArg()
8083 fabs = FakeUfuncOneArg()
8992 negative = FakeUfuncOneArg()
9093 positive = FakeUfuncOneArg()
9194 rad2deg = FakeUfuncOneArg()
95 radians = FakeUfuncOneArg()
9296 reciprocal = FakeUfuncOneArg()
9397 rint = FakeUfuncOneArg()
9498 sign = FakeUfuncOneArg()
101105 trunc = FakeUfuncOneArg()
102106
103107 # Two args functions with optional kwargs
108 add = FakeUfuncTwoArgs()
104109 bitwise_and = FakeUfuncTwoArgs()
105110 bitwise_or = FakeUfuncTwoArgs()
106111 bitwise_xor = FakeUfuncTwoArgs()
128133 logical_xor = FakeUfuncTwoArgs()
129134 maximum = FakeUfuncTwoArgs()
130135 minimum = FakeUfuncTwoArgs()
136 multiply = FakeUfuncTwoArgs()
131137 nextafter = FakeUfuncTwoArgs()
132138 not_equal = FakeUfuncTwoArgs()
133139 power = FakeUfuncTwoArgs()
0 # Copyright (c) 2015-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2015-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2017-2020 hippo91 <guillaume.peillex@gmail.com>
33
1616 class ndarray(object):
1717 def __init__(self, shape, dtype=float, buffer=None, offset=0,
1818 strides=None, order=None):
19 self.T = None
19 self.T = numpy.ndarray([0, 0])
2020 self.base = None
2121 self.ctypes = None
2222 self.data = None
2323 self.dtype = None
2424 self.flags = None
25 self.flat = None
25 # Should be a numpy.flatiter instance but not available for now
26 # Putting an array instead so that iteration and indexing are authorized
27 self.flat = np.ndarray([0, 0])
2628 self.imag = np.ndarray([0, 0])
2729 self.itemsize = None
2830 self.nbytes = None
7072 def __mul__(self, value): return numpy.ndarray([0, 0])
7173 def __ne__(self, value): return numpy.ndarray([0, 0])
7274 def __neg__(self): return numpy.ndarray([0, 0])
73 def __or__(self): return numpy.ndarray([0, 0])
75 def __or__(self, value): return numpy.ndarray([0, 0])
7476 def __pos__(self): return numpy.ndarray([0, 0])
7577 def __pow__(self): return numpy.ndarray([0, 0])
7678 def __repr__(self): return str()
0 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
0 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
4344 import numpy
4445 return numpy.ndarray((1,1))
4546 def randn(*args): return uninferable
47 def random(size=None): return uninferable
4648 def random_integers(low, high=None, size=None): return uninferable
4749 def random_sample(size=None): return uninferable
4850 def rayleigh(scale=1.0, size=None): return uninferable
00 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2019 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2019-2020 Claudiu Popa <pcmanticore@gmail.com>
22
33 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
44 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # Copyright (c) 2014-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2014-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2014 Jeff Quast <contact@jeffquast.com>
22 # Copyright (c) 2014 Google, Inc.
33 # Copyright (c) 2016 Florian Bruhin <me@the-compiler.org>
44 # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
5 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
56
67 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
78 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2017 Roy Wright <roy@wright.org>
33 # Copyright (c) 2018 Ashley Whetter <ashley@awhetter.co.uk>
44 # Copyright (c) 2019 Antoine Boellinger <aboellinger@hotmail.com>
5 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
56
67 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
78 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
4646
4747 try:
4848 elts = random.sample(inferred_sequence.elts, length.value)
49 except ValueError:
50 raise astroid.UseInferenceDefault
49 except ValueError as exc:
50 raise astroid.UseInferenceDefault from exc
5151
5252 new_node = astroid.List(
5353 lineno=node.lineno, col_offset=node.col_offset, parent=node.scope()
00 # Copyright (c) 2019 Valentin Valls <valentin.valls@esrf.fr>
1 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
2 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
13
24 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
35 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # Copyright (c) 2014-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
3 # Copyright (c) 2020-2021 hippo91 <guillaume.peillex@gmail.com>
4 # Copyright (c) 2020 Ram Rachum <ram@rachum.com>
5 # Copyright (c) 2021 Francis Charette Migneault <francis.charette.migneault@gmail.com>
36
47 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
58 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
2023
2124
2225 SIX_ADD_METACLASS = "six.add_metaclass"
26 SIX_WITH_METACLASS = "six.with_metaclass"
2327
2428
2529 def _indent(text, prefix, predicate=None):
144148 attribute = modname[start_index:].lstrip(".").replace(".", "_")
145149 try:
146150 import_attr = module.getattr(attribute)[0]
147 except AttributeInferenceError:
148 raise AstroidBuildingError(modname=modname)
151 except AttributeInferenceError as exc:
152 raise AstroidBuildingError(modname=modname) from exc
149153 if isinstance(import_attr, nodes.Import):
150154 submodule = MANAGER.ast_from_module_name(import_attr.names[0][0])
151155 return submodule
188192 return node
189193
190194
195 def _looks_like_nested_from_six_with_metaclass(node):
196 if len(node.bases) != 1:
197 return False
198 base = node.bases[0]
199 if not isinstance(base, nodes.Call):
200 return False
201 try:
202 if hasattr(base.func, "expr"):
203 # format when explicit 'six.with_metaclass' is used
204 mod = base.func.expr.name
205 func = base.func.attrname
206 func = "{}.{}".format(mod, func)
207 else:
208 # format when 'with_metaclass' is used directly (local import from six)
209 # check reference module to avoid 'with_metaclass' name clashes
210 mod = base.parent.parent
211 import_from = mod.locals["with_metaclass"][0]
212 func = "{}.{}".format(import_from.modname, base.func.name)
213 except (AttributeError, KeyError, IndexError):
214 return False
215 return func == SIX_WITH_METACLASS
216
217
218 def transform_six_with_metaclass(node):
219 """Check if the given class node is defined with *six.with_metaclass*
220
221 If so, inject its argument as the metaclass of the underlying class.
222 """
223 call = node.bases[0]
224 node._metaclass = call.args[0]
225
226
191227 register_module_extender(MANAGER, "six", six_moves_transform)
192228 register_module_extender(
193229 MANAGER, "requests.packages.urllib3.packages.six", six_moves_transform
198234 transform_six_add_metaclass,
199235 _looks_like_decorated_with_six_add_metaclass,
200236 )
237 MANAGER.register_transform(
238 nodes.ClassDef,
239 transform_six_with_metaclass,
240 _looks_like_nested_from_six_with_metaclass,
241 )
0 import astroid
1
2
3 def _session_transform():
4 return astroid.parse(
5 """
6 from sqlalchemy.orm.session import Session
7
8 class sessionmaker:
9 def __init__(
10 self,
11 bind=None,
12 class_=Session,
13 autoflush=True,
14 autocommit=False,
15 expire_on_commit=True,
16 info=None,
17 **kw
18 ):
19 return
20
21 def __call__(self, **local_kw):
22 return Session()
23
24 def configure(self, **new_kw):
25 return
26
27 return Session()
28 """
29 )
30
31
32 astroid.register_module_extender(
33 astroid.MANAGER, "sqlalchemy.orm.session", _session_transform
34 )
0 # Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2019 Benjamin Elven <25181435+S3ntinelX@users.noreply.github.com>
3 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
22 # Copyright (c) 2018 Peter Talley <peterctalley@gmail.com>
33 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
44 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
5 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
6 # Copyright (c) 2020 Peter Pentchev <roam@ringlet.net>
7 # Copyright (c) 2021 Damien Baty <damien@damienbaty.com>
58
69 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
710 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1215 import astroid
1316
1417
18 PY39 = sys.version_info >= (3, 9)
1519 PY37 = sys.version_info >= (3, 7)
1620 PY36 = sys.version_info >= (3, 6)
1721
7680 preexec_fn=None,
7781 pass_fds=(),
7882 input=None,
83 bufsize=0,
84 executable=None,
85 close_fds=False,
86 startupinfo=None,
87 creationflags=0,
7988 start_new_session=False
8089 ):
8190 """.strip()
96105 preexec_fn=None,
97106 pass_fds=(),
98107 input=None,
108 bufsize=0,
109 executable=None,
110 close_fds=False,
111 startupinfo=None,
112 creationflags=0,
99113 start_new_session=False
100114 ):
101115 """.strip()
135149 "py3_args": py3_args,
136150 }
137151 )
152 if PY39:
153 code += """
154 @classmethod
155 def __class_getitem__(cls, item):
156 pass
157 """
138158
139159 init_lines = textwrap.dedent(init).splitlines()
140160 indented_init = "\n".join(" " * 4 + line for line in init_lines)
00 # -*- coding: utf-8 -*-
1 # Copyright (c) 2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
22 # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
3 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # -*- coding: utf-8 -*-
1 """
2 Astroid hooks for type support.
3
4 Starting from python3.9, type object behaves as it had __class_getitem__ method.
5 However it was not possible to simply add this method inside type's body, otherwise
6 all types would also have this method. In this case it would have been possible
7 to write str[int].
8 Guido Van Rossum proposed a hack to handle this in the interpreter:
9 https://github.com/python/cpython/blob/master/Objects/abstract.c#L186-L189
10
11 This brain follows the same logic. It is no wise to add permanently the __class_getitem__ method
12 to the type object. Instead we choose to add it only in the case of a subscript node
13 which inside name node is type.
14 Doing this type[int] is allowed whereas str[int] is not.
15
16 Thanks to Lukasz Langa for fruitful discussion.
17 """
18 import sys
19
20 from astroid import MANAGER, extract_node, inference_tip, nodes
21
22
23 PY39 = sys.version_info >= (3, 9)
24
25
26 def _looks_like_type_subscript(node):
27 """
28 Try to figure out if a Name node is used inside a type related subscript
29
30 :param node: node to check
31 :type node: astroid.node_classes.NodeNG
32 :return: true if the node is a Name node inside a type related subscript
33 :rtype: bool
34 """
35 if isinstance(node, nodes.Name) and isinstance(node.parent, nodes.Subscript):
36 return node.name == "type"
37 return False
38
39
40 def infer_type_sub(node, context=None):
41 """
42 Infer a type[...] subscript
43
44 :param node: node to infer
45 :type node: astroid.node_classes.NodeNG
46 :param context: inference context
47 :type context: astroid.context.InferenceContext
48 :return: the inferred node
49 :rtype: nodes.NodeNG
50 """
51 class_src = """
52 class type:
53 def __class_getitem__(cls, key):
54 return cls
55 """
56 node = extract_node(class_src)
57 return node.infer(context=context)
58
59
60 if PY39:
61 MANAGER.register_transform(
62 nodes.Name, inference_tip(infer_type_sub), _looks_like_type_subscript
63 )
0 # Copyright (c) 2017-2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2017-2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
12
23 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
34 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # -*- coding: utf-8 -*-
11 # Copyright (c) 2006-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
22 # Copyright (c) 2013 Phil Schaf <flying-sheep@web.de>
3 # Copyright (c) 2014-2019 Claudiu Popa <pcmanticore@gmail.com>
3 # Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
44 # Copyright (c) 2014-2015 Google, Inc.
55 # Copyright (c) 2014 Alexander Presnyakov <flagist0@gmail.com>
66 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
77 # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
88 # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
99 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
10 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
1011
1112 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1213 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
0 # Copyright (c) 2015-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2015-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
33 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
4 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
5 # Copyright (c) 2020 Bryce Guinta <bryce.guinta@protonmail.com>
46
57 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
68 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
2729 "extra_context",
2830 )
2931
32 maximum_path_visit = 3
33
3034 def __init__(self, path=None, inferred=None):
31 self.path = path or set()
35 self.path = path or dict()
3236 """
3337 :type: set(tuple(NodeNG, optional(str)))
3438
8589 Allows one to see if the given node has already
8690 been looked at for this inference context"""
8791 name = self.lookupname
88 if (node, name) in self.path:
92 if self.path.get((node, name), 0) >= self.maximum_path_visit:
8993 return True
9094
91 self.path.add((node, name))
95 self.path[(node, name)] = self.path.setdefault((node, name), 0) + 1
9296 return False
9397
9498 def clone(self):
104108 clone.extra_context = self.extra_context
105109 return clone
106110
107 def cache_generator(self, key, generator):
108 """Cache result of generator into dictionary
109
110 Used to cache inference results"""
111 results = []
112 for result in generator:
113 results.append(result)
114 yield result
115
116 self.inferred[key] = tuple(results)
117
118111 @contextlib.contextmanager
119112 def restore_path(self):
120 path = set(self.path)
113 path = dict(self.path)
121114 yield
122115 self.path = path
123116
0 # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
33 # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
66 # Copyright (c) 2018 Ashley Whetter <ashley@awhetter.co.uk>
77 # Copyright (c) 2018 HoverHell <hoverhell@gmail.com>
88 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
9 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
10 # Copyright (c) 2020 Ram Rachum <ram@rachum.com>
911
1012 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1113 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
133135 # generator is empty
134136 if error.args:
135137 # pylint: disable=not-a-mapping
136 raise exceptions.InferenceError(**error.args[0])
138 raise exceptions.InferenceError(**error.args[0]) from error
137139 raise exceptions.InferenceError(
138140 "StopIteration raised without any error information."
139 )
141 ) from error
140142
141143 yield from generator
00 # Copyright (c) 2007, 2009-2010, 2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
11 # Copyright (c) 2014 Google, Inc.
2 # Copyright (c) 2015-2018 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2015-2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
44 # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
55 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
6 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
67
78 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
89 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # Copyright (c) 2015-2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
3 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
4 # Copyright (c) 2020 Simon Hewitt <si@sjhewitt.co.uk>
5 # Copyright (c) 2020 Bryce Guinta <bryce.guinta@protonmail.com>
6 # Copyright (c) 2020 Ram Rachum <ram@rachum.com>
37
48 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
59 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
189193 return False
190194 try:
191195 return type1 in type2.mro()[:-1]
192 except exceptions.MroError:
196 except exceptions.MroError as e:
193197 # The MRO is invalid.
194 raise exceptions._NonDeducibleTypeHierarchy
198 raise exceptions._NonDeducibleTypeHierarchy from e
195199
196200
197201 def is_subtype(type1, type2):
236240 :raises AstroidTypeError: If an invalid node is returned
237241 from __len__ method or no __len__ method exists
238242 :raises InferenceError: If the given node cannot be inferred
239 or if multiple nodes are inferred
243 or if multiple nodes are inferred or if the code executed in python
244 would result in a infinite recursive check for length
240245 :rtype int: Integer length of node
241246 """
242247 # pylint: disable=import-outside-toplevel; circular import
243248 from astroid.objects import FrozenSet
244249
245250 inferred_node = safe_infer(node, context=context)
251
252 # prevent self referential length calls from causing a recursion error
253 # see https://github.com/PyCQA/astroid/issues/777
254 node_frame = node.frame()
255 if (
256 isinstance(node_frame, scoped_nodes.FunctionDef)
257 and node_frame.name == "__len__"
258 and inferred_node is not None
259 and inferred_node._proxied == node_frame.parent
260 ):
261 message = (
262 "Self referential __len__ function will "
263 "cause a RecursionError on line {} of {}".format(
264 node.lineno, node.root().file
265 )
266 )
267 raise exceptions.InferenceError(message)
268
246269 if inferred_node is None or inferred_node is util.Uninferable:
247270 raise exceptions.InferenceError(node=node)
248271 if isinstance(inferred_node, nodes.Const) and isinstance(
260283
261284 try:
262285 len_call = next(node_type.igetattr("__len__", context=context))
263 except exceptions.AttributeInferenceError:
286 except exceptions.AttributeInferenceError as e:
264287 raise exceptions.AstroidTypeError(
265288 "object of type '{}' has no len()".format(node_type.pytype())
266 )
289 ) from e
267290
268291 result_of_len = next(len_call.infer_call_result(node, context))
269292 if (
0 # Copyright (c) 2016-2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2016-2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
22 # Copyright (c) 2017 Chris Philip <chrisp533@gmail.com>
33 # Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com>
66 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
77 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
88 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
9 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
10 # Copyright (c) 2020 Peter Kolbus <peter.kolbus@gmail.com>
11 # Copyright (c) 2020 Raphael Gaschignard <raphael@rtpg.co>
912
1013 import abc
1114 import collections
1215 import distutils
1316 import enum
14 import imp
1517 import os
1618 import sys
1719 import zipimport
1820
19 try:
20 import importlib.machinery
21
22 _HAS_MACHINERY = True
23 except ImportError:
24 _HAS_MACHINERY = False
21 import importlib.machinery
2522
2623 try:
2724 from functools import lru_cache
3633 "PY_CODERESOURCE PY_COMPILED PY_FROZEN PY_RESOURCE "
3734 "PY_SOURCE PY_ZIPMODULE PY_NAMESPACE",
3835 )
39 _ImpTypes = {
40 imp.C_BUILTIN: ModuleType.C_BUILTIN,
41 imp.C_EXTENSION: ModuleType.C_EXTENSION,
42 imp.PKG_DIRECTORY: ModuleType.PKG_DIRECTORY,
43 imp.PY_COMPILED: ModuleType.PY_COMPILED,
44 imp.PY_FROZEN: ModuleType.PY_FROZEN,
45 imp.PY_SOURCE: ModuleType.PY_SOURCE,
46 }
47 if hasattr(imp, "PY_RESOURCE"):
48 _ImpTypes[imp.PY_RESOURCE] = ModuleType.PY_RESOURCE
49 if hasattr(imp, "PY_CODERESOURCE"):
50 _ImpTypes[imp.PY_CODERESOURCE] = ModuleType.PY_CODERESOURCE
51
52
53 def _imp_type_to_module_type(imp_type):
54 return _ImpTypes[imp_type]
5536
5637
5738 _ModuleSpec = collections.namedtuple(
11394 """Get a list of extra paths where this finder can search."""
11495
11596
116 class ImpFinder(Finder):
117 """A finder based on the imp module."""
118
119 def find_module(self, modname, module_parts, processed, submodule_path):
97 class ImportlibFinder(Finder):
98 """A finder based on the importlib module."""
99
100 _SUFFIXES = (
101 [(s, ModuleType.C_EXTENSION) for s in importlib.machinery.EXTENSION_SUFFIXES]
102 + [(s, ModuleType.PY_SOURCE) for s in importlib.machinery.SOURCE_SUFFIXES]
103 + [(s, ModuleType.PY_COMPILED) for s in importlib.machinery.BYTECODE_SUFFIXES]
104 )
105
106 def find_module(self, modname, module_parts, processed, submodule_path):
107 if not isinstance(modname, str):
108 raise TypeError("'modname' must be a str, not {}".format(type(modname)))
120109 if submodule_path is not None:
121110 submodule_path = list(submodule_path)
122 try:
123 stream, mp_filename, mp_desc = imp.find_module(modname, submodule_path)
124 except ImportError:
125 return None
126
127 # Close resources.
128 if stream:
129 stream.close()
130
131 return ModuleSpec(
132 name=modname,
133 location=mp_filename,
134 module_type=_imp_type_to_module_type(mp_desc[2]),
135 )
111 else:
112 try:
113 spec = importlib.util.find_spec(modname)
114 if spec:
115 if spec.loader is importlib.machinery.BuiltinImporter:
116 return ModuleSpec(
117 name=modname,
118 location=None,
119 module_type=ModuleType.C_BUILTIN,
120 )
121 if spec.loader is importlib.machinery.FrozenImporter:
122 return ModuleSpec(
123 name=modname,
124 location=None,
125 module_type=ModuleType.PY_FROZEN,
126 )
127 except ValueError:
128 pass
129 submodule_path = sys.path
130
131 for entry in submodule_path:
132 package_directory = os.path.join(entry, modname)
133 for suffix in [".py", importlib.machinery.BYTECODE_SUFFIXES[0]]:
134 package_file_name = "__init__" + suffix
135 file_path = os.path.join(package_directory, package_file_name)
136 if os.path.isfile(file_path):
137 return ModuleSpec(
138 name=modname,
139 location=package_directory,
140 module_type=ModuleType.PKG_DIRECTORY,
141 )
142 for suffix, type_ in ImportlibFinder._SUFFIXES:
143 file_name = modname + suffix
144 file_path = os.path.join(entry, file_name)
145 if os.path.isfile(file_path):
146 return ModuleSpec(
147 name=modname, location=file_path, module_type=type_
148 )
149 return None
136150
137151 def contribute_to_path(self, spec, processed):
138152 if spec.location is None:
158172 return path
159173
160174
161 class ExplicitNamespacePackageFinder(ImpFinder):
175 class ExplicitNamespacePackageFinder(ImportlibFinder):
162176 """A finder for the explicit namespace packages, generated through pkg_resources."""
163177
164178 def find_module(self, modname, module_parts, processed, submodule_path):
228242 return None
229243
230244
231 _SPEC_FINDERS = (ImpFinder, ZipFinder)
232 if _HAS_MACHINERY:
233 _SPEC_FINDERS += (PathSpecFinder,)
234 _SPEC_FINDERS += (ExplicitNamespacePackageFinder,)
245 _SPEC_FINDERS = (
246 ImportlibFinder,
247 ZipFinder,
248 PathSpecFinder,
249 ExplicitNamespacePackageFinder,
250 )
235251
236252
237253 def _is_setuptools_namespace(location):
239255 with open(os.path.join(location, "__init__.py"), "rb") as stream:
240256 data = stream.read(4096)
241257 except IOError:
242 pass
258 return None
243259 else:
244260 extend_path = b"pkgutil" in data and b"extend_path" in data
245261 declare_namespace = (
256272
257273
258274 def _precache_zipimporters(path=None):
275 """
276 For each path that has not been already cached
277 in the sys.path_importer_cache, create a new zipimporter
278 instance and add it into the cache.
279 Return a dict associating all paths, stored in the cache, to corresponding
280 zipimporter instances.
281
282 :param path: paths that has to be added into the cache
283 :return: association between paths stored in the cache and zipimporter instances
284 """
259285 pic = sys.path_importer_cache
260286
261287 # When measured, despite having the same complexity (O(n)),
271297 pic[entry_path] = zipimport.zipimporter(entry_path)
272298 except zipimport.ZipImportError:
273299 continue
274 return pic
300 return {
301 key: value
302 for key, value in pic.items()
303 if isinstance(value, zipimport.zipimporter)
304 }
275305
276306
277307 def _search_zip(modpath, pic):
00 # -*- coding: utf-8 -*-
1 # Copyright (c) 2016-2019 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2016-2020 Claudiu Popa <pcmanticore@gmail.com>
22 # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
33 # Copyright (c) 2017-2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
44 # Copyright (c) 2017 Ceridwen <ceridwenv@gmail.com>
55 # Copyright (c) 2017 Calen Pennington <cale@edx.org>
66 # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
77 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
8 # Copyright (c) 2020-2021 hippo91 <guillaume.peillex@gmail.com>
89 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
910 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1011 """
3132 import os
3233 import types
3334 from functools import lru_cache
35 from typing import Optional
3436
3537 import astroid
3638 from astroid import context as contextmod
3739 from astroid import exceptions
3840 from astroid import node_classes
41 from astroid import util
42
43 # Prevents circular imports
44 objects = util.lazy_import("objects")
3945
4046
4147 IMPL_PREFIX = "attr_"
323329 doc=func.doc,
324330 lineno=func.lineno,
325331 col_offset=func.col_offset,
332 parent=func.parent,
326333 )
327334 # pylint: disable=no-member
328335 new_func.postinit(func.args, func.body, func.decorators, func.returns)
658665 return node_classes.Const("")
659666
660667
668 class UnicodeDecodeErrorInstanceModel(ExceptionInstanceModel):
669 @property
670 def attr_object(self):
671 return node_classes.Const("")
672
673
661674 BUILTIN_EXCEPTIONS = {
662675 "builtins.SyntaxError": SyntaxErrorInstanceModel,
663676 "builtins.ImportError": ImportErrorInstanceModel,
677 "builtins.UnicodeDecodeError": UnicodeDecodeErrorInstanceModel,
664678 # These are all similar to OSError in terms of attributes
665679 "builtins.OSError": OSErrorInstanceModel,
666680 "builtins.BlockingIOError": OSErrorInstanceModel,
706720 elems.append(elem)
707721 obj.postinit(elts=elems)
708722
709 # pylint: disable=import-outside-toplevel; circular import
710 from astroid import objects
711
712723 obj = objects.DictItems(obj)
713724 return self._generic_dict_attribute(obj, "items")
714725
718729 obj = node_classes.List(parent=self._instance)
719730 obj.postinit(elts=keys)
720731
721 # pylint: disable=import-outside-toplevel; circular import
722 from astroid import objects
723
724732 obj = objects.DictKeys(obj)
725733 return self._generic_dict_attribute(obj, "keys")
726734
730738 values = [value for (_, value) in self._instance.items]
731739 obj = node_classes.List(parent=self._instance)
732740 obj.postinit(values)
733
734 # pylint: disable=import-outside-toplevel; circular import
735 from astroid import objects
736741
737742 obj = objects.DictValues(obj)
738743 return self._generic_dict_attribute(obj, "values")
786791 return property_accessor
787792
788793 @property
794 def attr_fset(self):
795 from astroid.scoped_nodes import FunctionDef
796
797 func = self._instance
798
799 def find_setter(func: objects.Property) -> Optional[astroid.FunctionDef]:
800 """
801 Given a property, find the corresponding setter function and returns it.
802
803 :param func: property for which the setter has to be found
804 :return: the setter function or None
805 """
806 for target in [
807 t for t in func.parent.get_children() if t.name == func.function.name
808 ]:
809 for dec_name in target.decoratornames():
810 if dec_name.endswith(func.function.name + ".setter"):
811 return target
812 return None
813
814 func_setter = find_setter(func)
815 if not func_setter:
816 raise exceptions.InferenceError(
817 f"Unable to find the setter of property {func.function.name}"
818 )
819
820 class PropertyFuncAccessor(FunctionDef):
821 def infer_call_result(self, caller=None, context=None):
822 nonlocal func_setter
823 if caller and len(caller.args) != 2:
824 raise exceptions.InferenceError(
825 "fset() needs two arguments", target=self, context=context
826 )
827 yield from func_setter.infer_call_result(caller=caller, context=context)
828
829 property_accessor = PropertyFuncAccessor(name="fset", parent=self._instance)
830 property_accessor.postinit(args=func_setter.args, body=func_setter.body)
831 return property_accessor
832
833 @property
789834 def attr_setter(self):
790835 return self._init_function("setter")
791836
00 # Copyright (c) 2006-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
1 # Copyright (c) 2014-2019 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
22 # Copyright (c) 2014 BioGeek <jeroen.vangoey@gmail.com>
33 # Copyright (c) 2014 Google, Inc.
44 # Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
88 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
99 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
1010 # Copyright (c) 2019 Raphael Gaschignard <raphael@makeleaps.com>
11 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
12 # Copyright (c) 2020 Raphael Gaschignard <raphael@rtpg.co>
1113 # Copyright (c) 2020 Anubhav <35621759+anubh-v@users.noreply.github.com>
1214 # Copyright (c) 2020 Ashley Whetter <ashley@awhetter.co.uk>
1315
235237 value = exceptions.AstroidImportError(
236238 "Failed to import module {modname} with error:\n{error}.",
237239 modname=modname,
238 error=ex,
240 # we remove the traceback here to save on memory usage (since these exceptions are cached)
241 error=ex.with_traceback(None),
239242 )
240243 self._mod_file_cache[(modname, contextfile)] = value
241244 if isinstance(value, exceptions.AstroidBuildingError):
242 raise value
245 # we remove the traceback here to save on memory usage (since these exceptions are cached)
246 raise value.with_traceback(None)
243247 return value
244248
245249 def ast_from_module(self, module, modname=None):
1515 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
1616 # Copyright (c) 2019 markmcclain <markmcclain@users.noreply.github.com>
1717 # Copyright (c) 2019 BasPH <BasPH@users.noreply.github.com>
18 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
19 # Copyright (c) 2020 Peter Kolbus <peter.kolbus@gmail.com>
1820
1921 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2022 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
3032 :type BUILTIN_MODULES: dict
3133 :var BUILTIN_MODULES: dictionary with builtin module names has key
3234 """
33 import imp
35 import importlib.util
3436 import os
3537 import platform
3638 import sys
4345 # distutils is replaced by virtualenv with a module that does
4446 # weird path manipulations in order to get to the
4547 # real distutils module.
46 from typing import Optional, List
4748
4849 from .interpreter._import import spec
4950 from .interpreter._import import util
8990 pass
9091
9192 if platform.python_implementation() == "PyPy":
93 # The get_python_lib(standard_lib=True) function does not give valid
94 # result with pypy in a virtualenv.
95 # In a virtual environment, with CPython implementation the call to this function returns a path toward
96 # the binary (its libraries) which has been used to create the virtual environment.
97 # Not with pypy implementation.
98 # The only way to retrieve such information is to use the sys.base_prefix hint.
99 # It's worth noticing that under CPython implementation the return values of
100 # get_python_lib(standard_lib=True) and get_python_lib(santdard_lib=True, prefix=sys.base_prefix)
101 # are the same.
102 # In the lines above, we could have replace the call to get_python_lib(standard=True)
103 # with the one using prefix=sys.base_prefix but we prefer modifying only what deals with pypy.
104 STD_LIB_DIRS.add(get_python_lib(standard_lib=True, prefix=sys.base_prefix))
92105 _root = os.path.join(sys.prefix, "lib_pypy")
93106 STD_LIB_DIRS.add(_root)
94107 try:
95108 # real_prefix is defined when running inside virtualenv.
96 STD_LIB_DIRS.add(os.path.join(sys.real_prefix, "lib_pypy"))
109 STD_LIB_DIRS.add(os.path.join(sys.base_prefix, "lib_pypy"))
97110 except AttributeError:
98111 pass
99112 del _root
177190 return result
178191
179192
180 def load_module_from_name(dotted_name, path=None, use_sys=True):
193 def load_module_from_name(dotted_name):
181194 """Load a Python module from its name.
182195
183196 :type dotted_name: str
184197 :param dotted_name: python name of a module or package
185198
186 :type path: list or None
187 :param path:
188 optional list of path where the module or package should be
189 searched (use sys.path if nothing or None is given)
190
191 :type use_sys: bool
192 :param use_sys:
193 boolean indicating whether the sys.modules dictionary should be
194 used or not
195
196
197199 :raise ImportError: if the module or package is not found
198200
199201 :rtype: module
200202 :return: the loaded module
201203 """
202 return load_module_from_modpath(dotted_name.split("."), path, use_sys)
203
204
205 def load_module_from_modpath(parts, path: Optional[List[str]] = None, use_sys=1):
204 try:
205 return sys.modules[dotted_name]
206 except KeyError:
207 pass
208
209 return importlib.import_module(dotted_name)
210
211
212 def load_module_from_modpath(parts):
206213 """Load a python module from its split name.
207214
208215 :type parts: list(str) or tuple(str)
209216 :param parts:
210217 python name of a module or package split on '.'
211218
212 :param path:
213 Optional list of path where the module or package should be
214 searched (use sys.path if nothing or None is given)
215
216 :type use_sys: bool
217 :param use_sys:
218 boolean indicating whether the sys.modules dictionary should be used or not
219
220219 :raise ImportError: if the module or package is not found
221220
222221 :rtype: module
223222 :return: the loaded module
224223 """
225 if use_sys:
226 try:
227 return sys.modules[".".join(parts)]
228 except KeyError:
229 pass
230 modpath = []
231 prevmodule = None
232 for part in parts:
233 modpath.append(part)
234 curname = ".".join(modpath)
235 module = None
236 if len(modpath) != len(parts):
237 # even with use_sys=False, should try to get outer packages from sys.modules
238 module = sys.modules.get(curname)
239 elif use_sys:
240 # because it may have been indirectly loaded through a parent
241 module = sys.modules.get(curname)
242 if module is None:
243 mp_file, mp_filename, mp_desc = imp.find_module(part, path)
244 module = imp.load_module(curname, mp_file, mp_filename, mp_desc)
245 # mp_file still needs to be closed.
246 if mp_file:
247 mp_file.close()
248 if prevmodule:
249 setattr(prevmodule, part, module)
250 _file = getattr(module, "__file__", "")
251 prevmodule = module
252 if not _file and util.is_namespace(curname):
253 continue
254 if not _file and len(modpath) != len(parts):
255 raise ImportError("no module in %s" % ".".join(parts[len(modpath) :]))
256 path = [os.path.dirname(_file)]
257 return module
258
259
260 def load_module_from_file(
261 filepath: str, path: Optional[List[str]] = None, use_sys=True
262 ):
224 return load_module_from_name(".".join(parts))
225
226
227 def load_module_from_file(filepath: str):
263228 """Load a Python module from it's path.
264229
265230 :type filepath: str
266231 :param filepath: path to the python module or package
267232
268 :param Optional[List[str]] path:
269 Optional list of path where the module or package should be
270 searched (use sys.path if nothing or None is given)
271
272 :type use_sys: bool
273 :param use_sys:
274 boolean indicating whether the sys.modules dictionary should be
275 used or not
276
277233 :raise ImportError: if the module or package is not found
278234
279235 :rtype: module
280236 :return: the loaded module
281237 """
282238 modpath = modpath_from_file(filepath)
283 return load_module_from_modpath(modpath, path, use_sys)
239 return load_module_from_modpath(modpath)
284240
285241
286242 def check_modpath_has_init(path, mod_path):
417373 elif modpath == ["os", "path"]:
418374 # FIXME: currently ignoring search_path...
419375 return spec.ModuleSpec(
420 name="os.path", location=os.path.__file__, module_type=imp.PY_SOURCE
376 name="os.path",
377 location=os.path.__file__,
378 module_type=spec.ModuleType.PY_SOURCE,
421379 )
422380 return _spec_from_modpath(modpath, path, context)
423381
613571 from_file = os.path.dirname(from_file)
614572 if from_file in sys.path:
615573 return False
616 try:
617 stream, _, _ = imp.find_module(modname.split(".")[0], [from_file])
618
619 # Close the stream to avoid ResourceWarnings.
620 if stream:
621 stream.close()
622 return True
623 except ImportError:
574 name = os.path.basename(from_file)
575 file_path = os.path.dirname(from_file)
576 parent_spec = importlib.util.find_spec(name, from_file)
577 while parent_spec is None and len(file_path) > 0:
578 name = os.path.basename(file_path) + "." + name
579 file_path = os.path.dirname(file_path)
580 parent_spec = importlib.util.find_spec(name, from_file)
581
582 if parent_spec is None:
624583 return False
584
585 submodule_spec = importlib.util.find_spec(
586 name + "." + modname.split(".")[0], parent_spec.submodule_search_locations
587 )
588 return submodule_spec is not None
625589
626590
627591 # internal only functions #####################################################
22 # Copyright (c) 2010 Daniel Harding <dharding@gmail.com>
33 # Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
44 # Copyright (c) 2013-2014 Google, Inc.
5 # Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
5 # Copyright (c) 2014-2021 Claudiu Popa <pcmanticore@gmail.com>
66 # Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
77 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
88 # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
1313 # Copyright (c) 2017-2020 Ashley Whetter <ashley@awhetter.co.uk>
1414 # Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com>
1515 # Copyright (c) 2017 rr- <rr-@sakuya.pl>
16 # Copyright (c) 2018-2019 hippo91 <guillaume.peillex@gmail.com>
16 # Copyright (c) 2018-2020 hippo91 <guillaume.peillex@gmail.com>
17 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
1718 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
1819 # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
19 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
2020 # Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>
2121 # Copyright (c) 2018 HoverHell <hoverhell@gmail.com>
2222 # Copyright (c) 2019 kavins14 <kavin.singh@mail.utoronto.ca>
2323 # Copyright (c) 2019 kavins14 <kavinsingh@hotmail.com>
24 # Copyright (c) 2020 Raphael Gaschignard <raphael@rtpg.co>
25 # Copyright (c) 2020 Bryce Guinta <bryce.guinta@protonmail.com>
2426
2527 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2628 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
353355 # explicit_inference is not bound, give it self explicitly
354356 try:
355357 # pylint: disable=not-callable
356 return self._explicit_inference(self, context, **kwargs)
358 yield from self._explicit_inference(self, context, **kwargs)
359 return
357360 except exceptions.UseInferenceDefault:
358361 pass
359362
360363 if not context:
361 return self._infer(context, **kwargs)
364 yield from self._infer(context, **kwargs)
365 return
362366
363367 key = (self, context.lookupname, context.callcontext, context.boundnode)
364368 if key in context.inferred:
365 return iter(context.inferred[key])
366
367 gen = context.cache_generator(key, self._infer(context, **kwargs))
368 return util.limit_inference(gen, MANAGER.max_inferable_values)
369 yield from context.inferred[key]
370 return
371
372 generator = self._infer(context, **kwargs)
373 results = []
374
375 # Limit inference amount to help with performance issues with
376 # exponentially exploding possible results.
377 limit = MANAGER.max_inferable_values
378 for i, result in enumerate(generator):
379 if i >= limit:
380 yield util.Uninferable
381 break
382 results.append(result)
383 yield result
384
385 # Cache generated results for subsequent inferences of the
386 # same node using the same context
387 context.inferred[key] = tuple(results)
388 return
369389
370390 def _repr_name(self):
371391 """Get a name for nice representation.
949969 try:
950970 return stmts[index + 1]
951971 except IndexError:
952 pass
972 return None
953973
954974 def previous_sibling(self):
955975 """The previous sibling statement.
11481168 _stmts = []
11491169 _stmt_parents = []
11501170 statements = self._get_filtered_node_statements(stmts)
1151
11521171 for node, stmt in statements:
11531172 # line filtering is on and we have reached our location, break
1154 if stmt.fromlineno > mylineno > 0:
1173 if stmt.fromlineno and stmt.fromlineno > mylineno > 0:
11551174 break
11561175 # Ignore decorators with the same name as the
11571176 # decorated function
21052124 yield self.target
21062125 yield self.value
21072126
2127 def _get_yield_nodes_skip_lambdas(self):
2128 """An AugAssign node can contain a Yield node in the value"""
2129 yield from self.value._get_yield_nodes_skip_lambdas()
2130 yield from super()._get_yield_nodes_skip_lambdas()
2131
21082132
21092133 class Repr(NodeNG):
21102134 """Class representing an :class:`ast.Repr` node.
35073531 def has_elif_block(self):
35083532 return len(self.orelse) == 1 and isinstance(self.orelse[0], If)
35093533
3534 def _get_yield_nodes_skip_lambdas(self):
3535 """An If node can contain a Yield node in the test"""
3536 yield from self.test._get_yield_nodes_skip_lambdas()
3537 yield from super()._get_yield_nodes_skip_lambdas()
3538
35103539
35113540 class IfExp(NodeNG):
35123541 """Class representing an :class:`ast.IfExp` node.
1313 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
1414 # Copyright (c) 2018 HoverHell <hoverhell@gmail.com>
1515 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
16 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
17 # Copyright (c) 2020 Vilnis Termanis <vilnis.termanis@iotics.com>
18 # Copyright (c) 2020 Ram Rachum <ram@rachum.com>
1619
1720 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1821 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
497500 elif isinstance(inferred, bases.Instance):
498501 try:
499502 enter = next(inferred.igetattr("__enter__", context=context))
500 except (exceptions.InferenceError, exceptions.AttributeInferenceError):
501 raise exceptions.InferenceError(node=inferred)
503 except (exceptions.InferenceError, exceptions.AttributeInferenceError) as exc:
504 raise exceptions.InferenceError(node=inferred) from exc
502505 if not isinstance(enter, bases.BoundMethod):
503506 raise exceptions.InferenceError(node=enter)
504507 yield from enter.infer_call_result(self, context)
685688 continue
686689
687690 # We're done unpacking.
688 elts = list(elts)
689691 packed = nodes.List(
690692 ctx=Store, parent=self, lineno=lhs.lineno, col_offset=lhs.col_offset
691693 )
692 packed.postinit(elts=elts)
694 packed.postinit(elts=list(elts))
693695 yield packed
694696 break
695697
1010 # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
1111 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
1212 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
13 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
14 # Copyright (c) 2020 Becker Awqatty <bawqatty@mide.com>
1315 # Copyright (c) 2020 Robin Jarry <robin.jarry@6wind.com>
1416
1517 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2426 import os
2527 import sys
2628 import types
29 import warnings
2730
2831 from astroid import bases
2932 from astroid import manager
323326 self._done[obj] = node
324327 for name in dir(obj):
325328 try:
326 member = getattr(obj, name)
327 except AttributeError:
329 with warnings.catch_warnings():
330 warnings.filterwarnings("error")
331 member = getattr(obj, name)
332 except (AttributeError, DeprecationWarning):
328333 # damned ExtensionClass.Base, I know you're there !
329334 attach_dummy_node(node, name)
330335 continue
1414 # Copyright (c) 2018 Serhiy Storchaka <storchaka@gmail.com>
1515 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
1616 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
17 # Copyright (c) 2019-2020 Ashley Whetter <ashley@awhetter.co.uk>
17 # Copyright (c) 2019-2021 Ashley Whetter <ashley@awhetter.co.uk>
1818 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
1919 # Copyright (c) 2019 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
2020
237237
238238 return type_object.value
239239
240 def check_function_type_comment(self, node):
240 def check_function_type_comment(self, node, parent):
241241 type_comment = getattr(node, "type_comment", None)
242242 if not type_comment:
243243 return None
250250
251251 returns = None
252252 argtypes = [
253 self.visit(elem, node) for elem in (type_comment_ast.argtypes or [])
253 self.visit(elem, parent) for elem in (type_comment_ast.argtypes or [])
254254 ]
255255 if type_comment_ast.returns:
256 returns = self.visit(type_comment_ast.returns, node)
256 returns = self.visit(type_comment_ast.returns, parent)
257257
258258 return returns, argtypes
259259
614614 returns = None
615615
616616 type_comment_args = type_comment_returns = None
617 type_comment_annotation = self.check_function_type_comment(node)
617 type_comment_annotation = self.check_function_type_comment(node, newnode)
618618 if type_comment_annotation:
619619 type_comment_returns, type_comment_args = type_comment_annotation
620620 newnode.postinit(
1919 # Copyright (c) 2018 HoverHell <hoverhell@gmail.com>
2020 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
2121 # Copyright (c) 2019 Peter de Blanc <peter@standard.ai>
22 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
23 # Copyright (c) 2020 Peter Kolbus <peter.kolbus@gmail.com>
24 # Copyright (c) 2020 Tim Martin <tim@asymptotic.co.uk>
25 # Copyright (c) 2020 Ram Rachum <ram@rachum.com>
2226
2327 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2428 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
14471451 decorators.append(assign.value)
14481452 return decorators
14491453
1454 # pylint: disable=invalid-overridden-method
14501455 @decorators_mod.cachedproperty
14511456 def type(
14521457 self
25702575 else:
25712576 raise exceptions.InferenceError(
25722577 error.message, target=self, attribute=name, context=context
2573 )
2578 ) from error
25742579
25752580 def has_dynamic_getattr(self, context=None):
25762581 """Check if the class has a custom __getattr__ or __getattribute__.
28572862
28582863 for stmt in self.bases:
28592864 try:
2860 baseobj = next(stmt.infer(context=context))
2865 baseobj = next(stmt.infer(context=context.clone()))
28612866 except exceptions.InferenceError:
28622867 continue
28632868 if isinstance(baseobj, bases.Instance):
00 # Copyright (c) 2013-2014 Google, Inc.
11 # Copyright (c) 2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
2 # Copyright (c) 2015-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2015-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
44 # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
55 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
6 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
67
78 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
89 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
11 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
33 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
4 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
5 # Copyright (c) 2020 Bryce Guinta <bryce.guinta@protonmail.com>
46
57 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
68 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
79
810 import warnings
9 from itertools import islice
1011
1112 import importlib
1213 import lazy_object_proxy
138139 },
139140 )
140141 return proxy(lambda: node_type)
141
142
143 def limit_inference(iterator, size):
144 """Limit inference amount.
145
146 Limit inference amount to help with performance issues with
147 exponentially exploding possible results.
148
149 :param iterator: Inference generator to limit
150 :type iterator: Iterator(NodeNG)
151
152 :param size: Maximum mount of nodes yielded plus an
153 Uninferable at the end if limit reached
154 :type size: int
155
156 :yields: A possibly modified generator
157 :rtype param: Iterable
158 """
159 yield from islice(iterator, size)
160 has_more = next(iterator, False)
161 if has_more is not False:
162 yield Uninferable
163 return
00 Metadata-Version: 1.2
11 Name: astroid
2 Version: 2.4.2
2 Version: 2.5
33 Summary: An abstract syntax tree for Python with inference support.
44 Home-page: https://github.com/PyCQA/astroid
55 Author: Python Code Quality Authority
8686 ---------------
8787
8888 astroid 2.0 is currently available for Python 3 only. If you want Python 2
89 support, older versions of astroid will still supported until 2020.
89 support, use an older version of astroid (though note that these versions
90 are no longer supported).
9091
9192 Test
9293 ----
102103 Classifier: Topic :: Software Development :: Quality Assurance
103104 Classifier: Programming Language :: Python
104105 Classifier: Programming Language :: Python :: 3
105 Classifier: Programming Language :: Python :: 3.5
106106 Classifier: Programming Language :: Python :: 3.6
107107 Classifier: Programming Language :: Python :: 3.7
108108 Classifier: Programming Language :: Python :: 3.8
109 Classifier: Programming Language :: Python :: 3.9
109110 Classifier: Programming Language :: Python :: Implementation :: CPython
110111 Classifier: Programming Language :: Python :: Implementation :: PyPy
111 Requires-Python: >=3.5
112 Requires-Python: >=3.6
4949 astroid/brain/brain_gi.py
5050 astroid/brain/brain_hashlib.py
5151 astroid/brain/brain_http.py
52 astroid/brain/brain_hypothesis.py
5253 astroid/brain/brain_io.py
5354 astroid/brain/brain_mechanize.py
5455 astroid/brain/brain_multiprocessing.py
7172 astroid/brain/brain_responses.py
7273 astroid/brain/brain_scipy_signal.py
7374 astroid/brain/brain_six.py
75 astroid/brain/brain_sqlalchemy.py
7476 astroid/brain/brain_ssl.py
7577 astroid/brain/brain_subprocess.py
7678 astroid/brain/brain_threading.py
79 astroid/brain/brain_type.py
7780 astroid/brain/brain_typing.py
7881 astroid/brain/brain_uuid.py
7982 astroid/interpreter/__init__.py
109112 tests/unittest_scoped_nodes.py
110113 tests/unittest_transforms.py
111114 tests/unittest_utils.py
112 tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg
113 tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip
114 tests/testdata/python2/data/__init__.py
115 tests/testdata/python2/data/absimport.py
116 tests/testdata/python2/data/all.py
117 tests/testdata/python2/data/descriptor_crash.py
118 tests/testdata/python2/data/email.py
119 tests/testdata/python2/data/foogle_fax-0.12.5-py2.7-nspkg.pth
120 tests/testdata/python2/data/format.py
121 tests/testdata/python2/data/invalid_encoding.py
122 tests/testdata/python2/data/module.py
123 tests/testdata/python2/data/module2.py
124 tests/testdata/python2/data/noendingnewline.py
125 tests/testdata/python2/data/nonregr.py
126 tests/testdata/python2/data/notall.py
127 tests/testdata/python2/data/operator_precedence.py
128 tests/testdata/python2/data/recursion.py
129 tests/testdata/python2/data/tmp__init__.py
130 tests/testdata/python2/data/SSL1/Connection1.py
131 tests/testdata/python2/data/SSL1/__init__.py
132 tests/testdata/python2/data/absimp/__init__.py
133 tests/testdata/python2/data/absimp/string.py
134 tests/testdata/python2/data/absimp/sidepackage/__init__.py
135 tests/testdata/python2/data/appl/__init__.py
136 tests/testdata/python2/data/appl/myConnection.py
137 tests/testdata/python2/data/contribute_to_namespace/namespace_pep_420/submodule.py
138 tests/testdata/python2/data/find_test/__init__.py
139 tests/testdata/python2/data/find_test/module.py
140 tests/testdata/python2/data/find_test/module2.py
141 tests/testdata/python2/data/find_test/noendingnewline.py
142 tests/testdata/python2/data/find_test/nonregr.py
143 tests/testdata/python2/data/foogle/fax/__init__.py
144 tests/testdata/python2/data/foogle/fax/a.py
145 tests/testdata/python2/data/lmfp/__init__.py
146 tests/testdata/python2/data/lmfp/foo.py
147 tests/testdata/python2/data/module1abs/__init__.py
148 tests/testdata/python2/data/module1abs/core.py
149 tests/testdata/python2/data/namespace_pep_420/module.py
150 tests/testdata/python2/data/notamodule/file.py
151 tests/testdata/python2/data/package/__init__.py
152 tests/testdata/python2/data/package/absimport.py
153 tests/testdata/python2/data/package/hello.py
154 tests/testdata/python2/data/package/import_package_subpackage_module.py
155 tests/testdata/python2/data/package/subpackage/__init__.py
156 tests/testdata/python2/data/package/subpackage/module.py
157 tests/testdata/python2/data/path_pkg_resources_1/package/__init__.py
158 tests/testdata/python2/data/path_pkg_resources_1/package/foo.py
159 tests/testdata/python2/data/path_pkg_resources_2/package/__init__.py
160 tests/testdata/python2/data/path_pkg_resources_2/package/bar.py
161 tests/testdata/python2/data/path_pkg_resources_3/package/__init__.py
162 tests/testdata/python2/data/path_pkg_resources_3/package/baz.py
163 tests/testdata/python2/data/path_pkgutil_1/package/__init__.py
164 tests/testdata/python2/data/path_pkgutil_1/package/foo.py
165 tests/testdata/python2/data/path_pkgutil_2/package/__init__.py
166 tests/testdata/python2/data/path_pkgutil_2/package/bar.py
167 tests/testdata/python2/data/path_pkgutil_3/package/__init__.py
168 tests/testdata/python2/data/path_pkgutil_3/package/baz.py
169 tests/testdata/python2/data/unicode_package/__init__.py
170 tests/testdata/python2/data/unicode_package/core/__init__.py
171115 tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg
172116 tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip
173117 tests/testdata/python3/data/__init__.py
0 lazy_object_proxy==1.4.*
1 six~=1.12
2 wrapt~=1.11
0 lazy_object_proxy>=1.4.0
1 wrapt<1.13,>=1.11
32
43 [:implementation_name == "cpython" and python_version < "3.8"]
54 typed-ast<1.5,>=1.4.0
00 #!/usr/bin/env python
11 # Copyright (c) 2006, 2009-2010, 2012-2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
22 # Copyright (c) 2010-2011 Julien Jehannet <julien.jehannet@logilab.fr>
3 # Copyright (c) 2014-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
3 # Copyright (c) 2014-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
44 # Copyright (c) 2014 Google, Inc.
55 # Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com>
66 # Copyright (c) 2018-2019 Ashley Whetter <ashley@awhetter.co.uk>
77 # Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
8 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
9 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
10 # Copyright (c) 2020 Colin Kennedy <colinvfx@gmail.com>
811
912 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1013 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1316 """Setup script for astroid."""
1417 import os
1518 import sys
19 import warnings
1620 from setuptools import find_packages, setup
1721 from setuptools.command import easy_install # pylint: disable=unused-import
1822 from setuptools.command import install_lib # pylint: disable=unused-import
23
24 if sys.version_info.major == 3 and sys.version_info.minor <=5:
25 warnings.warn("You will soon need to upgrade to python 3.6 in order to use the latest version of Astroid.", DeprecationWarning)
1926
2027 real_path = os.path.realpath(__file__)
2128 astroid_dir = os.path.dirname(real_path)
4350 author=author,
4451 author_email=author_email,
4552 url=web,
46 python_requires=">=3.5",
53 python_requires=">=3.6",
4754 install_requires=install_requires,
4855 extras_require=extras_require,
4956 packages=find_packages(exclude=["tests"]) + ["astroid.brain"],
00 # Copyright (c) 2014 Google, Inc.
1 # Copyright (c) 2015-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2015-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
22 # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
33 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
44 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
5 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
6 # Copyright (c) 2020 David Cain <davidjosephcain@gmail.com>
57
68 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
79 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1416 from astroid.bases import BUILTINS
1517
1618
17 DATA_DIR = os.path.join("testdata", "python{}".format(sys.version_info[0]))
19 DATA_DIR = os.path.join("testdata", "python3")
1820 RESOURCE_PATH = os.path.join(os.path.dirname(__file__), DATA_DIR, "data")
1921
2022
tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg less more
Binary diff not shown
tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip less more
Binary diff not shown
+0
-5
tests/testdata/python2/data/SSL1/Connection1.py less more
0
1 class Connection:
2
3 def __init__(self, ctx, sock=None):
4 print('init Connection')
+0
-1
tests/testdata/python2/data/SSL1/__init__.py less more
0 from Connection1 import Connection
+0
-1
tests/testdata/python2/data/__init__.py less more
0 __revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $"
+0
-5
tests/testdata/python2/data/absimp/__init__.py less more
0 """a package with absolute import activated
1 """
2
3 from __future__ import absolute_import
4
+0
-3
tests/testdata/python2/data/absimp/sidepackage/__init__.py less more
0 """a side package with nothing in it
1 """
2
+0
-3
tests/testdata/python2/data/absimp/string.py less more
0 from __future__ import absolute_import, print_function
1 import string
2 print(string)
+0
-3
tests/testdata/python2/data/absimport.py less more
0 from __future__ import absolute_import
1 import email
2 from email import message
+0
-9
tests/testdata/python2/data/all.py less more
0
1 name = 'a'
2 _bla = 2
3 other = 'o'
4 class Aaa: pass
5
6 def func(): print 'yo'
7
8 __all__ = 'Aaa', '_bla', 'name'
+0
-3
tests/testdata/python2/data/appl/__init__.py less more
0 """
1 Init
2 """
+0
-12
tests/testdata/python2/data/appl/myConnection.py less more
0 from __future__ import print_function
1 from data import SSL1
2 class MyConnection(SSL1.Connection):
3
4 """An SSL connection."""
5
6 def __init__(self, dummy):
7 print('MyConnection init')
8
9 if __name__ == '__main__':
10 myConnection = MyConnection(' ')
11 raw_input('Press Enter to continue...')
+0
-1
tests/testdata/python2/data/contribute_to_namespace/namespace_pep_420/submodule.py less more
0 var = 42
+0
-11
tests/testdata/python2/data/descriptor_crash.py less more
0
1 import urllib
2
3 class Page(object):
4 _urlOpen = staticmethod(urllib.urlopen)
5
6 def getPage(self, url):
7 handle = self._urlOpen(url)
8 data = handle.read()
9 handle.close()
10 return data
+0
-1
tests/testdata/python2/data/email.py less more
0 """fake email module to test absolute import doesn't grab this one"""
+0
-0
tests/testdata/python2/data/find_test/__init__.py less more
(Empty file)
+0
-0
tests/testdata/python2/data/find_test/module.py less more
(Empty file)
+0
-0
tests/testdata/python2/data/find_test/module2.py less more
(Empty file)
+0
-0
tests/testdata/python2/data/find_test/noendingnewline.py less more
(Empty file)
+0
-0
tests/testdata/python2/data/find_test/nonregr.py less more
(Empty file)
+0
-0
tests/testdata/python2/data/foogle/fax/__init__.py less more
(Empty file)
+0
-1
tests/testdata/python2/data/foogle/fax/a.py less more
0 x = 1
+0
-2
tests/testdata/python2/data/foogle_fax-0.12.5-py2.7-nspkg.pth less more
0 import sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('foogle',));ie = os.path.exists(os.path.join(p,'__init__.py'));m = not ie and sys.modules.setdefault('foogle', types.ModuleType('foogle'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)
1 import sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('foogle','crank'));ie = os.path.exists(os.path.join(p,'__init__.py'));m = not ie and sys.modules.setdefault('foogle.crank', types.ModuleType('foogle.crank'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)
+0
-34
tests/testdata/python2/data/format.py less more
0 """A multiline string
1 """
2
3 function('aeozrijz\
4 earzer', hop)
5 # XXX write test
6 x = [i for i in range(5)
7 if i % 4]
8
9 fonction(1,
10 2,
11 3,
12 4)
13
14 def definition(a,
15 b,
16 c):
17 return a + b + c
18
19 class debile(dict,
20 object):
21 pass
22
23 if aaaa: pass
24 else:
25 aaaa,bbbb = 1,2
26 aaaa,bbbb = bbbb,aaaa
27 # XXX write test
28 hop = \
29 aaaa
30
31
32 __revision__.lower();
33
+0
-1
tests/testdata/python2/data/invalid_encoding.py less more
0 # -*- coding: lala -*-
+0
-2
tests/testdata/python2/data/lmfp/__init__.py less more
0 # force a "direct" python import
1 from . import foo
+0
-6
tests/testdata/python2/data/lmfp/foo.py less more
0 import sys
1 if not getattr(sys, 'bar', None):
2 sys.just_once = []
3 # there used to be two numbers here because
4 # of a load_module_from_path bug
5 sys.just_once.append(42)
+0
-90
tests/testdata/python2/data/module.py less more
0 """test module for astroid
1 """
2
3 __revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $'
4 from astroid.node_classes import Name as NameNode
5 from astroid import modutils
6 from astroid.utils import *
7 import os.path
8 MY_DICT = {}
9
10 def global_access(key, val):
11 """function test"""
12 local = 1
13 MY_DICT[key] = val
14 for i in val:
15 if i:
16 del MY_DICT[i]
17 continue
18 else:
19 break
20 else:
21 return local
22
23
24 class YO:
25 """hehe
26 haha"""
27 a = 1
28
29 def __init__(self):
30 try:
31 self.yo = 1
32 except ValueError, ex:
33 pass
34 except (NameError, TypeError):
35 raise XXXError()
36 except:
37 raise
38
39
40
41 class YOUPI(YO):
42 class_attr = None
43
44 def __init__(self):
45 self.member = None
46
47 def method(self):
48 """method
49 test"""
50 global MY_DICT
51 try:
52 MY_DICT = {}
53 local = None
54 autre = [a for (a, b) in MY_DICT if b]
55 if b in autre:
56 return b
57 elif a in autre:
58 return a
59 global_access(local, val=autre)
60 finally:
61 return local
62
63 def static_method():
64 """static method test"""
65 assert MY_DICT, '???'
66 static_method = staticmethod(static_method)
67
68 def class_method(cls):
69 """class method test"""
70 exec a in b
71 class_method = classmethod(class_method)
72
73
74 def four_args(a, b, c, d):
75 """four arguments (was nested_args)"""
76 pass
77 while 1:
78 if a:
79 break
80 a += +1
81 else:
82 b += -2
83 if c:
84 d = a and (b or c)
85 else:
86 c = a and b or d
87 map(lambda x, y: (y, x), a)
88 redirect = four_args
89
+0
-4
tests/testdata/python2/data/module1abs/__init__.py less more
0 from __future__ import absolute_import, print_function
1 from . import core
2 from .core import *
3 print(sys.version)
+0
-1
tests/testdata/python2/data/module1abs/core.py less more
0 import sys
+0
-143
tests/testdata/python2/data/module2.py less more
0 from data.module import YO, YOUPI
1 import data
2
3
4 class Specialization(YOUPI, YO):
5 pass
6
7
8
9 class Metaclass(type):
10 pass
11
12
13
14 class Interface:
15 pass
16
17
18
19 class MyIFace(Interface):
20 pass
21
22
23
24 class AnotherIFace(Interface):
25 pass
26
27
28
29 class MyException(Exception):
30 pass
31
32
33
34 class MyError(MyException):
35 pass
36
37
38
39 class AbstractClass(object):
40
41 def to_override(self, whatever):
42 raise NotImplementedError()
43
44 def return_something(self, param):
45 if param:
46 return 'toto'
47 return
48
49
50
51 class Concrete0:
52 __implements__ = MyIFace
53
54
55
56 class Concrete1:
57 __implements__ = (MyIFace, AnotherIFace)
58
59
60
61 class Concrete2:
62 __implements__ = (MyIFace, AnotherIFace)
63
64
65
66 class Concrete23(Concrete1):
67 pass
68
69 del YO.member
70 del YO
71 [SYN1, SYN2] = (Concrete0, Concrete1)
72 assert '1'
73 b = (1 | 2) & (3 ^ 8)
74 bb = 1 | (two | 6)
75 ccc = one & two & three
76 dddd = x ^ (o ^ r)
77 exec 'c = 3'
78 exec 'c = 3' in {}, {}
79
80 def raise_string(a=2, *args, **kwargs):
81 raise Exception, 'yo'
82 yield 'coucou'
83 yield
84 a = b + 2
85 c = b * 2
86 c = b / 2
87 c = b // 2
88 c = b - 2
89 c = b % 2
90 c = b**2
91 c = b << 2
92 c = b >> 2
93 c = ~b
94 c = not b
95 d = [c]
96 e = d[:]
97 e = d[a:b:c]
98 raise_string(*args, **kwargs)
99 print >> stream, 'bonjour'
100 print >> stream, 'salut',
101
102 def make_class(any, base=data.module.YO, *args, **kwargs):
103 """check base is correctly resolved to Concrete0"""
104
105
106 class Aaaa(base):
107 """dynamic class"""
108
109
110 return Aaaa
111 from os.path import abspath
112 import os as myos
113
114
115 class A:
116 pass
117
118
119
120 class A(A):
121 pass
122
123
124 def generator():
125 """A generator."""
126 yield
127
128 def not_a_generator():
129 """A function that contains generator, but is not one."""
130
131 def generator():
132 yield
133 genl = lambda: (yield)
134
135 def with_metaclass(meta, *bases):
136 return meta('NewBase', bases, {})
137
138
139 class NotMetaclass(with_metaclass(Metaclass)):
140 pass
141
142
+0
-1
tests/testdata/python2/data/namespace_pep_420/module.py less more
0 from namespace_pep_420.submodule import var
+0
-36
tests/testdata/python2/data/noendingnewline.py less more
0 import unittest
1
2
3 class TestCase(unittest.TestCase):
4
5 def setUp(self):
6 unittest.TestCase.setUp(self)
7
8
9 def tearDown(self):
10 unittest.TestCase.tearDown(self)
11
12 def testIt(self):
13 self.a = 10
14 self.xxx()
15
16
17 def xxx(self):
18 if False:
19 pass
20 print 'a'
21
22 if False:
23 pass
24 pass
25
26 if False:
27 pass
28 print 'rara'
29
30
31 if __name__ == '__main__':
32 print 'test2'
33 unittest.main()
34
35
+0
-57
tests/testdata/python2/data/nonregr.py less more
0 from __future__ import generators, print_function
1
2 try:
3 enumerate = enumerate
4 except NameError:
5
6 def enumerate(iterable):
7 """emulates the python2.3 enumerate() function"""
8 i = 0
9 for val in iterable:
10 yield i, val
11 i += 1
12
13 def toto(value):
14 for k, v in value:
15 print(v.get('yo'))
16
17
18 import imp
19 fp, mpath, desc = imp.find_module('optparse',a)
20 s_opt = imp.load_module('std_optparse', fp, mpath, desc)
21
22 class OptionParser(s_opt.OptionParser):
23
24 def parse_args(self, args=None, values=None, real_optparse=False):
25 if real_optparse:
26 pass
27 ## return super(OptionParser, self).parse_args()
28 else:
29 import optcomp
30 optcomp.completion(self)
31
32
33 class Aaa(object):
34 """docstring"""
35 def __init__(self):
36 self.__setattr__('a','b')
37 pass
38
39 def one_public(self):
40 """docstring"""
41 pass
42
43 def another_public(self):
44 """docstring"""
45 pass
46
47 class Ccc(Aaa):
48 """docstring"""
49
50 class Ddd(Aaa):
51 """docstring"""
52 pass
53
54 class Eee(Ddd):
55 """docstring"""
56 pass
+0
-7
tests/testdata/python2/data/notall.py less more
0 name = 'a'
1 _bla = 2
2 other = 'o'
3 class Aaa: pass
4
5 def func(): return 'yo'
6
+0
-0
tests/testdata/python2/data/notamodule/file.py less more
(Empty file)
+0
-27
tests/testdata/python2/data/operator_precedence.py less more
0 assert not not True == True
1 assert (not False or True) == True
2 assert True or False and True
3 assert (True or False) and True
4
5 assert True is not (False is True) == False
6 assert True is (not False is True == False)
7
8 assert 1 + 2 + 3 == 6
9 assert 5 - 4 + 3 == 4
10 assert 4 - 5 - 6 == -7
11 assert 7 - (8 - 9) == 8
12 assert 2**3**4 == 2**81
13 assert (2**3)**4 == 8**4
14
15 assert 1 + 2 if (0.5 if True else 0.2) else 1 if True else 2 == 3
16 assert (0 if True else 1) if False else 2 == 2
17 assert lambda x: x if (0 if False else 0) else 0 if False else 0
18 assert (lambda x: x) if (0 if True else 0.2) else 1 if True else 2 == 1
19
20 assert ('1' + '2').replace('1', '3') == '32'
21 assert (lambda x: x)(1) == 1
22 assert ([0] + [1])[1] == 1
23 assert (lambda x: lambda: x + 1)(2)() == 3
24
25 f = lambda x, y, z: y(x, z)
26 assert f(1, lambda x, y: x + y[1], (2, 3)) == 4
+0
-4
tests/testdata/python2/data/package/__init__.py less more
0 """package's __init__ file"""
1
2
3 from . import subpackage
+0
-6
tests/testdata/python2/data/package/absimport.py less more
0 from __future__ import absolute_import, print_function
1 import import_package_subpackage_module # fail
2 print(import_package_subpackage_module)
3
4 from . import hello as hola
5
+0
-2
tests/testdata/python2/data/package/hello.py less more
0 """hello module"""
1
+0
-49
tests/testdata/python2/data/package/import_package_subpackage_module.py less more
0 # pylint: disable-msg=I0011,C0301,W0611
1 """I found some of my scripts trigger off an AttributeError in pylint
2 0.8.1 (with common 0.12.0 and astroid 0.13.1).
3
4 Traceback (most recent call last):
5 File "/usr/bin/pylint", line 4, in ?
6 lint.Run(sys.argv[1:])
7 File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__
8 linter.check(args)
9 File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check
10 self.check_file(filepath, modname, checkers)
11 File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file
12 astroid = self._check_file(filepath, modname, checkers)
13 File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file
14 self.check_astroid_module(astroid, checkers)
15 File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module
16 self.astroid_events(astroid, [checker for checker in checkers
17 File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
18 self.astroid_events(child, checkers, _reversed_checkers)
19 File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
20 self.astroid_events(child, checkers, _reversed_checkers)
21 File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events
22 checker.visit(astroid)
23 File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit
24 method(node)
25 File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import
26 self._check_module_attrs(node, module, name_parts[1:])
27 File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs
28 self.add_message('E0611', args=(name, module.name),
29 AttributeError: Import instance has no attribute 'name'
30
31
32 You can reproduce it by:
33 (1) create package structure like the following:
34
35 package/
36 __init__.py
37 subpackage/
38 __init__.py
39 module.py
40
41 (2) in package/__init__.py write:
42
43 import subpackage
44
45 (3) run pylint with a script importing package.subpackage.module.
46 """
47 __revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $'
48 import package.subpackage.module
+0
-1
tests/testdata/python2/data/package/subpackage/__init__.py less more
0 """package.subpackage"""
+0
-1
tests/testdata/python2/data/package/subpackage/module.py less more
0 """package.subpackage.module"""
+0
-1
tests/testdata/python2/data/path_pkg_resources_1/package/__init__.py less more
0 __import__('pkg_resources').declare_namespace(__name__)
+0
-0
tests/testdata/python2/data/path_pkg_resources_1/package/foo.py less more
(Empty file)
+0
-1
tests/testdata/python2/data/path_pkg_resources_2/package/__init__.py less more
0 __import__('pkg_resources').declare_namespace(__name__)
+0
-0
tests/testdata/python2/data/path_pkg_resources_2/package/bar.py less more
(Empty file)
+0
-1
tests/testdata/python2/data/path_pkg_resources_3/package/__init__.py less more
0 __import__('pkg_resources').declare_namespace(__name__)
+0
-0
tests/testdata/python2/data/path_pkg_resources_3/package/baz.py less more
(Empty file)
+0
-2
tests/testdata/python2/data/path_pkgutil_1/package/__init__.py less more
0 from pkgutil import extend_path
1 __path__ = extend_path(__path__, __name__)
+0
-0
tests/testdata/python2/data/path_pkgutil_1/package/foo.py less more
(Empty file)
+0
-2
tests/testdata/python2/data/path_pkgutil_2/package/__init__.py less more
0 from pkgutil import extend_path
1 __path__ = extend_path(__path__, __name__)
+0
-0
tests/testdata/python2/data/path_pkgutil_2/package/bar.py less more
(Empty file)
+0
-2
tests/testdata/python2/data/path_pkgutil_3/package/__init__.py less more
0 from pkgutil import extend_path
1 __path__ = extend_path(__path__, __name__)
+0
-0
tests/testdata/python2/data/path_pkgutil_3/package/baz.py less more
(Empty file)
+0
-3
tests/testdata/python2/data/recursion.py less more
0 """ For issue #25 """
1 class Base(object):
2 pass
+0
-0
tests/testdata/python2/data/tmp__init__.py less more
(Empty file)
+0
-1
tests/testdata/python2/data/unicode_package/__init__.py less more
0 x = "șțîâ"
+0
-0
tests/testdata/python2/data/unicode_package/core/__init__.py less more
(Empty file)
1515 print(v.get('yo'))
1616
1717
18 import imp
19 fp, mpath, desc = imp.find_module('optparse',a)
20 s_opt = imp.load_module('std_optparse', fp, mpath, desc)
18 import optparse as s_opt
2119
2220 class OptionParser(s_opt.OptionParser):
2321
55 # Copyright (c) 2015 raylu <lurayl@gmail.com>
66 # Copyright (c) 2015 Philip Lorenz <philip@bithub.de>
77 # Copyright (c) 2016 Florian Bruhin <me@the-compiler.org>
8 # Copyright (c) 2017-2018, 2020-2021 hippo91 <guillaume.peillex@gmail.com>
89 # Copyright (c) 2017-2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
9 # Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
1010 # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
1111 # Copyright (c) 2017 David Euresti <github@euresti.com>
1212 # Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com>
1717 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
1818 # Copyright (c) 2018 Ioana Tagirta <ioana.tagirta@gmail.com>
1919 # Copyright (c) 2018 Ahmed Azzaoui <ahmed.azzaoui@engie.com>
20 # Copyright (c) 2019-2020 Bryce Guinta <bryce.guinta@protonmail.com>
2021 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
2122 # Copyright (c) 2019 Tomas Novak <ext.Tomas.Novak@skoda-auto.cz>
2223 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
2324 # Copyright (c) 2019 Grygorii Iermolenko <gyermolenko@gmail.com>
24 # Copyright (c) 2019 Bryce Guinta <bryce.guinta@protonmail.com>
25 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
26 # Copyright (c) 2020 Peter Kolbus <peter.kolbus@gmail.com>
27 # Copyright (c) 2021 Damien Baty <damien@damienbaty.com>
2528
2629 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2730 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
3033 import io
3134 import queue
3235 import re
36 import os
3337
3438 try:
3539 import multiprocessing # pylint: disable=unused-import
7781 except ImportError:
7882 HAS_ATTR = False
7983
84 try:
85 import six # pylint: disable=unused-import
86
87 HAS_SIX = True
88 except ImportError:
89 HAS_SIX = False
90
8091 from astroid import MANAGER
8192 from astroid import bases
8293 from astroid import builder
8394 from astroid import nodes
8495 from astroid import util
85 from astroid import test_utils
8696 import astroid
97 import astroid.test_utils as test_utils
8798
8899
89100 class HashlibTest(unittest.TestCase):
106117 class_obj = hashlib_module[class_name]
107118 self._assert_hashlib_class(class_obj)
108119
109 @test_utils.require_version(minver="3.6")
110120 def test_hashlib_py36(self):
111121 hashlib_module = MANAGER.ast_from_module_name("hashlib")
112122 for class_name in ["sha3_224", "sha3_512", "shake_128"]:
132142 inferred = self._inferred_queue_instance()
133143 self.assertTrue(inferred.getattr("__len__"))
134144
135 @test_utils.require_version(minver="3.5")
136145 def test_deque_py35methods(self):
137146 inferred = self._inferred_queue_instance()
138147 self.assertIn("copy", inferred.locals)
139148 self.assertIn("insert", inferred.locals)
140149 self.assertIn("index", inferred.locals)
141150
151 @test_utils.require_version(maxver="3.8")
152 def test_deque_not_py39methods(self):
153 inferred = self._inferred_queue_instance()
154 with self.assertRaises(astroid.exceptions.AttributeInferenceError):
155 inferred.getattr("__class_getitem__")
156
157 @test_utils.require_version(minver="3.9")
158 def test_deque_py39methods(self):
159 inferred = self._inferred_queue_instance()
160 self.assertTrue(inferred.getattr("__class_getitem__"))
161
142162
143163 class OrderedDictTest(unittest.TestCase):
144164 def _inferred_ordered_dict_instance(self):
151171 )
152172 return next(node.infer())
153173
154 @test_utils.require_version(minver="3.4")
155174 def test_ordered_dict_py34method(self):
156175 inferred = self._inferred_ordered_dict_instance()
157176 self.assertIn("move_to_end", inferred.locals)
203222 # namedtuple call and a mixin as base classes
204223 result = builder.extract_node(
205224 """
206 import six
207
208 result = __(six.moves.urllib.parse.urlparse('gopher://'))
225 from urllib.parse import urlparse
226
227 result = __(urlparse('gopher://'))
209228 """
210229 )
211230 instance = next(result.infer())
390409 self.assertEqual(assert_equals.qname(), "unittest.case.TestCase.assertEqual")
391410
392411
412 @unittest.skipUnless(HAS_SIX, "These tests require the six library")
393413 class SixBrainTest(unittest.TestCase):
414 @classmethod
415 def setUpClass(cls):
416 tox_env = os.environ.get("TOX_ENV_NAME")
417 if tox_env and not tox_env.endswith("-six") and HAS_SIX:
418 raise Exception("six was installed in a non-six testing environment.")
419
394420 def test_attribute_access(self):
395421 ast_nodes = builder.extract_node(
396422 """
458484 )
459485 inferred = next(ast_node.infer())
460486 self.assertIsInstance(inferred, nodes.FunctionDef)
487
488 def test_with_metaclass_subclasses_inheritance(self):
489 ast_node = builder.extract_node(
490 """
491 class A(type):
492 def test(cls):
493 return cls
494
495 class C:
496 pass
497
498 import six
499 class B(six.with_metaclass(A, C)):
500 pass
501
502 B #@
503 """
504 )
505 inferred = next(ast_node.infer())
506 self.assertIsInstance(inferred, nodes.ClassDef)
507 self.assertEqual(inferred.name, "B")
508 bases = inferred.bases
509 self.assertIsInstance(bases[0], nodes.Call)
510 ancestors = tuple(inferred.ancestors())
511 self.assertIsInstance(ancestors[0], nodes.ClassDef)
512 self.assertEqual(ancestors[0].name, "C")
513 self.assertIsInstance(ancestors[1], nodes.ClassDef)
514 self.assertEqual(ancestors[1].name, "object")
461515
462516
463517 @unittest.skipUnless(
539593 obj = next(module[attr].infer())
540594 self.assertEqual(obj.qname(), "{}.{}".format(bases.BUILTINS, attr))
541595
542 array = next(module["array"].infer())
543 self.assertEqual(array.qname(), "array.array")
596 # pypy's implementation of array.__spec__ return None. This causes problems for this inference.
597 if not hasattr(sys, "pypy_version_info"):
598 array = next(module["array"].infer())
599 self.assertEqual(array.qname(), "array.array")
544600
545601 manager = next(module["manager"].infer())
546602 # Verify that we have these attributes
799855 inferred_string = next(node.infer())
800856 assert inferred_string.value == "\N{NULL}"
801857
802 @test_utils.require_version(minver="3.6")
803858 def test_dont_crash_on_for_loops_in_body(self):
804859 node = builder.extract_node(
805860 """
837892 assert isinstance(inferred_list_node, astroid.List)
838893 assert inferred_tuple_node.as_string() == "(1, 2)"
839894 assert inferred_list_node.as_string() == "[2, 4]"
895
896 def test_enum_starred_is_skipped(self):
897 code = """
898 from enum import Enum
899 class ContentType(Enum):
900 TEXT, PHOTO, VIDEO, GIF, YOUTUBE, *_ = [1, 2, 3, 4, 5, 6]
901 ContentType.TEXT #@
902 """
903 node = astroid.extract_node(code)
904 next(node.infer())
840905
841906
842907 @unittest.skipUnless(HAS_DATEUTIL, "This test requires the dateutil library.")
923988 self.assertEqual(raw.name, "FileIO")
924989
925990
991 @test_utils.require_version("3.9")
992 class TypeBrain(unittest.TestCase):
993 def test_type_subscript(self):
994 """
995 Check that type object has the __class_getitem__ method
996 when it is used as a subscript
997 """
998 src = builder.extract_node(
999 """
1000 a: type[int] = int
1001 """
1002 )
1003 val_inf = src.annotation.value.inferred()[0]
1004 self.assertIsInstance(val_inf, astroid.ClassDef)
1005 self.assertEqual(val_inf.name, "type")
1006 meth_inf = val_inf.getattr("__class_getitem__")[0]
1007 self.assertIsInstance(meth_inf, astroid.FunctionDef)
1008
1009 def test_invalid_type_subscript(self):
1010 """
1011 Check that a type (str for example) that inherits
1012 from type does not have __class_getitem__ method even
1013 when it is used as a subscript
1014 """
1015 src = builder.extract_node(
1016 """
1017 a: str[int] = "abc"
1018 """
1019 )
1020 val_inf = src.annotation.value.inferred()[0]
1021 self.assertIsInstance(val_inf, astroid.ClassDef)
1022 self.assertEqual(val_inf.name, "str")
1023 with self.assertRaises(astroid.exceptions.AttributeInferenceError):
1024 meth_inf = val_inf.getattr("__class_getitem__")[0]
1025
1026
9261027 @test_utils.require_version("3.6")
9271028 class TypingBrain(unittest.TestCase):
9281029 def test_namedtuple_base(self):
11011202 self.assertEqual(next(re_ast[name].infer()).value, getattr(re, name))
11021203
11031204
1104 @test_utils.require_version("3.6")
11051205 class BrainFStrings(unittest.TestCase):
11061206 def test_no_crash_on_const_reconstruction(self):
11071207 node = builder.extract_node(
11191219 self.assertIs(inferred, util.Uninferable)
11201220
11211221
1122 @test_utils.require_version("3.6")
11231222 class BrainNamedtupleAnnAssignTest(unittest.TestCase):
11241223 def test_no_crash_on_ann_assign_in_namedtuple(self):
11251224 node = builder.extract_node(
12211320 """
12221321 next(astroid.extract_node(code).infer())
12231322
1224 @test_utils.require_version(minver="3.6")
12251323 def test_attrs_with_annotation(self):
12261324 code = """
12271325 import attr
12771375 # Can be either str or bytes
12781376 assert isinstance(inferred, astroid.Const)
12791377 assert isinstance(inferred.value, (str, bytes))
1378
1379 @test_utils.require_version("3.9")
1380 def test_popen_does_not_have_class_getitem(self):
1381 code = """import subprocess; subprocess.Popen"""
1382 node = astroid.extract_node(code)
1383 inferred = next(node.infer())
1384 assert "__class_getitem__" in inferred
12801385
12811386
12821387 class TestIsinstanceInference:
20192124 assert isinstance(name[0], astroid.Unknown)
20202125
20212126
2127 @pytest.mark.parametrize(
2128 "code,expected_class,expected_value",
2129 [
2130 ("'hey'.encode()", astroid.Const, b""),
2131 ("b'hey'.decode()", astroid.Const, ""),
2132 ("'hey'.encode().decode()", astroid.Const, ""),
2133 ],
2134 )
2135 def test_str_and_bytes(code, expected_class, expected_value):
2136 node = astroid.extract_node(code)
2137 inferred = next(node.infer())
2138 assert isinstance(inferred, expected_class)
2139 assert inferred.value == expected_value
2140
2141
2142 def test_no_recursionerror_on_self_referential_length_check():
2143 """
2144 Regression test for https://github.com/PyCQA/astroid/issues/777
2145 """
2146 with pytest.raises(astroid.InferenceError):
2147 node = astroid.extract_node(
2148 """
2149 class Crash:
2150 def __len__(self) -> int:
2151 return len(self)
2152 len(Crash()) #@
2153 """
2154 )
2155 node.inferred()
2156
2157
20222158 if __name__ == "__main__":
20232159 unittest.main()
00 # -*- encoding=utf-8 -*-
1 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
12 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
2 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
3 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # -*- encoding=utf-8 -*-
1 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
12 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
2 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
3 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # -*- encoding=utf-8 -*-
1 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
22 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
3 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # -*- encoding=utf-8 -*-
1 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
12 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
2 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
3 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # -*- encoding=utf-8 -*-
11 # Copyright (c) 2017-2020 hippo91 <guillaume.peillex@gmail.com>
2 # Copyright (c) 2017-2018 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2017-2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
44 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
55
00 # -*- encoding=utf-8 -*-
1 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
1 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
22 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
3 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
3536 "conjugate",
3637 "cosh",
3738 "deg2rad",
39 "degrees",
3840 "exp2",
3941 "expm1",
4042 "fabs",
4951 "negative",
5052 "positive",
5153 "rad2deg",
54 "radians",
5255 "reciprocal",
5356 "rint",
5457 "sign",
6164 )
6265
6366 two_args_ufunc = (
67 "add",
6468 "bitwise_and",
6569 "bitwise_or",
6670 "bitwise_xor",
8892 "logical_xor",
8993 "maximum",
9094 "minimum",
95 "multiply",
9196 "nextafter",
9297 "not_equal",
9398 "power",
220225 with self.subTest(typ=func_):
221226 inferred_values = list(self._inferred_numpy_func_call(func_))
222227 self.assertTrue(
223 len(inferred_values) == 1
224 or len(inferred_values) == 2
225 and inferred_values[-1].pytype() is util.Uninferable,
228 len(inferred_values) == 1,
226229 msg="Too much inferred values ({}) for {:s}".format(
227 inferred_values[-1].pytype(), func_
230 inferred_values, func_
228231 ),
229232 )
230233 self.assertTrue(
00 # -*- encoding=utf-8 -*-
11 # Copyright (c) 2017-2020 hippo91 <guillaume.peillex@gmail.com>
2 # Copyright (c) 2017-2018 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2017-2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
44 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
55
153153 Test that some numpy ndarray attributes are inferred as numpy.ndarray
154154 """
155155 licit_array_types = ".ndarray"
156 for attr_ in ("real", "imag"):
156 for attr_ in ("real", "imag", "shape", "T"):
157157 with self.subTest(typ=attr_):
158158 inferred_values = list(self._inferred_ndarray_attribute(attr_))
159159 self.assertTrue(
00 # -*- encoding=utf-8 -*-
1 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
12 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
2 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
3 # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
5455 "rand": (["args"], []),
5556 "randint": (["low", "high", "size", "dtype"], [None, None, "l"]),
5657 "randn": (["args"], []),
58 "random": (["size"], [None]),
5759 "random_integers": (["low", "high", "size"], [None, None]),
5860 "random_sample": (["size"], [None]),
5961 "rayleigh": (["scale", "size"], [1.0, None]),
00 # -*- coding: utf-8 -*-
11 # Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
2 # Copyright (c) 2014-2019 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2014-2015 Google, Inc.
44 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
55 # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
1111 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
1212 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
1313 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
14 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
1415
1516 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1617 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
3 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
34
45 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
56 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1314 from astroid import helpers
1415 from astroid import manager
1516 from astroid import raw_building
16 from astroid import test_utils
1717 from astroid import util
1818
1919
105105 expected_type = self._build_custom_builtin(expected)
106106 self.assert_classes_equal(node_type, expected_type)
107107
108 @test_utils.require_version(minver="3.0")
109108 def test_object_type_metaclasses(self):
110109 module = builder.parse(
111110 """
122121 instance_type = helpers.object_type(meta_instance)
123122 self.assert_classes_equal(instance_type, module["Meta"])
124123
125 @test_utils.require_version(minver="3.0")
126124 def test_object_type_most_derived(self):
127125 node = builder.extract_node(
128126 """
11 # Copyright (c) 2006-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
22 # Copyright (c) 2007 Marien Zwart <marienz@gentoo.org>
33 # Copyright (c) 2013-2014 Google, Inc.
4 # Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
4 # Copyright (c) 2014-2021 Claudiu Popa <pcmanticore@gmail.com>
55 # Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
66 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
77 # Copyright (c) 2015 Dmitry Pribysh <dmand@yandex.ru>
1313 # Copyright (c) 2017 Calen Pennington <calen.pennington@gmail.com>
1414 # Copyright (c) 2017 David Euresti <david@dropbox.com>
1515 # Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com>
16 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
1617 # Copyright (c) 2018 Daniel Martin <daniel.martin@crowdstrike.com>
1718 # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
18 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
1919 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
20 # Copyright (c) 2019-2021 hippo91 <guillaume.peillex@gmail.com>
2021 # Copyright (c) 2019 Stanislav Levin <slev@altlinux.org>
2122 # Copyright (c) 2019 David Liu <david@cs.toronto.edu>
2223 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
2324 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
25 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
26 # Copyright (c) 2020 Peter Kolbus <peter.kolbus@gmail.com>
27 # Copyright (c) 2020 Karthikeyan Singaravelan <tir.karthi@gmail.com>
28 # Copyright (c) 2020 Bryce Guinta <bryce.guinta@protonmail.com>
29 # Copyright (c) 2021 Francis Charette Migneault <francis.charette.migneault@gmail.com>
2430
2531 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2632 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
427433 del undefined_attr
428434 """
429435 delete = extract_node(code, __name__)
430 self.assertRaises(InferenceError, delete.infer)
436 self.assertRaises(InferenceError, next, delete.infer())
431437
432438 def test_del2(self):
433439 code = """
540546 self.assertEqual(ancestor.root().name, BUILTINS)
541547 self.assertRaises(StopIteration, partial(next, ancestors))
542548
543 def test_qqch(self):
544 code = """
545 from astroid.modutils import load_module_from_name
546 xxx = load_module_from_name('__pkginfo__')
547 """
548 ast = parse(code, __name__)
549 xxx = ast["xxx"]
550 self.assertSetEqual(
551 {n.__class__ for n in xxx.inferred()},
552 {nodes.Const, util.Uninferable.__class__},
553 )
554
555549 def test_method_argument(self):
556550 code = '''
557551 class ErudiEntitySchema:
1003997 inferred = next(node.infer())
1004998 self.assertEqual(inferred.value, expected_value)
1005999
1006 @test_utils.require_version(minver="3.5")
10071000 def test_matmul(self):
10081001 node = extract_node(
10091002 """
12481241 self.assertEqual(variable_a.inferred()[0].value, 2)
12491242
12501243 @pytest.mark.xfail(reason="Relying on path copy")
1251 @test_utils.require_version(minver="3.5")
12521244 def test_nonregr_layed_dictunpack(self):
12531245 """Regression test for https://github.com/PyCQA/astroid/issues/483
12541246 Make sure multiple dictunpack references are inferable
13081300 result = node.inferred()
13091301 assert len(result) == 2
13101302 assert isinstance(result[0], nodes.Dict)
1311 assert result[1] is util.Uninferable
1303 assert isinstance(result[1], nodes.Dict)
13121304
13131305 def test_python25_no_relative_import(self):
13141306 ast = resources.build_file("data/package/absimport.py")
17431735 self.assertIsInstance(inferred, Instance)
17441736 self.assertEqual(inferred.qname(), "{}.tuple".format(BUILTINS))
17451737
1746 @test_utils.require_version("3.5")
17471738 def test_starred_in_tuple_literal(self):
17481739 code = """
17491740 var = (1, 2, 3)
17621753 self.assertInferTuple(ast[3], [0, 1, 2, 3, 4, 5, 6, 7, 8])
17631754 self.assertInferTuple(ast[4], [0, 1, 2, 3, 4, 5, 6, 7, 999, 1000, 1001])
17641755
1765 @test_utils.require_version("3.5")
17661756 def test_starred_in_list_literal(self):
17671757 code = """
17681758 var = (1, 2, 3)
17811771 self.assertInferList(ast[3], [0, 1, 2, 3, 4, 5, 6, 7, 8])
17821772 self.assertInferList(ast[4], [0, 1, 2, 3, 4, 5, 6, 7, 999, 1000, 1001])
17831773
1784 @test_utils.require_version("3.5")
17851774 def test_starred_in_set_literal(self):
17861775 code = """
17871776 var = (1, 2, 3)
18001789 self.assertInferSet(ast[3], [0, 1, 2, 3, 4, 5, 6, 7, 8])
18011790 self.assertInferSet(ast[4], [0, 1, 2, 3, 4, 5, 6, 7, 999, 1000, 1001])
18021791
1803 @test_utils.require_version("3.5")
18041792 def test_starred_in_literals_inference_issues(self):
18051793 code = """
18061794 {0, *var} #@
18141802 with self.assertRaises(InferenceError):
18151803 next(node.infer())
18161804
1817 @test_utils.require_version("3.5")
18181805 def test_starred_in_mapping_literal(self):
18191806 code = """
18201807 var = {1: 'b', 2: 'c'}
18301817 ast[2], {0: "a", 1: "b", 2: "c", 3: "d", 4: "e", 5: "f", 6: "g"}
18311818 )
18321819
1833 @test_utils.require_version("3.5")
18341820 def test_starred_in_mapping_literal_no_inference_possible(self):
18351821 node = extract_node(
18361822 """
18481834 )
18491835 self.assertEqual(next(node.infer()), util.Uninferable)
18501836
1851 @test_utils.require_version("3.5")
18521837 def test_starred_in_mapping_inference_issues(self):
18531838 code = """
18541839 {0: 'a', **var} #@
18601845 with self.assertRaises(InferenceError):
18611846 next(node.infer())
18621847
1863 @test_utils.require_version("3.5")
18641848 def test_starred_in_mapping_literal_non_const_keys_values(self):
18651849 code = """
18661850 a, b, c, d, e, f, g, h, i, j = "ABCDEFGHIJ"
19811965 self.assertInferTuple(ast_nodes[3], [1, 3])
19821966 self.assertInferSet(ast_nodes[4], [1, 2])
19831967
1984 @test_utils.require_version("3.0")
19851968 def test_builtin_inference_py3k(self):
19861969 code = """
19871970 list(b"abc") #@
20412024 ast_node = extract_node("""dict(a=1, b=2, **{'c': 3})""")
20422025 self.assertInferDict(ast_node, {"a": 1, "b": 2, "c": 3})
20432026
2044 @test_utils.require_version("3.5")
20452027 def test_dict_inference_for_multiple_starred(self):
20462028 pairs = [
20472029 ('dict(a=1, **{"b": 2}, **{"c":3})', {"a": 1, "b": 2, "c": 3}),
20522034 node = extract_node(code)
20532035 self.assertInferDict(node, expected_value)
20542036
2055 @test_utils.require_version("3.5")
20562037 def test_dict_inference_unpack_repeated_key(self):
20572038 """Make sure astroid does not infer repeated keys in a dictionary
20582039
20822063 def test_str_methods(self):
20832064 code = """
20842065 ' '.decode() #@
2085
2086 ' '.encode() #@
20872066 ' '.join('abcd') #@
20882067 ' '.replace('a', 'b') #@
20892068 ' '.format('a') #@
21052084 """
21062085 ast = extract_node(code, __name__)
21072086 self.assertInferConst(ast[0], "")
2108 for i in range(1, 16):
2087 for i in range(1, 15):
21092088 self.assertInferConst(ast[i], "")
2110 for i in range(16, 19):
2089 for i in range(15, 18):
21112090 self.assertInferConst(ast[i], 0)
21122091
21132092 def test_unicode_methods(self):
21142093 code = """
2115 u' '.encode() #@
2116
21172094 u' '.decode() #@
21182095 u' '.join('abcd') #@
21192096 u' '.replace('a', 'b') #@
21362113 """
21372114 ast = extract_node(code, __name__)
21382115 self.assertInferConst(ast[0], "")
2139 for i in range(1, 16):
2116 for i in range(1, 15):
21402117 self.assertInferConst(ast[i], "")
2141 for i in range(16, 19):
2118 for i in range(15, 18):
21422119 self.assertInferConst(ast[i], 0)
21432120
21442121 def test_scope_lookup_same_attributes(self):
24582435 1 ** (lambda x: x) #@
24592436 {} * {} #@
24602437 {} - {} #@
2461 {} | {} #@
24622438 {} >> {} #@
24632439 [] + () #@
24642440 () + [] #@
25032479 msg.format(op="**", lhs="int", rhs="function"),
25042480 msg.format(op="*", lhs="dict", rhs="dict"),
25052481 msg.format(op="-", lhs="dict", rhs="dict"),
2506 msg.format(op="|", lhs="dict", rhs="dict"),
25072482 msg.format(op=">>", lhs="dict", rhs="dict"),
25082483 msg.format(op="+", lhs="list", rhs="tuple"),
25092484 msg.format(op="+", lhs="tuple", rhs="list"),
25182493 msg.format(op="+=", lhs="int", rhs="A"),
25192494 msg.format(op="+=", lhs="int", rhs="list"),
25202495 ]
2496
2497 # PEP-584 supports | for dictionary union
2498 if sys.version_info < (3, 9):
2499 ast_nodes.append(extract_node("{} | {} #@"))
2500 expected.append(msg.format(op="|", lhs="dict", rhs="dict"))
2501
25212502 for node, expected_value in zip(ast_nodes, expected):
25222503 errors = node.type_errors()
25232504 self.assertEqual(len(errors), 1)
29922973 class Meta(type):
29932974 def __getitem__(cls, arg):
29942975 return 24
2995 import six
2996 @six.add_metaclass(Meta)
2997 class A(object):
2976 class A(object, metaclass=Meta):
29982977 pass
29992978
30002979 A['Awesome'] #@
30042983 self.assertIsInstance(inferred, nodes.Const)
30052984 self.assertEqual(inferred.value, 24)
30062985
2986 def test_with_metaclass__getitem__(self):
2987 ast_node = extract_node(
2988 """
2989 class Meta(type):
2990 def __getitem__(cls, arg):
2991 return 24
2992 import six
2993 class A(six.with_metaclass(Meta)):
2994 pass
2995
2996 A['Awesome'] #@
2997 """
2998 )
2999 inferred = next(ast_node.infer())
3000 self.assertIsInstance(inferred, nodes.Const)
3001 self.assertEqual(inferred.value, 24)
3002
30073003 def test_bin_op_classes(self):
3004 ast_node = extract_node(
3005 """
3006 class Meta(type):
3007 def __or__(self, other):
3008 return 24
3009 class A(object, metaclass=Meta):
3010 pass
3011
3012 A | A
3013 """
3014 )
3015 inferred = next(ast_node.infer())
3016 self.assertIsInstance(inferred, nodes.Const)
3017 self.assertEqual(inferred.value, 24)
3018
3019 def test_bin_op_classes_with_metaclass(self):
30083020 ast_node = extract_node(
30093021 """
30103022 class Meta(type):
30113023 def __or__(self, other):
30123024 return 24
30133025 import six
3014 @six.add_metaclass(Meta)
3015 class A(object):
3026 class A(six.with_metaclass(Meta)):
30163027 pass
30173028
30183029 A | A
33473358 def test_unary_op_classes(self):
33483359 ast_node = extract_node(
33493360 """
3361 class Meta(type):
3362 def __invert__(self):
3363 return 42
3364 class A(object, metaclass=Meta):
3365 pass
3366 ~A
3367 """
3368 )
3369 inferred = next(ast_node.infer())
3370 self.assertIsInstance(inferred, nodes.Const)
3371 self.assertEqual(inferred.value, 42)
3372
3373 def test_unary_op_classes_with_metaclass(self):
3374 ast_node = extract_node(
3375 """
33503376 import six
33513377 class Meta(type):
33523378 def __invert__(self):
33533379 return 42
3354 @six.add_metaclass(Meta)
3355 class A(object):
3380 class A(six.with_metaclass(Meta)):
33563381 pass
33573382 ~A
33583383 """
36313656 # they will be in the future.
36323657 ast_node = extract_node(
36333658 """
3634 import six
3635
36363659 class BookMeta(type):
36373660 author = 'Rushdie'
36383661
36393662 def metaclass_function(*args):
36403663 return BookMeta
36413664
3642 @six.add_metaclass(metaclass_function)
3643 class Book(object):
3665 class Book(object, metaclass=metaclass_function):
36443666 pass
36453667 Book #@
36463668 """
36633685 flow = AttributeDict()
36643686 flow['app'] = AttributeDict()
36653687 flow['app']['config'] = AttributeDict()
3666 flow['app']['config']['doffing'] = AttributeDict() #@
3688 flow['app']['config']['doffing'] = AttributeDict()
3689 flow['app']['config']['doffing']['thinkto'] = AttributeDict() #@
36673690 """
36683691 )
36693692 self.assertIsNone(helpers.safe_infer(ast_node.targets[0]))
37443767 class A(type):
37453768 def test(cls):
37463769 return cls
3770 class B(object, metaclass=A):
3771 pass
3772
3773 B.test() #@
3774 """
3775 )
3776 inferred = next(ast_node.infer())
3777 self.assertIsInstance(inferred, nodes.ClassDef)
3778 self.assertEqual(inferred.name, "B")
3779
3780 def test_With_metaclass_subclasses_arguments_are_classes_not_instances(self):
3781 ast_node = extract_node(
3782 """
3783 class A(type):
3784 def test(cls):
3785 return cls
37473786 import six
3748 @six.add_metaclass(A)
3749 class B(object):
3787 class B(six.with_metaclass(A)):
3788 pass
3789
3790 B.test() #@
3791 """
3792 )
3793 inferred = next(ast_node.infer())
3794 self.assertIsInstance(inferred, nodes.ClassDef)
3795 self.assertEqual(inferred.name, "B")
3796
3797 def test_With_metaclass_with_partial_imported_name(self):
3798 ast_node = extract_node(
3799 """
3800 class A(type):
3801 def test(cls):
3802 return cls
3803 from six import with_metaclass
3804 class B(with_metaclass(A)):
37503805 pass
37513806
37523807 B.test() #@
37863841 self.assertIsInstance(inferred, nodes.ClassDef)
37873842 self.assertEqual(inferred.name, "A")
37883843
3789 @test_utils.require_version(minver="3.0")
37903844 def test_metaclass_with_keyword_args(self):
37913845 ast_node = extract_node(
37923846 """
44204474 self.assertIsInstance(inferred, nodes.Tuple)
44214475 self.assertEqual(self._get_tuple_value(inferred), expected_value)
44224476
4423 @test_utils.require_version("3.5")
44244477 def test_multiple_starred_args(self):
44254478 expected_values = [(1, 2, 3), (1, 4, 2, 3, 5, 6, 7)]
44264479 ast_nodes = extract_node(
44534506 self.assertIsInstance(inferred, nodes.Const)
44544507 self.assertEqual(inferred.value, expected_value)
44554508
4456 @test_utils.require_version("3.0")
44574509 def test_kwonly_args(self):
44584510 expected_values = [24, 24, 42, 23, 24, 24, 54]
44594511 ast_nodes = extract_node(
45364588 self.assertIsInstance(inferred, nodes.Const, inferred)
45374589 self.assertEqual(inferred.value, value)
45384590
4539 @test_utils.require_version("3.5")
45404591 def test_multiple_kwargs(self):
45414592 expected_value = [("a", 1), ("b", 2), ("c", 3), ("d", 4), ("f", 42)]
45424593 ast_node = extract_node(
46834734 for pair in pairs:
46844735 self._test_call_site_pair(*pair)
46854736
4686 @test_utils.require_version("3.5")
46874737 def test_call_site_starred_args(self):
46884738 pairs = [
46894739 (
51735223 assert as_string.strip() == "(ValueError, TypeError)"
51745224
51755225
5176 @test_utils.require_version(minver="3.6")
51775226 def test_cannot_getattr_ann_assigns():
51785227 node = extract_node(
51795228 """
54465495 def test(self):
54475496 return 42
54485497
5498 @test.setter
5499 def test(self, value):
5500 return "banco"
5501
54495502 A.test #@
54505503 A().test #@
54515504 A.test.fget(A) #@
5505 A.test.fset(A, "a_value") #@
54525506 A.test.setter #@
54535507 A.test.getter #@
54545508 A.test.deleter #@
54555509 """
5456 prop, prop_result, prop_fget_result, prop_setter, prop_getter, prop_deleter = extract_node(
5510 prop, prop_result, prop_fget_result, prop_fset_result, prop_setter, prop_getter, prop_deleter = extract_node(
54575511 code
54585512 )
54595513
54705524 inferred = next(prop_fget_result.infer())
54715525 assert isinstance(inferred, nodes.Const)
54725526 assert inferred.value == 42
5527
5528 inferred = next(prop_fset_result.infer())
5529 assert isinstance(inferred, nodes.Const)
5530 assert inferred.value == "banco"
54735531
54745532 for prop_func in prop_setter, prop_getter, prop_deleter:
54755533 inferred = next(prop_func.infer())
56665724
56675725
56685726 @pytest.mark.skipif(sys.version_info < (3, 8), reason="Needs dataclasses available")
5727 @pytest.mark.skipif(
5728 sys.version_info >= (3, 9),
5729 reason="Exact inference with dataclasses (replace function) in python3.9",
5730 )
56695731 def test_dataclasses_subscript_inference_recursion_error():
56705732 code = """
56715733 from dataclasses import dataclass, replace
56845746 node = extract_node(code)
56855747 # Reproduces only with safe_infer()
56865748 assert helpers.safe_infer(node) is None
5749
5750
5751 @pytest.mark.skipif(
5752 sys.version_info < (3, 9),
5753 reason="Exact inference with dataclasses (replace function) in python3.9",
5754 )
5755 def test_dataclasses_subscript_inference_recursion_error_39():
5756 code = """
5757 from dataclasses import dataclass, replace
5758
5759 @dataclass
5760 class ProxyConfig:
5761 auth: str = "/auth"
5762
5763
5764 a = ProxyConfig("")
5765 test_dict = {"proxy" : {"auth" : "", "bla" : "f"}}
5766
5767 foo = test_dict['proxy']
5768 replace(a, **test_dict['proxy']) # This fails
5769 """
5770 node = extract_node(code)
5771 infer_val = helpers.safe_infer(node)
5772 assert isinstance(infer_val, Instance)
5773 assert infer_val.pytype() == ".ProxyConfig"
56875774
56885775
56895776 def test_self_reference_infer_does_not_trigger_recursion_error():
58625949 assert list(inferred.nodes_of_class(nodes.Const)) == []
58635950
58645951
5952 def test_infer_list_of_uninferables_does_not_crash():
5953 code = """
5954 x = [A] * 1
5955 f = [x, [A] * 2]
5956 x = list(f) + [] # List[Uninferable]
5957 tuple(x[0])
5958 """
5959 node = extract_node(code)
5960 inferred = next(node.infer())
5961 assert isinstance(inferred, nodes.Tuple)
5962 # Would not be able to infer the first element.
5963 assert not inferred.elts
5964
5965
58655966 if __name__ == "__main__":
58665967 unittest.main()
00 # Copyright (c) 2007-2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
11 # Copyright (c) 2010 Daniel Harding <dharding@gmail.com>
2 # Copyright (c) 2014-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2014-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2014 Google, Inc.
44 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
55 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
66 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
7 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
78
89 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
910 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # -*- coding: utf-8 -*-
11 # Copyright (c) 2006, 2009-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
22 # Copyright (c) 2013 AndroWiiid <androwiiid@gmail.com>
3 # Copyright (c) 2014-2019 Claudiu Popa <pcmanticore@gmail.com>
3 # Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
44 # Copyright (c) 2014 Google, Inc.
55 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
66 # Copyright (c) 2017 Chris Philip <chrisp533@gmail.com>
1010 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
1111 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
1212 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
13 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
14 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
1315 # Copyright (c) 2020 Anubhav <35621759+anubh-v@users.noreply.github.com>
1416
1517 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1618 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1719
20 import builtins
1821 import os
1922 import platform
2023 import site
2225 import unittest
2326
2427 import pkg_resources
25 import six
2628 import time
2729
2830 import astroid
3133 from . import resources
3234
3335
34 BUILTINS = six.moves.builtins.__name__
36 BUILTINS = builtins.__name__
3537
3638
3739 def _get_file_from_object(obj):
99 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
1010 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
1111 # Copyright (c) 2019 markmcclain <markmcclain@users.noreply.github.com>
12 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
13 # Copyright (c) 2020 Peter Kolbus <peter.kolbus@gmail.com>
1214
1315 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1416 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
8183
8284 def test_raise_load_module_from_name_1(self):
8385 self.assertRaises(
84 ImportError, modutils.load_module_from_name, "os.path", use_sys=0
86 ImportError, modutils.load_module_from_name, "_this_module_does_not_exist_"
8587 )
8688
8789
296298 def test_knownValues_is_relative_3(self):
297299 self.assertFalse(modutils.is_relative("astroid", astroid.__path__[0]))
298300
301 def test_deep_relative(self):
302 self.assertTrue(modutils.is_relative("ElementTree", xml.etree.__path__[0]))
303
304 def test_deep_relative2(self):
305 self.assertFalse(modutils.is_relative("ElementTree", xml.__path__[0]))
306
307 def test_deep_relative3(self):
308 self.assertTrue(modutils.is_relative("etree.ElementTree", xml.__path__[0]))
309
310 def test_deep_relative4(self):
311 self.assertTrue(modutils.is_relative("etree.gibberish", xml.__path__[0]))
312
313 def test_is_relative_bad_path(self):
314 self.assertFalse(
315 modutils.is_relative("ElementTree", os.path.join(xml.__path__[0], "ftree"))
316 )
317
299318
300319 class GetModuleFilesTest(unittest.TestCase):
301320 def test_get_module_files_1(self):
00 # Copyright (c) 2006-2007, 2009-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
11 # Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
2 # Copyright (c) 2013-2020 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2013-2021 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2014 Google, Inc.
44 # Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
55 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
1111 # Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>
1212 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
1313 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
14 # Copyright (c) 2019-2020 Ashley Whetter <ashley@awhetter.co.uk>
14 # Copyright (c) 2019-2021 Ashley Whetter <ashley@awhetter.co.uk>
1515 # Copyright (c) 2019 Alex Hall <alex.mojaki@gmail.com>
1616 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
17 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
1718
1819 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1920 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
2021
2122 """tests for specific behaviour of astroid nodes
2223 """
24 import builtins
2325 import os
2426 import sys
2527 import textwrap
2830 import platform
2931
3032 import pytest
31 import six
3233
3334 import astroid
3435 from astroid import bases
4546
4647
4748 abuilder = builder.AstroidBuilder()
48 BUILTINS = six.moves.builtins.__name__
49 BUILTINS = builtins.__name__
4950 PY38 = sys.version_info[:2] >= (3, 8)
5051 try:
5152 import typed_ast # pylint: disable=unused-import
6667 self.assertEqual(build("(1, )").as_string(), "(1, )")
6768 self.assertEqual(build("1, 2, 3").as_string(), "(1, 2, 3)")
6869
69 @test_utils.require_version(minver="3.0")
7070 def test_func_signature_issue_185(self):
7171 code = textwrap.dedent(
7272 """
135135 ast = abuilder.string_build(code)
136136 self.assertMultiLineEqual(ast.as_string(), code)
137137
138 @test_utils.require_version("3.0")
139138 def test_3k_as_string(self):
140139 """check as_string for python 3k syntax"""
141140 code = """print()
400399 self.assertEqual(self.astroid.body[0].block_range(6), (6, 6))
401400
402401
403 @unittest.skipIf(six.PY3, "Python 2 specific test.")
404 class TryExcept2xNodeTest(_NodeTest):
405 CODE = """
406 try:
407 hello
408 except AttributeError, (retval, desc):
409 pass
410 """
411
412 def test_tuple_attribute(self):
413 handler = self.astroid.body[0].handlers[0]
414 self.assertIsInstance(handler.name, nodes.Tuple)
415
416
417402 class ImportNodeTest(resources.SysPathSetup, unittest.TestCase):
418403 def setUp(self):
419404 super(ImportNodeTest, self).setUp()
579564
580565
581566 class AnnAssignNodeTest(unittest.TestCase):
582 @test_utils.require_version(minver="3.6")
583567 def test_primitive(self):
584568 code = textwrap.dedent(
585569 """
593577 self.assertEqual(assign.value.value, 5)
594578 self.assertEqual(assign.simple, 1)
595579
596 @test_utils.require_version(minver="3.6")
597580 def test_primitive_without_initial_value(self):
598581 code = textwrap.dedent(
599582 """
606589 self.assertEqual(assign.annotation.name, "str")
607590 self.assertEqual(assign.value, None)
608591
609 @test_utils.require_version(minver="3.6")
610592 def test_complex(self):
611593 code = textwrap.dedent(
612594 """
619601 self.assertIsInstance(assign.annotation, astroid.Subscript)
620602 self.assertIsInstance(assign.value, astroid.Dict)
621603
622 @test_utils.require_version(minver="3.6")
623604 def test_as_string(self):
624605 code = textwrap.dedent(
625606 """
653634 "(no line number on function args)"
654635 )
655636
656 @test_utils.require_version(minver="3.0")
657637 def test_kwoargs(self):
658638 ast = builder.parse(
659639 """
861841 self.assertIsInstance(module.body[6].value, nodes.GeneratorExp)
862842
863843
864 @test_utils.require_version("3.5")
865844 class Python35AsyncTest(unittest.TestCase):
866845 def test_async_await_keywords(self):
867846 async_def, async_for, async_with, await_node = builder.extract_node(
961940 with self.assertRaises(exceptions.AstroidSyntaxError):
962941 builder.extract_node("(1, ) = 3")
963942
964 @test_utils.require_version(minver="3.5")
965943 def test_starred_load(self):
966944 node = builder.extract_node("a = *b")
967945 starred = node.value
968946 self.assertIs(starred.ctx, astroid.Load)
969947
970 @test_utils.require_version(minver="3.0")
971948 def test_starred_store(self):
972949 node = builder.extract_node("a, *b = 1, 2")
973950 starred = node.targets[0].elts[1]
11801157 assert actual_arg.as_string() == expected_arg
11811158
11821159
1160 @pytest.mark.skipif(not HAS_TYPED_AST, reason="requires typed_ast")
1161 def test_correct_function_type_comment_parent():
1162 data = """
1163 def f(a):
1164 # type: (A) -> A
1165 pass
1166 """
1167 astroid = builder.parse(data)
1168 f = astroid.body[0]
1169 assert f.type_comment_args[0].parent is f
1170 assert f.type_comment_returns.parent is f
1171
1172
11831173 def test_is_generator_for_yield_assignments():
11841174 node = astroid.extract_node(
11851175 """
11991189
12001190
12011191 class AsyncGeneratorTest:
1202 @test_utils.require_version(minver="3.6")
12031192 def test_async_generator(self):
12041193 node = astroid.extract_node(
12051194 """
12171206 assert inferred.pytype() == "builtins.async_generator"
12181207 assert inferred.display_type() == "AsyncGenerator"
12191208
1220 @test_utils.require_version(maxver="3.5")
12211209 def test_async_generator_is_generator_on_older_python(self):
12221210 node = astroid.extract_node(
12231211 """
13461334 assert bool(node.is_generator())
13471335
13481336
1337 def test_is_generator_for_yield_in_if():
1338 code = """
1339 import asyncio
1340
1341 def paused_iter(iterable):
1342 if (yield from asyncio.sleep(0.01)):
1343 pass
1344 return
1345 """
1346 node = astroid.extract_node(code)
1347 assert bool(node.is_generator())
1348
1349
1350 def test_is_generator_for_yield_in_aug_assign():
1351 code = """
1352 def test():
1353 buf = ''
1354 while True:
1355 buf += yield
1356 """
1357 node = astroid.extract_node(code)
1358 assert bool(node.is_generator())
1359
1360
13491361 if __name__ == "__main__":
13501362 unittest.main()
33 # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
44 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
55 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
6 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
67 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
78 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
89
430431 for ast_node in ast_nodes[7:9]:
431432 self.assertIs(next(ast_node.infer()), astroid.Uninferable)
432433
433 @test_utils.require_version(minver="3.0")
434434 def test_empty_return_annotation(self):
435435 ast_node = builder.extract_node(
436436 """
442442 self.assertIsInstance(annotations, astroid.Dict)
443443 self.assertEqual(len(annotations.items), 0)
444444
445 @test_utils.require_version(minver="3.0")
446445 def test_builtin_dunder_init_does_not_crash_when_accessing_annotations(self):
447446 ast_node = builder.extract_node(
448447 """
456455 self.assertIsInstance(inferred, astroid.Dict)
457456 self.assertEqual(len(inferred.items), 0)
458457
459 @test_utils.require_version(minver="3.0")
460458 def test_annotations_kwdefaults(self):
461459 ast_node = builder.extract_node(
462460 """
584582 inferred = next(node.infer())
585583 assert isinstance(inferred, astroid.Const)
586584 assert inferred.value == value
585
586 def test_unicodedecodeerror(self):
587 code = """
588 try:
589 raise UnicodeDecodeError("utf-8", "blob", 0, 1, "reason")
590 except UnicodeDecodeError as error:
591 error.object[:1] #@
592 """
593 node = builder.extract_node(code)
594 inferred = next(node.infer())
595 assert isinstance(inferred, astroid.Const)
587596
588597 def test_import_error(self):
589598 ast_nodes = builder.extract_node(
11 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
33 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
4 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
45
56 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
67 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1314 from astroid import exceptions
1415 from astroid import nodes
1516 from astroid import objects
16 from astroid import test_utils
1717
1818
1919 class ObjectsTest(unittest.TestCase):
9696 self.assertIsInstance(second, bases.Instance)
9797 self.assertEqual(second.qname(), "%s.super" % bases.BUILTINS)
9898
99 @test_utils.require_version(minver="3.0")
10099 def test_no_arguments_super(self):
101100 ast_nodes = builder.extract_node(
102101 """
00 # -*- coding: utf-8 -*-
1 # Copyright (c) 2015-2019 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2015-2020 Claudiu Popa <pcmanticore@gmail.com>
22 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
33 # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
44 # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
55 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
66 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
7 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
8 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
79
810 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
911 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
1719
1820 import astroid
1921 from astroid import extract_node
20 from astroid.test_utils import require_version
2122 from astroid import InferenceError
2223 from astroid import nodes
2324 from astroid import util
6667 for2_assnode = next(assign_stmts[1].nodes_of_class(AssignName))
6768 self.assertRaises(InferenceError, list, for2_assnode.assigned_stmts())
6869
69 @require_version(minver="3.0")
7070 def test_assigned_stmts_starred_for(self):
7171 assign_stmts = extract_node(
7272 """
100100 starred = next(assign_stmt.nodes_of_class(Starred))
101101 self.assertRaises(InferenceError, list, starred.assigned_stmts())
102102
103 @require_version(minver="3.0")
104103 def test_assigned_stmts_starred_assnames(self):
105104 self._helper_starred_expected_const("a, *b = (1, 2, 3, 4) #@", [2, 3, 4])
106105 self._helper_starred_expected_const("*a, b = (1, 2, 3) #@", [1, 2])
109108 self._helper_starred_expected_const("*b, a = (1, 2) #@", [1])
110109 self._helper_starred_expected_const("[*b] = (1, 2) #@", [1, 2])
111110
112 @require_version(minver="3.0")
113111 def test_assigned_stmts_starred_yes(self):
114112 # Not something iterable and known
115113 self._helper_starred_expected("a, *b = range(3) #@", util.Uninferable)
127125 "a, (*b, c), d = (1, (2, 3, 4), 5) #@", util.Uninferable
128126 )
129127
130 @require_version(minver="3.0")
131128 def test_assign_stmts_starred_fails(self):
132129 # Too many starred
133130 self._helper_starred_inference_error("a, *b, *c = (1, 2, 3) #@")
158155 assigned = list(simple_mul_assnode_2.assigned_stmts())
159156 self.assertNameNodesEqual(["c"], assigned)
160157
161 @require_version(minver="3.6")
162158 def test_assigned_stmts_annassignments(self):
163159 annassign_stmts = extract_node(
164160 """
00 # -*- coding: utf-8 -*-
11 # Copyright (c) 2010, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
22 # Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
3 # Copyright (c) 2013-2018 Claudiu Popa <pcmanticore@gmail.com>
3 # Copyright (c) 2013-2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
44 # Copyright (c) 2014 Google, Inc.
55 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
66 # Copyright (c) 2016 Jared Garst <jgarst@users.noreply.github.com>
77 # Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com>
88 # Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com>
99 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
10 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
11 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
1012
1113 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1214 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
2628 def setUpClass(cls):
2729 cls.builder = AstroidBuilder()
2830
29 @require_version("3.4")
3031 def test_starred_notation(self):
3132 astroid = self.builder.string_build("*a, b = [1, 2, 3]", "test", "test")
3233
3536
3637 self.assertTrue(isinstance(node.assign_type(), Assign))
3738
38 @require_version("3.4")
3939 def test_yield_from(self):
4040 body = dedent(
4141 """
5252 self.assertIsInstance(yieldfrom_stmt.value, YieldFrom)
5353 self.assertEqual(yieldfrom_stmt.as_string(), "yield from iter([1, 2])")
5454
55 @require_version("3.4")
5655 def test_yield_from_is_generator(self):
5756 body = dedent(
5857 """
6564 self.assertIsInstance(func, FunctionDef)
6665 self.assertTrue(func.is_generator())
6766
68 @require_version("3.4")
6967 def test_yield_from_as_string(self):
7068 body = dedent(
7169 """
8078
8179 # metaclass tests
8280
83 @require_version("3.4")
8481 def test_simple_metaclass(self):
8582 astroid = self.builder.string_build("class Test(metaclass=type): pass")
8683 klass = astroid.body[0]
8986 self.assertIsInstance(metaclass, ClassDef)
9087 self.assertEqual(metaclass.name, "type")
9188
92 @require_version("3.4")
9389 def test_metaclass_error(self):
9490 astroid = self.builder.string_build("class Test(metaclass=typ): pass")
9591 klass = astroid.body[0]
9692 self.assertFalse(klass.metaclass())
9793
98 @require_version("3.4")
9994 def test_metaclass_imported(self):
10095 astroid = self.builder.string_build(
10196 dedent(
110105 self.assertIsInstance(metaclass, ClassDef)
111106 self.assertEqual(metaclass.name, "ABCMeta")
112107
113 @require_version("3.4")
114108 def test_metaclass_multiple_keywords(self):
115109 astroid = self.builder.string_build(
116110 "class Test(magic=None, metaclass=type): pass"
121115 self.assertIsInstance(metaclass, ClassDef)
122116 self.assertEqual(metaclass.name, "type")
123117
124 @require_version("3.4")
125118 def test_as_string(self):
126119 body = dedent(
127120 """
135128 klass.as_string(), "\n\nclass Test(metaclass=ABCMeta):\n pass\n"
136129 )
137130
138 @require_version("3.4")
139131 def test_old_syntax_works(self):
140132 astroid = self.builder.string_build(
141133 dedent(
150142 metaclass = klass.metaclass()
151143 self.assertIsNone(metaclass)
152144
153 @require_version("3.4")
154145 def test_metaclass_yes_leak(self):
155146 astroid = self.builder.string_build(
156147 dedent(
165156 klass = astroid["Meta"]
166157 self.assertIsNone(klass.metaclass())
167158
168 @require_version("3.4")
169159 def test_parent_metaclass(self):
170160 astroid = self.builder.string_build(
171161 dedent(
182172 self.assertIsInstance(metaclass, ClassDef)
183173 self.assertEqual(metaclass.name, "ABCMeta")
184174
185 @require_version("3.4")
186175 def test_metaclass_ancestors(self):
187176 astroid = self.builder.string_build(
188177 dedent(
211200 self.assertIsInstance(meta, ClassDef)
212201 self.assertEqual(meta.name, metaclass)
213202
214 @require_version("3.4")
215203 def test_annotation_support(self):
216204 astroid = self.builder.string_build(
217205 dedent(
254242 self.assertEqual(func.args.annotations[1].name, "str")
255243 self.assertIsNone(func.returns)
256244
257 @require_version("3.4")
258245 def test_kwonlyargs_annotations_supper(self):
259246 node = self.builder.string_build(
260247 dedent(
275262 self.assertIsNone(arguments.kwonlyargs_annotations[3])
276263 self.assertIsNone(arguments.kwonlyargs_annotations[4])
277264
278 @require_version("3.4")
279265 def test_annotation_as_string(self):
280266 code1 = dedent(
281267 """
291277 func = extract_node(code)
292278 self.assertEqual(func.as_string(), code)
293279
294 @require_version("3.5")
295280 def test_unpacking_in_dicts(self):
296281 code = "{'x': 1, **{'y': 2}}"
297282 node = extract_node(code)
300285 self.assertIsInstance(keys[0], nodes.Const)
301286 self.assertIsInstance(keys[1], nodes.DictUnpack)
302287
303 @require_version("3.5")
304288 def test_nested_unpacking_in_dicts(self):
305289 code = "{'x': 1, **{'y': 2, **{'z': 3}}}"
306290 node = extract_node(code)
307291 self.assertEqual(node.as_string(), code)
308292
309 @require_version("3.5")
310293 def test_unpacking_in_dict_getitem(self):
311294 node = extract_node("{1:2, **{2:3, 3:4}, **{5: 6}}")
312295 for key, expected in ((1, 2), (2, 3), (3, 4), (5, 6)):
314297 self.assertIsInstance(value, nodes.Const)
315298 self.assertEqual(value.value, expected)
316299
317 @require_version("3.6")
318300 def test_format_string(self):
319301 code = "f'{greetings} {person}'"
320302 node = extract_node(code)
321303 self.assertEqual(node.as_string(), code)
322304
323 @require_version("3.6")
324305 def test_underscores_in_numeral_literal(self):
325306 pairs = [("10_1000", 101000), ("10_000_000", 10000000), ("0x_FF_FF", 65535)]
326307 for value, expected in pairs:
329310 self.assertIsInstance(inferred, nodes.Const)
330311 self.assertEqual(inferred.value, expected)
331312
332 @require_version("3.6")
333313 def test_async_comprehensions(self):
334314 async_comprehensions = [
335315 extract_node(
378358 node = extract_node(comp)
379359 self.assertTrue(node.generators[0].is_async)
380360
381 @require_version("3.6")
382361 def test_async_comprehensions_as_string(self):
383362 func_bodies = [
384363 "return [i async for i in aiter() if condition(i)]",
00 # Copyright (c) 2013 AndroWiiid <androwiiid@gmail.com>
1 # Copyright (c) 2014-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
1 # Copyright (c) 2014-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
22 # Copyright (c) 2014 Google, Inc.
33 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
44 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
55 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
66 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
7 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
8 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
79
810 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
911 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
2022 build_function,
2123 build_from_import,
2224 )
23 from astroid import test_utils
2425
2526
2627 class RawBuildingTC(unittest.TestCase):
6869 self.assertEqual(len(names), len(node.names))
6970
7071 @unittest.skipIf(platform.python_implementation() == "PyPy", "Only affects CPython")
71 @test_utils.require_version(minver="3.0")
7272 def test_io_is__io(self):
7373 # _io module calls itself io. This leads
7474 # to cyclic dependencies when astroid tries to resolve
66 # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
77 # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
88 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
9 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
910 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
11 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
1012
1113 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
1214 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
2123 from astroid import exceptions
2224 from astroid.raw_building import build_module
2325 from astroid.manager import AstroidManager
24 from astroid.test_utils import require_version
2526 from astroid import transforms
2627 from . import resources
2728
9293 data = """
9394 from numpy import multiply
9495
95 multiply(1, 2, 3)
96 multiply([1, 2], [3, 4])
9697 """
9798 astroid = builder.string_build(data, __name__, __file__)
9899 callfunc = astroid.body[1].value.func
99100 inferred = callfunc.inferred()
100101 self.assertEqual(len(inferred), 1)
101102
102 @require_version("3.0")
103103 def test_nameconstant(self):
104104 # used to fail for Python 3.4
105105 builder = AstroidBuilder()
323323 a = property(lambda x: x, lambda x: x)
324324
325325
326 def test_ancestor_looking_up_redefined_function():
327 code = """
328 class Foo:
329 def _format(self):
330 pass
331
332 def format(self):
333 self.format = self._format
334 self.format()
335 Foo
336 """
337 node = extract_node(code)
338 inferred = next(node.infer())
339 ancestor = next(inferred.ancestors())
340 _, found = ancestor.lookup("format")
341 assert len(found) == 1
342 assert isinstance(found[0], nodes.FunctionDef)
343
344
345 def test_crash_in_dunder_inference_prevented():
346 code = """
347 class MyClass():
348 def fu(self, objects):
349 delitem = dict.__delitem__.__get__(self, dict)
350 delitem #@
351 """
352 inferred = next(extract_node(code).infer())
353 assert "builtins.dict.__delitem__" == inferred.qname()
354
355
326356 if __name__ == "__main__":
327357 unittest.main()
1414 # Copyright (c) 2018-2019 Ville Skyttä <ville.skytta@iki.fi>
1515 # Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>
1616 # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
17 # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
1718 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
1819 # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
1920 # Copyright (c) 2019 Peter de Blanc <peter@standard.ai>
20 # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
21 # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
22 # Copyright (c) 2020 Tim Martin <tim@asymptotic.co.uk>
2123
2224 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2325 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
5153 from astroid.bases import BUILTINS, Instance, BoundMethod, UnboundMethod, Generator
5254 from astroid import test_utils
5355 from . import resources
56
57 try:
58 import six # pylint: disable=unused-import
59
60 HAS_SIX = True
61 except ImportError:
62 HAS_SIX = False
5463
5564
5665 def _test_dict_interface(self, node, test_attr):
333342 func = self.module["four_args"]
334343 self.assertEqual(func.args.format_args(), "a, b, c, d")
335344
336 @test_utils.require_version("3.0")
337345 def test_format_args_keyword_only_args(self):
338346 node = (
339347 builder.parse(
594602 self.assertIsInstance(inferred, nodes.Const)
595603 self.assertEqual(inferred.value, 42)
596604
597 @test_utils.require_version(minver="3.0")
598605 def test_return_annotation_is_not_the_last(self):
599606 func = builder.extract_node(
600607 """
608615 self.assertIsInstance(last_child, nodes.Return)
609616 self.assertEqual(func.tolineno, 5)
610617
611 @test_utils.require_version(minver="3.6")
612618 def test_method_init_subclass(self):
613619 klass = builder.extract_node(
614620 """
621627 self.assertEqual([n.name for n in method.args.args], ["cls"])
622628 self.assertEqual(method.type, "classmethod")
623629
624 @test_utils.require_version(minver="3.0")
625630 def test_dunder_class_local_to_method(self):
626631 node = builder.extract_node(
627632 """
634639 self.assertIsInstance(inferred, nodes.ClassDef)
635640 self.assertEqual(inferred.name, "MyClass")
636641
637 @test_utils.require_version(minver="3.0")
638642 def test_dunder_class_local_to_function(self):
639643 node = builder.extract_node(
640644 """
645649 with self.assertRaises(NameInferenceError):
646650 next(node.infer())
647651
648 @test_utils.require_version(minver="3.0")
649652 def test_dunder_class_local_to_classmethod(self):
650653 node = builder.extract_node(
651654 """
10901093 for klass in ast_nodes:
10911094 self.assertEqual(None, klass.metaclass())
10921095
1096 @unittest.skipUnless(HAS_SIX, "These tests require the six library")
10931097 def test_metaclass_generator_hack(self):
10941098 klass = builder.extract_node(
10951099 """
11021106 self.assertEqual(["object"], [base.name for base in klass.ancestors()])
11031107 self.assertEqual("type", klass.metaclass().name)
11041108
1105 def test_using_six_add_metaclass(self):
1109 def test_add_metaclass(self):
11061110 klass = builder.extract_node(
11071111 """
1108 import six
11091112 import abc
11101113
1111 @six.add_metaclass(abc.ABCMeta)
1112 class WithMeta(object):
1114 class WithMeta(object, metaclass=abc.ABCMeta):
11131115 pass
11141116 """
11151117 )
11181120 self.assertIsInstance(metaclass, scoped_nodes.ClassDef)
11191121 self.assertIn(metaclass.qname(), ("abc.ABCMeta", "_py_abc.ABCMeta"))
11201122
1123 @unittest.skipUnless(HAS_SIX, "These tests require the six library")
11211124 def test_using_invalid_six_add_metaclass_call(self):
11221125 klass = builder.extract_node(
11231126 """
12701273 def assertEqualMro(self, klass, expected_mro):
12711274 self.assertEqual([member.name for member in klass.mro()], expected_mro)
12721275
1276 @unittest.skipUnless(HAS_SIX, "These tests require the six library")
12731277 def test_with_metaclass_mro(self):
12741278 astroid = builder.parse(
12751279 """
14161420 ],
14171421 )
14181422
1423 def test_mro_with_attribute_classes(self):
1424 cls = builder.extract_node(
1425 """
1426 class A:
1427 pass
1428 class B:
1429 pass
1430 scope = object()
1431 scope.A = A
1432 scope.B = B
1433 class C(scope.A, scope.B):
1434 pass
1435 """
1436 )
1437 self.assertEqualMro(cls, ["C", "A", "B", "object"])
1438
14191439 def test_generator_from_infer_call_result_parent(self):
14201440 func = builder.extract_node(
14211441 """
14811501 def test_metaclass_lookup_inference_errors(self):
14821502 module = builder.parse(
14831503 """
1484 import six
1485
14861504 class Metaclass(type):
14871505 foo = lala
14881506
1489 @six.add_metaclass(Metaclass)
1490 class B(object): pass
1507 class B(object, metaclass=Metaclass): pass
14911508 """
14921509 )
14931510 cls = module["B"]
14961513 def test_metaclass_lookup(self):
14971514 module = builder.parse(
14981515 """
1499 import six
1500
15011516 class Metaclass(type):
15021517 foo = 42
15031518 @classmethod
15121527 def static():
15131528 pass
15141529
1515 @six.add_metaclass(Metaclass)
1516 class A(object):
1530 class A(object, metaclass=Metaclass):
15171531 pass
15181532 """
15191533 )
17331747 parent = bind.scope()
17341748 self.assertEqual(len(parent.extra_decorators), 0)
17351749
1736 @test_utils.require_version(minver="3.0")
17371750 def test_class_keywords(self):
17381751 data = """
17391752 class TestKlass(object, metaclass=TestMetaKlass,
0 # Copyright (c) 2015-2018 Claudiu Popa <pcmanticore@gmail.com>
0 # Copyright (c) 2015-2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
11 # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
22 # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
33 # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
44 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
5 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
56
67 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
78 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
00 # Copyright (c) 2008-2010, 2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
11 # Copyright (c) 2014 Google, Inc.
2 # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
2 # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
33 # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
44 # Copyright (c) 2016 Dave Baum <dbaum@google.com>
55 # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
6 # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com>
67
78 # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
89 # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER