New upstream version 2.5
Sandro Tosi
3 years ago
0 | 0 | =================== |
1 | 1 | astroid's ChangeLog |
2 | 2 | =================== |
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 | ||
3 | 143 | |
4 | 144 | What's New in astroid 2.4.2? |
5 | 145 | ============================ |
0 | 0 | Metadata-Version: 1.2 |
1 | 1 | Name: astroid |
2 | Version: 2.4.2 | |
2 | Version: 2.5 | |
3 | 3 | Summary: An abstract syntax tree for Python with inference support. |
4 | 4 | Home-page: https://github.com/PyCQA/astroid |
5 | 5 | Author: Python Code Quality Authority |
86 | 86 | --------------- |
87 | 87 | |
88 | 88 | 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). | |
90 | 91 | |
91 | 92 | Test |
92 | 93 | ---- |
102 | 103 | Classifier: Topic :: Software Development :: Quality Assurance |
103 | 104 | Classifier: Programming Language :: Python |
104 | 105 | Classifier: Programming Language :: Python :: 3 |
105 | Classifier: Programming Language :: Python :: 3.5 | |
106 | 106 | Classifier: Programming Language :: Python :: 3.6 |
107 | 107 | Classifier: Programming Language :: Python :: 3.7 |
108 | 108 | Classifier: Programming Language :: Python :: 3.8 |
109 | Classifier: Programming Language :: Python :: 3.9 | |
109 | 110 | Classifier: Programming Language :: Python :: Implementation :: CPython |
110 | 111 | Classifier: Programming Language :: Python :: Implementation :: PyPy |
111 | Requires-Python: >=3.5 | |
112 | Requires-Python: >=3.6 |
78 | 78 | --------------- |
79 | 79 | |
80 | 80 | 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). | |
82 | 83 | |
83 | 84 | Test |
84 | 85 | ---- |
0 | 0 | # Copyright (c) 2006-2013, 2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
1 | 1 | # Copyright (c) 2014 Google, Inc. |
2 | 2 | # 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> | |
4 | 4 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
5 | 5 | # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com> |
6 | 6 | # Copyright (c) 2016 Moises Lopez <moylop260@vauxoo.com> |
7 | 7 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
8 | 8 | # Copyright (c) 2019 Nick Drozd <nicholasdrozd@gmail.com> |
9 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
9 | 10 | |
10 | 11 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
11 | 12 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # -*- coding: utf-8 -*- |
1 | 1 | # 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> | |
3 | 3 | # Copyright (c) 2014 Google, Inc. |
4 | 4 | # Copyright (c) 2015-2017 Ceridwen <ceridwenv@gmail.com> |
5 | 5 | # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org> |
13 | 13 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
14 | 14 | # Copyright (c) 2019 Uilian Ries <uilianries@gmail.com> |
15 | 15 | # 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> | |
16 | 20 | # Copyright (c) 2020 Michael <michael-k@users.noreply.github.com> |
17 | 21 | |
18 | 22 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
20 | 24 | |
21 | 25 | """astroid packaging information""" |
22 | 26 | |
23 | version = "2.4.2" | |
27 | version = "2.5" | |
24 | 28 | numversion = tuple(int(elem) for elem in version.split(".") if elem.isdigit()) |
25 | 29 | |
26 | 30 | extras_require = {} |
27 | 31 | 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", | |
31 | 34 | 'typed-ast>=1.4.0,<1.5;implementation_name== "cpython" and python_version<"3.8"', |
32 | 35 | ] |
33 | 36 | |
46 | 49 | "Topic :: Software Development :: Quality Assurance", |
47 | 50 | "Programming Language :: Python", |
48 | 51 | "Programming Language :: Python :: 3", |
49 | "Programming Language :: Python :: 3.5", | |
50 | 52 | "Programming Language :: Python :: 3.6", |
51 | 53 | "Programming Language :: Python :: 3.7", |
52 | 54 | "Programming Language :: Python :: 3.8", |
55 | "Programming Language :: Python :: 3.9", | |
53 | 56 | "Programming Language :: Python :: Implementation :: CPython", |
54 | 57 | "Programming Language :: Python :: Implementation :: PyPy", |
55 | 58 | ] |
2 | 2 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
3 | 3 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
4 | 4 | # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> |
5 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
5 | 6 | |
6 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
7 | 8 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
172 | 173 | |
173 | 174 | # Too many arguments given and no variable arguments. |
174 | 175 | 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: | |
176 | 177 | raise exceptions.InferenceError( |
177 | 178 | "Too many positional arguments " |
178 | 179 | "passed to {func!r} that does " |
291 | 292 | except exceptions.NoDefault: |
292 | 293 | pass |
293 | 294 | raise exceptions.InferenceError( |
294 | "No value found for argument {name} to " "{func!r}", | |
295 | "No value found for argument {arg} to {func!r}", | |
295 | 296 | call_site=self, |
296 | 297 | func=funcnode, |
297 | 298 | arg=name, |
0 | 0 | # -*- coding: utf-8 -*- |
1 | # Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com> | |
1 | # Copyright (c) 2014-2021 Claudiu Popa <pcmanticore@gmail.com> | |
2 | 2 | # Copyright (c) 2014-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
3 | 3 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
4 | 4 | # Copyright (c) 2015 Rene Zhang <rz99@cornell.edu> |
5 | 5 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
6 | 6 | # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi> |
7 | # Copyright (c) 2019-2020 Bryce Guinta <bryce.guinta@protonmail.com> | |
7 | 8 | # Copyright (c) 2019 Stanislav Levin <slev@altlinux.org> |
8 | 9 | # Copyright (c) 2019 David Liu <david@cs.toronto.edu> |
9 | # Copyright (c) 2019 Bryce Guinta <bryce.guinta@protonmail.com> | |
10 | 10 | # 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> | |
11 | 14 | |
12 | 15 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
13 | 16 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
17 | 20 | from functools import partial |
18 | 21 | from textwrap import dedent |
19 | 22 | |
20 | import six | |
21 | 23 | from astroid import ( |
22 | 24 | MANAGER, |
23 | 25 | UseInferenceDefault, |
39 | 41 | |
40 | 42 | OBJECT_DUNDER_NEW = "object.__new__" |
41 | 43 | |
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): | |
44 | 127 | """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 | ) | |
88 | 128 | code = code.format(rvalue=rvalue) |
89 | 129 | fake = AstroidBuilder(MANAGER).string_build(code)["whatever"] |
90 | 130 | for method in fake.mymethods(): |
105 | 145 | |
106 | 146 | _extend_builtins( |
107 | 147 | { |
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="''"), | |
110 | 150 | } |
111 | 151 | ) |
112 | 152 | |
164 | 204 | if not transformed: |
165 | 205 | try: |
166 | 206 | inferred = next(arg.infer(context=context)) |
167 | except (InferenceError, StopIteration): | |
168 | raise UseInferenceDefault() | |
207 | except (InferenceError, StopIteration) as exc: | |
208 | raise UseInferenceDefault from exc | |
169 | 209 | if inferred is util.Uninferable: |
170 | raise UseInferenceDefault() | |
210 | raise UseInferenceDefault | |
171 | 211 | transformed = transform(inferred) |
172 | 212 | if not transformed or transformed is util.Uninferable: |
173 | raise UseInferenceDefault() | |
213 | raise UseInferenceDefault | |
174 | 214 | return transformed |
175 | 215 | |
176 | 216 | |
184 | 224 | # TODO: Does not handle deduplication for sets. |
185 | 225 | elts = [] |
186 | 226 | for element in arg.elts: |
227 | if not element: | |
228 | continue | |
187 | 229 | inferred = helpers.safe_infer(element, context=context) |
188 | 230 | if inferred: |
189 | 231 | evaluated_object = nodes.EvaluatedObject( |
195 | 237 | if not all(isinstance(elt[0], nodes.Const) for elt in arg.items): |
196 | 238 | raise UseInferenceDefault() |
197 | 239 | 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)): | |
201 | 241 | elts = arg.value |
202 | 242 | else: |
203 | 243 | return |
266 | 306 | is_iterable = lambda n: isinstance(n, (nodes.List, nodes.Tuple, nodes.Set)) |
267 | 307 | try: |
268 | 308 | inferred = next(arg.infer(context)) |
269 | except (InferenceError, NameInferenceError): | |
270 | raise UseInferenceDefault() | |
309 | except (InferenceError, NameInferenceError) as exc: | |
310 | raise UseInferenceDefault from exc | |
271 | 311 | if isinstance(inferred, nodes.Dict): |
272 | 312 | items = inferred.items |
273 | 313 | elif is_iterable(inferred): |
370 | 410 | else: |
371 | 411 | try: |
372 | 412 | 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 | |
375 | 415 | try: |
376 | 416 | 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 | |
379 | 419 | |
380 | 420 | if mro_pointer is util.Uninferable or mro_type is util.Uninferable: |
381 | 421 | # No way we could understand this. |
396 | 436 | try: |
397 | 437 | obj = next(node.args[0].infer(context=context)) |
398 | 438 | attr = next(node.args[1].infer(context=context)) |
399 | except InferenceError: | |
400 | raise UseInferenceDefault | |
439 | except InferenceError as exc: | |
440 | raise UseInferenceDefault from exc | |
401 | 441 | |
402 | 442 | if obj is util.Uninferable or attr is util.Uninferable: |
403 | 443 | # If one of the arguments is something we can't infer, |
405 | 445 | # which is unknown. |
406 | 446 | return util.Uninferable, util.Uninferable |
407 | 447 | |
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) | |
411 | 449 | if not is_string: |
412 | 450 | raise UseInferenceDefault |
413 | 451 | |
436 | 474 | # Try to infer the default and return it instead. |
437 | 475 | try: |
438 | 476 | return next(node.args[2].infer(context=context)) |
439 | except InferenceError: | |
440 | raise UseInferenceDefault | |
477 | except InferenceError as exc: | |
478 | raise UseInferenceDefault from exc | |
441 | 479 | |
442 | 480 | raise UseInferenceDefault |
443 | 481 | |
504 | 542 | getter = node.args[0] |
505 | 543 | try: |
506 | 544 | inferred = next(getter.infer(context=context)) |
507 | except InferenceError: | |
508 | raise UseInferenceDefault | |
545 | except InferenceError as exc: | |
546 | raise UseInferenceDefault from exc | |
509 | 547 | |
510 | 548 | if not isinstance(inferred, (nodes.FunctionDef, nodes.Lambda)): |
511 | 549 | raise UseInferenceDefault |
672 | 710 | class_container = _class_or_tuple_to_container( |
673 | 711 | class_or_tuple_node, context=context |
674 | 712 | ) |
675 | except InferenceError: | |
676 | raise UseInferenceDefault | |
713 | except InferenceError as exc: | |
714 | raise UseInferenceDefault from exc | |
677 | 715 | try: |
678 | 716 | isinstance_bool = helpers.object_isinstance(obj_node, class_container, context) |
679 | 717 | except AstroidTypeError as exc: |
680 | raise UseInferenceDefault("TypeError: " + str(exc)) | |
718 | raise UseInferenceDefault("TypeError: " + str(exc)) from exc | |
681 | 719 | except MroError as exc: |
682 | 720 | raise UseInferenceDefault from exc |
683 | 721 | if isinstance_bool is util.Uninferable: |
720 | 758 | "({len}) given".format(len=len(call.positional_arguments)) |
721 | 759 | ) |
722 | 760 | [argument_node] = call.positional_arguments |
761 | ||
723 | 762 | try: |
724 | 763 | return nodes.Const(helpers.object_len(argument_node, context=context)) |
725 | 764 | except (AstroidTypeError, InferenceError) as exc: |
0 | 0 | # -*- coding: utf-8 -*- |
1 | # Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com> | |
1 | # Copyright (c) 2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com> | |
2 | 2 | # Copyright (c) 2016-2017 Łukasz Rogalski <rogalski.91@gmail.com> |
3 | 3 | # Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com> |
4 | 4 | # Copyright (c) 2018 Ioana Tagirta <ioana.tagirta@gmail.com> |
5 | 5 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
6 | # Copyright (c) 2020-2021 hippo91 <guillaume.peillex@gmail.com> | |
6 | 7 | |
7 | 8 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
8 | 9 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
9 | 10 | import sys |
10 | 11 | |
11 | 12 | import astroid |
13 | ||
14 | ||
15 | PY39 = sys.version_info >= (3, 9) | |
12 | 16 | |
13 | 17 | |
14 | 18 | def _collections_transform(): |
60 | 64 | def __mul__(self, other): pass |
61 | 65 | def __imul__(self, other): pass |
62 | 66 | def __rmul__(self, other): pass""" |
67 | if PY39: | |
68 | base_deque_class += """ | |
69 | @classmethod | |
70 | def __class_getitem__(self, item): pass""" | |
63 | 71 | return base_deque_class |
64 | 72 | |
65 | 73 |
0 | # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com> | |
0 | # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com> | |
1 | 1 | # Copyright (c) 2015 raylu <lurayl@gmail.com> |
2 | 2 | # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com> |
3 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # 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> | |
1 | 3 | |
2 | 4 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 5 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
4 | import collections | |
6 | import collections.abc | |
5 | 7 | import sys |
6 | 8 | |
7 | 9 | import astroid |
18 | 20 | new_node = cls(**init_params) |
19 | 21 | if hasattr(node, "postinit") and _astroid_fields: |
20 | 22 | 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): | |
22 | 24 | cloned_child = _clone_node_with_lineno( |
23 | 25 | node=child, lineno=new_node.lineno, parent=new_node |
24 | 26 | ) |
85 | 85 | |
86 | 86 | # Determine if the passed keywords into the callsite are supported |
87 | 87 | # 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 | ) | |
93 | 96 | parameter_names = set( |
94 | 97 | param.name |
95 | 98 | for param in function_parameters |
1 | 1 | # Copyright (c) 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
2 | 2 | # Copyright (c) 2014 Google, Inc. |
3 | 3 | # 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> | |
5 | 5 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
6 | 6 | # Copyright (c) 2015 David Shea <dshea@redhat.com> |
7 | 7 | # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net> |
8 | 8 | # Copyright (c) 2016 Giuseppe Scrivano <gscrivan@redhat.com> |
9 | 9 | # Copyright (c) 2018 Christoph Reiter <reiter.christoph@gmail.com> |
10 | 10 | # Copyright (c) 2019 Philipp Hörist <philipp@hoerist.com> |
11 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
11 | 12 | |
12 | 13 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
13 | 14 | # 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> | |
1 | 1 | # Copyright (c) 2018 David Poirier <david-poirier-csn@users.noreply.github.com> |
2 | 2 | # Copyright (c) 2018 wgehalo <wgehalo@gmail.com> |
3 | 3 | # 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> | |
4 | 6 | |
5 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
6 | 8 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
7 | 9 | import sys |
8 | ||
9 | import six | |
10 | 10 | |
11 | 11 | import astroid |
12 | 12 | |
54 | 54 | {"blake2b": blake2b_signature, "blake2s": blake2s_signature} |
55 | 55 | ) |
56 | 56 | 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} | |
63 | 58 | for hashfunc, signature in algorithms_with_signature.items() |
64 | 59 | ) |
65 | 60 | 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> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # 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> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # Copyright (c) 2012-2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
1 | 1 | # 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> | |
3 | 3 | # 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> | |
4 | 6 | |
5 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
6 | 8 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
14 | 16 | """ |
15 | 17 | |
16 | 18 | 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 | |
17 | 51 | def open(self, url, data=None, timeout=None): |
18 | 52 | return None |
19 | 53 | def open_novisit(self, url, data=None, timeout=None): |
20 | 54 | return None |
21 | 55 | def open_local_file(self, filename): |
22 | 56 | 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 | |
24 | 83 | """ |
25 | 84 | ) |
26 | 85 |
0 | # Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com> | |
0 | # Copyright (c) 2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com> | |
1 | 1 | # 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> | |
2 | 4 | |
3 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
4 | 6 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
53 | 55 | import array |
54 | 56 | import threading |
55 | 57 | import multiprocessing.pool as pool |
56 | ||
57 | import six | |
58 | import queue | |
58 | 59 | |
59 | 60 | class Namespace(object): |
60 | 61 | pass |
75 | 76 | return array.array(typecode, sequence) |
76 | 77 | |
77 | 78 | class SyncManager(object): |
78 | Queue = JoinableQueue = six.moves.queue.Queue | |
79 | Queue = JoinableQueue = queue.Queue | |
79 | 80 | Event = threading.Event |
80 | 81 | RLock = threading.RLock |
81 | 82 | BoundedSemaphore = threading.BoundedSemaphore |
12 | 12 | # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com> |
13 | 13 | # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi> |
14 | 14 | # 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> | |
15 | 17 | |
16 | 18 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
17 | 19 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
50 | 52 | raise UseInferenceDefault() |
51 | 53 | else: |
52 | 54 | return value |
53 | except StopIteration: | |
54 | raise InferenceError() | |
55 | except StopIteration as exc: | |
56 | raise InferenceError from exc | |
55 | 57 | |
56 | 58 | |
57 | 59 | def _find_func_form_arguments(node, context): |
87 | 89 | name, names = _find_func_form_arguments(node, context) |
88 | 90 | try: |
89 | 91 | attributes = names.value.replace(",", " ").split() |
90 | except AttributeError: | |
92 | except AttributeError as exc: | |
91 | 93 | if not enum: |
92 | 94 | attributes = [ |
93 | 95 | _infer_first(const, context).value for const in names.elts |
116 | 118 | _infer_first(const, context).value for const in names.elts |
117 | 119 | ] |
118 | 120 | else: |
119 | raise AttributeError | |
121 | raise AttributeError from exc | |
120 | 122 | 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 | |
124 | 126 | |
125 | 127 | attributes = [attr for attr in attributes if " " not in attr] |
126 | 128 | |
311 | 313 | if any(not isinstance(value, nodes.AssignName) for value in values): |
312 | 314 | continue |
313 | 315 | |
314 | targets = [] | |
315 | 316 | stmt = values[0].statement() |
316 | 317 | if isinstance(stmt, nodes.Assign): |
317 | 318 | if isinstance(stmt.targets[0], nodes.Tuple): |
335 | 336 | |
336 | 337 | new_targets = [] |
337 | 338 | for target in targets: |
339 | if isinstance(target, nodes.Starred): | |
340 | continue | |
338 | 341 | # Replace all the assignments with our mocked class. |
339 | 342 | classdef = dedent( |
340 | 343 | """ |
398 | 401 | return iter((generated_class_node,)) |
399 | 402 | |
400 | 403 | |
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 | ||
401 | 419 | def infer_typing_namedtuple(node, context=None): |
402 | 420 | """Infer a typing.NamedTuple(...) call.""" |
403 | 421 | # This is essentially a namedtuple with different arguments |
404 | 422 | # so we extract the args and infer a named tuple. |
405 | 423 | try: |
406 | 424 | func = next(node.func.infer()) |
407 | except InferenceError: | |
408 | raise UseInferenceDefault | |
425 | except InferenceError as exc: | |
426 | raise UseInferenceDefault from exc | |
409 | 427 | |
410 | 428 | if func.qname() != "typing.NamedTuple": |
411 | 429 | raise UseInferenceDefault |
450 | 468 | nodes.ClassDef, inference_tip(infer_typing_namedtuple_class), _has_namedtuple_base |
451 | 469 | ) |
452 | 470 | 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( | |
453 | 476 | nodes.Call, inference_tip(infer_typing_namedtuple), _looks_like_typing_namedtuple |
454 | 477 | ) |
0 | # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com> | |
0 | # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com> | |
1 | 1 | # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com> |
2 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
2 | 3 | |
3 | 4 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
4 | 5 | # 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> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # 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> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com> |
1 | # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # 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> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com> |
1 | # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
19 | 20 | # different types defined in numerictypes.py |
20 | 21 | class generic(object): |
21 | 22 | def __init__(self, value): |
22 | self.T = None | |
23 | self.T = np.ndarray([0, 0]) | |
23 | 24 | self.base = None |
24 | 25 | self.data = None |
25 | 26 | self.dtype = None |
26 | 27 | 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]) | |
28 | 31 | self.imag = None |
29 | 32 | self.itemsize = None |
30 | 33 | 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> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
4 | 5 | |
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) | |
6 | 8 | """Astroid hooks for numpy.core.umath module.""" |
7 | 9 | |
8 | 10 | import astroid |
75 | 77 | conjugate = FakeUfuncOneArg() |
76 | 78 | cosh = FakeUfuncOneArg() |
77 | 79 | deg2rad = FakeUfuncOneArg() |
80 | degrees = FakeUfuncOneArg() | |
78 | 81 | exp2 = FakeUfuncOneArg() |
79 | 82 | expm1 = FakeUfuncOneArg() |
80 | 83 | fabs = FakeUfuncOneArg() |
89 | 92 | negative = FakeUfuncOneArg() |
90 | 93 | positive = FakeUfuncOneArg() |
91 | 94 | rad2deg = FakeUfuncOneArg() |
95 | radians = FakeUfuncOneArg() | |
92 | 96 | reciprocal = FakeUfuncOneArg() |
93 | 97 | rint = FakeUfuncOneArg() |
94 | 98 | sign = FakeUfuncOneArg() |
101 | 105 | trunc = FakeUfuncOneArg() |
102 | 106 | |
103 | 107 | # Two args functions with optional kwargs |
108 | add = FakeUfuncTwoArgs() | |
104 | 109 | bitwise_and = FakeUfuncTwoArgs() |
105 | 110 | bitwise_or = FakeUfuncTwoArgs() |
106 | 111 | bitwise_xor = FakeUfuncTwoArgs() |
128 | 133 | logical_xor = FakeUfuncTwoArgs() |
129 | 134 | maximum = FakeUfuncTwoArgs() |
130 | 135 | minimum = FakeUfuncTwoArgs() |
136 | multiply = FakeUfuncTwoArgs() | |
131 | 137 | nextafter = FakeUfuncTwoArgs() |
132 | 138 | not_equal = FakeUfuncTwoArgs() |
133 | 139 | 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> | |
1 | 1 | # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # Copyright (c) 2017-2020 hippo91 <guillaume.peillex@gmail.com> |
3 | 3 | |
16 | 16 | class ndarray(object): |
17 | 17 | def __init__(self, shape, dtype=float, buffer=None, offset=0, |
18 | 18 | strides=None, order=None): |
19 | self.T = None | |
19 | self.T = numpy.ndarray([0, 0]) | |
20 | 20 | self.base = None |
21 | 21 | self.ctypes = None |
22 | 22 | self.data = None |
23 | 23 | self.dtype = None |
24 | 24 | 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]) | |
26 | 28 | self.imag = np.ndarray([0, 0]) |
27 | 29 | self.itemsize = None |
28 | 30 | self.nbytes = None |
70 | 72 | def __mul__(self, value): return numpy.ndarray([0, 0]) |
71 | 73 | def __ne__(self, value): return numpy.ndarray([0, 0]) |
72 | 74 | 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]) | |
74 | 76 | def __pos__(self): return numpy.ndarray([0, 0]) |
75 | 77 | def __pow__(self): return numpy.ndarray([0, 0]) |
76 | 78 | 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> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
43 | 44 | import numpy |
44 | 45 | return numpy.ndarray((1,1)) |
45 | 46 | def randn(*args): return uninferable |
47 | def random(size=None): return uninferable | |
46 | 48 | def random_integers(low, high=None, size=None): return uninferable |
47 | 49 | def random_sample(size=None): return uninferable |
48 | 50 | def rayleigh(scale=1.0, size=None): return uninferable |
0 | 0 | # 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> | |
2 | 2 | |
3 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
4 | 4 | # 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> | |
1 | 1 | # Copyright (c) 2014 Jeff Quast <contact@jeffquast.com> |
2 | 2 | # Copyright (c) 2014 Google, Inc. |
3 | 3 | # Copyright (c) 2016 Florian Bruhin <me@the-compiler.org> |
4 | 4 | # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com> |
5 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
5 | 6 | |
6 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
7 | 8 | # 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> | |
1 | 1 | # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # Copyright (c) 2017 Roy Wright <roy@wright.org> |
3 | 3 | # Copyright (c) 2018 Ashley Whetter <ashley@awhetter.co.uk> |
4 | 4 | # Copyright (c) 2019 Antoine Boellinger <aboellinger@hotmail.com> |
5 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
5 | 6 | |
6 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
7 | 8 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
46 | 46 | |
47 | 47 | try: |
48 | 48 | 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 | |
51 | 51 | |
52 | 52 | new_node = astroid.List( |
53 | 53 | lineno=node.lineno, col_offset=node.col_offset, parent=node.scope() |
0 | 0 | # 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> | |
1 | 3 | |
2 | 4 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 5 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # Copyright (c) 2014-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com> |
1 | 1 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # 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> | |
3 | 6 | |
4 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 8 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
20 | 23 | |
21 | 24 | |
22 | 25 | SIX_ADD_METACLASS = "six.add_metaclass" |
26 | SIX_WITH_METACLASS = "six.with_metaclass" | |
23 | 27 | |
24 | 28 | |
25 | 29 | def _indent(text, prefix, predicate=None): |
144 | 148 | attribute = modname[start_index:].lstrip(".").replace(".", "_") |
145 | 149 | try: |
146 | 150 | 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 | |
149 | 153 | if isinstance(import_attr, nodes.Import): |
150 | 154 | submodule = MANAGER.ast_from_module_name(import_attr.names[0][0]) |
151 | 155 | return submodule |
188 | 192 | return node |
189 | 193 | |
190 | 194 | |
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 | ||
191 | 227 | register_module_extender(MANAGER, "six", six_moves_transform) |
192 | 228 | register_module_extender( |
193 | 229 | MANAGER, "requests.packages.urllib3.packages.six", six_moves_transform |
198 | 234 | transform_six_add_metaclass, |
199 | 235 | _looks_like_decorated_with_six_add_metaclass, |
200 | 236 | ) |
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> | |
1 | 1 | # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # Copyright (c) 2019 Benjamin Elven <25181435+S3ntinelX@users.noreply.github.com> |
3 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
2 | 2 | # Copyright (c) 2018 Peter Talley <peterctalley@gmail.com> |
3 | 3 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
4 | 4 | # 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> | |
5 | 8 | |
6 | 9 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
7 | 10 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
12 | 15 | import astroid |
13 | 16 | |
14 | 17 | |
18 | PY39 = sys.version_info >= (3, 9) | |
15 | 19 | PY37 = sys.version_info >= (3, 7) |
16 | 20 | PY36 = sys.version_info >= (3, 6) |
17 | 21 | |
76 | 80 | preexec_fn=None, |
77 | 81 | pass_fds=(), |
78 | 82 | input=None, |
83 | bufsize=0, | |
84 | executable=None, | |
85 | close_fds=False, | |
86 | startupinfo=None, | |
87 | creationflags=0, | |
79 | 88 | start_new_session=False |
80 | 89 | ): |
81 | 90 | """.strip() |
96 | 105 | preexec_fn=None, |
97 | 106 | pass_fds=(), |
98 | 107 | input=None, |
108 | bufsize=0, | |
109 | executable=None, | |
110 | close_fds=False, | |
111 | startupinfo=None, | |
112 | creationflags=0, | |
99 | 113 | start_new_session=False |
100 | 114 | ): |
101 | 115 | """.strip() |
135 | 149 | "py3_args": py3_args, |
136 | 150 | } |
137 | 151 | ) |
152 | if PY39: | |
153 | code += """ | |
154 | @classmethod | |
155 | def __class_getitem__(cls, item): | |
156 | pass | |
157 | """ | |
138 | 158 | |
139 | 159 | init_lines = textwrap.dedent(init).splitlines() |
140 | 160 | indented_init = "\n".join(" " * 4 + line for line in init_lines) |
0 | 0 | # -*- 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> | |
2 | 2 | # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com> |
3 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # 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> | |
1 | 2 | |
2 | 3 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
3 | 4 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # -*- coding: utf-8 -*- |
1 | 1 | # Copyright (c) 2006-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
2 | 2 | # 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> | |
4 | 4 | # Copyright (c) 2014-2015 Google, Inc. |
5 | 5 | # Copyright (c) 2014 Alexander Presnyakov <flagist0@gmail.com> |
6 | 6 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
7 | 7 | # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com> |
8 | 8 | # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com> |
9 | 9 | # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> |
10 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
10 | 11 | |
11 | 12 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
12 | 13 | # 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> | |
1 | 1 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
3 | 3 | # 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> | |
4 | 6 | |
5 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
6 | 8 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
27 | 29 | "extra_context", |
28 | 30 | ) |
29 | 31 | |
32 | maximum_path_visit = 3 | |
33 | ||
30 | 34 | def __init__(self, path=None, inferred=None): |
31 | self.path = path or set() | |
35 | self.path = path or dict() | |
32 | 36 | """ |
33 | 37 | :type: set(tuple(NodeNG, optional(str))) |
34 | 38 | |
85 | 89 | Allows one to see if the given node has already |
86 | 90 | been looked at for this inference context""" |
87 | 91 | name = self.lookupname |
88 | if (node, name) in self.path: | |
92 | if self.path.get((node, name), 0) >= self.maximum_path_visit: | |
89 | 93 | return True |
90 | 94 | |
91 | self.path.add((node, name)) | |
95 | self.path[(node, name)] = self.path.setdefault((node, name), 0) + 1 | |
92 | 96 | return False |
93 | 97 | |
94 | 98 | def clone(self): |
104 | 108 | clone.extra_context = self.extra_context |
105 | 109 | return clone |
106 | 110 | |
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 | ||
118 | 111 | @contextlib.contextmanager |
119 | 112 | def restore_path(self): |
120 | path = set(self.path) | |
113 | path = dict(self.path) | |
121 | 114 | yield |
122 | 115 | self.path = path |
123 | 116 |
0 | # Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com> | |
0 | # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com> | |
1 | 1 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org> |
3 | 3 | # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com> |
6 | 6 | # Copyright (c) 2018 Ashley Whetter <ashley@awhetter.co.uk> |
7 | 7 | # Copyright (c) 2018 HoverHell <hoverhell@gmail.com> |
8 | 8 | # 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> | |
9 | 11 | |
10 | 12 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
11 | 13 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
133 | 135 | # generator is empty |
134 | 136 | if error.args: |
135 | 137 | # pylint: disable=not-a-mapping |
136 | raise exceptions.InferenceError(**error.args[0]) | |
138 | raise exceptions.InferenceError(**error.args[0]) from error | |
137 | 139 | raise exceptions.InferenceError( |
138 | 140 | "StopIteration raised without any error information." |
139 | ) | |
141 | ) from error | |
140 | 142 | |
141 | 143 | yield from generator |
0 | 0 | # Copyright (c) 2007, 2009-2010, 2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
1 | 1 | # 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> | |
3 | 3 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
4 | 4 | # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com> |
5 | 5 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
6 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
6 | 7 | |
7 | 8 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
8 | 9 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # Copyright (c) 2015-2020 Claudiu Popa <pcmanticore@gmail.com> |
1 | 1 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # 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> | |
3 | 7 | |
4 | 8 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 9 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
189 | 193 | return False |
190 | 194 | try: |
191 | 195 | return type1 in type2.mro()[:-1] |
192 | except exceptions.MroError: | |
196 | except exceptions.MroError as e: | |
193 | 197 | # The MRO is invalid. |
194 | raise exceptions._NonDeducibleTypeHierarchy | |
198 | raise exceptions._NonDeducibleTypeHierarchy from e | |
195 | 199 | |
196 | 200 | |
197 | 201 | def is_subtype(type1, type2): |
236 | 240 | :raises AstroidTypeError: If an invalid node is returned |
237 | 241 | from __len__ method or no __len__ method exists |
238 | 242 | :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 | |
240 | 245 | :rtype int: Integer length of node |
241 | 246 | """ |
242 | 247 | # pylint: disable=import-outside-toplevel; circular import |
243 | 248 | from astroid.objects import FrozenSet |
244 | 249 | |
245 | 250 | 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 | ||
246 | 269 | if inferred_node is None or inferred_node is util.Uninferable: |
247 | 270 | raise exceptions.InferenceError(node=node) |
248 | 271 | if isinstance(inferred_node, nodes.Const) and isinstance( |
260 | 283 | |
261 | 284 | try: |
262 | 285 | len_call = next(node_type.igetattr("__len__", context=context)) |
263 | except exceptions.AttributeInferenceError: | |
286 | except exceptions.AttributeInferenceError as e: | |
264 | 287 | raise exceptions.AstroidTypeError( |
265 | 288 | "object of type '{}' has no len()".format(node_type.pytype()) |
266 | ) | |
289 | ) from e | |
267 | 290 | |
268 | 291 | result_of_len = next(len_call.infer_call_result(node, context)) |
269 | 292 | if ( |
0 | # Copyright (c) 2016-2018 Claudiu Popa <pcmanticore@gmail.com> | |
0 | # Copyright (c) 2016-2018, 2020 Claudiu Popa <pcmanticore@gmail.com> | |
1 | 1 | # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com> |
2 | 2 | # Copyright (c) 2017 Chris Philip <chrisp533@gmail.com> |
3 | 3 | # Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com> |
6 | 6 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
7 | 7 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
8 | 8 | # 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> | |
9 | 12 | |
10 | 13 | import abc |
11 | 14 | import collections |
12 | 15 | import distutils |
13 | 16 | import enum |
14 | import imp | |
15 | 17 | import os |
16 | 18 | import sys |
17 | 19 | import zipimport |
18 | 20 | |
19 | try: | |
20 | import importlib.machinery | |
21 | ||
22 | _HAS_MACHINERY = True | |
23 | except ImportError: | |
24 | _HAS_MACHINERY = False | |
21 | import importlib.machinery | |
25 | 22 | |
26 | 23 | try: |
27 | 24 | from functools import lru_cache |
36 | 33 | "PY_CODERESOURCE PY_COMPILED PY_FROZEN PY_RESOURCE " |
37 | 34 | "PY_SOURCE PY_ZIPMODULE PY_NAMESPACE", |
38 | 35 | ) |
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] | |
55 | 36 | |
56 | 37 | |
57 | 38 | _ModuleSpec = collections.namedtuple( |
113 | 94 | """Get a list of extra paths where this finder can search.""" |
114 | 95 | |
115 | 96 | |
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))) | |
120 | 109 | if submodule_path is not None: |
121 | 110 | 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 | |
136 | 150 | |
137 | 151 | def contribute_to_path(self, spec, processed): |
138 | 152 | if spec.location is None: |
158 | 172 | return path |
159 | 173 | |
160 | 174 | |
161 | class ExplicitNamespacePackageFinder(ImpFinder): | |
175 | class ExplicitNamespacePackageFinder(ImportlibFinder): | |
162 | 176 | """A finder for the explicit namespace packages, generated through pkg_resources.""" |
163 | 177 | |
164 | 178 | def find_module(self, modname, module_parts, processed, submodule_path): |
228 | 242 | return None |
229 | 243 | |
230 | 244 | |
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 | ) | |
235 | 251 | |
236 | 252 | |
237 | 253 | def _is_setuptools_namespace(location): |
239 | 255 | with open(os.path.join(location, "__init__.py"), "rb") as stream: |
240 | 256 | data = stream.read(4096) |
241 | 257 | except IOError: |
242 | pass | |
258 | return None | |
243 | 259 | else: |
244 | 260 | extend_path = b"pkgutil" in data and b"extend_path" in data |
245 | 261 | declare_namespace = ( |
256 | 272 | |
257 | 273 | |
258 | 274 | 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 | """ | |
259 | 285 | pic = sys.path_importer_cache |
260 | 286 | |
261 | 287 | # When measured, despite having the same complexity (O(n)), |
271 | 297 | pic[entry_path] = zipimport.zipimporter(entry_path) |
272 | 298 | except zipimport.ZipImportError: |
273 | 299 | continue |
274 | return pic | |
300 | return { | |
301 | key: value | |
302 | for key, value in pic.items() | |
303 | if isinstance(value, zipimport.zipimporter) | |
304 | } | |
275 | 305 | |
276 | 306 | |
277 | 307 | def _search_zip(modpath, pic): |
0 | 0 | # -*- coding: utf-8 -*- |
1 | # Copyright (c) 2016-2019 Claudiu Popa <pcmanticore@gmail.com> | |
1 | # Copyright (c) 2016-2020 Claudiu Popa <pcmanticore@gmail.com> | |
2 | 2 | # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com> |
3 | 3 | # Copyright (c) 2017-2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
4 | 4 | # Copyright (c) 2017 Ceridwen <ceridwenv@gmail.com> |
5 | 5 | # Copyright (c) 2017 Calen Pennington <cale@edx.org> |
6 | 6 | # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi> |
7 | 7 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
8 | # Copyright (c) 2020-2021 hippo91 <guillaume.peillex@gmail.com> | |
8 | 9 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
9 | 10 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
10 | 11 | """ |
31 | 32 | import os |
32 | 33 | import types |
33 | 34 | from functools import lru_cache |
35 | from typing import Optional | |
34 | 36 | |
35 | 37 | import astroid |
36 | 38 | from astroid import context as contextmod |
37 | 39 | from astroid import exceptions |
38 | 40 | from astroid import node_classes |
41 | from astroid import util | |
42 | ||
43 | # Prevents circular imports | |
44 | objects = util.lazy_import("objects") | |
39 | 45 | |
40 | 46 | |
41 | 47 | IMPL_PREFIX = "attr_" |
323 | 329 | doc=func.doc, |
324 | 330 | lineno=func.lineno, |
325 | 331 | col_offset=func.col_offset, |
332 | parent=func.parent, | |
326 | 333 | ) |
327 | 334 | # pylint: disable=no-member |
328 | 335 | new_func.postinit(func.args, func.body, func.decorators, func.returns) |
658 | 665 | return node_classes.Const("") |
659 | 666 | |
660 | 667 | |
668 | class UnicodeDecodeErrorInstanceModel(ExceptionInstanceModel): | |
669 | @property | |
670 | def attr_object(self): | |
671 | return node_classes.Const("") | |
672 | ||
673 | ||
661 | 674 | BUILTIN_EXCEPTIONS = { |
662 | 675 | "builtins.SyntaxError": SyntaxErrorInstanceModel, |
663 | 676 | "builtins.ImportError": ImportErrorInstanceModel, |
677 | "builtins.UnicodeDecodeError": UnicodeDecodeErrorInstanceModel, | |
664 | 678 | # These are all similar to OSError in terms of attributes |
665 | 679 | "builtins.OSError": OSErrorInstanceModel, |
666 | 680 | "builtins.BlockingIOError": OSErrorInstanceModel, |
706 | 720 | elems.append(elem) |
707 | 721 | obj.postinit(elts=elems) |
708 | 722 | |
709 | # pylint: disable=import-outside-toplevel; circular import | |
710 | from astroid import objects | |
711 | ||
712 | 723 | obj = objects.DictItems(obj) |
713 | 724 | return self._generic_dict_attribute(obj, "items") |
714 | 725 | |
718 | 729 | obj = node_classes.List(parent=self._instance) |
719 | 730 | obj.postinit(elts=keys) |
720 | 731 | |
721 | # pylint: disable=import-outside-toplevel; circular import | |
722 | from astroid import objects | |
723 | ||
724 | 732 | obj = objects.DictKeys(obj) |
725 | 733 | return self._generic_dict_attribute(obj, "keys") |
726 | 734 | |
730 | 738 | values = [value for (_, value) in self._instance.items] |
731 | 739 | obj = node_classes.List(parent=self._instance) |
732 | 740 | obj.postinit(values) |
733 | ||
734 | # pylint: disable=import-outside-toplevel; circular import | |
735 | from astroid import objects | |
736 | 741 | |
737 | 742 | obj = objects.DictValues(obj) |
738 | 743 | return self._generic_dict_attribute(obj, "values") |
786 | 791 | return property_accessor |
787 | 792 | |
788 | 793 | @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 | |
789 | 834 | def attr_setter(self): |
790 | 835 | return self._init_function("setter") |
791 | 836 |
0 | 0 | # 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> | |
2 | 2 | # Copyright (c) 2014 BioGeek <jeroen.vangoey@gmail.com> |
3 | 3 | # Copyright (c) 2014 Google, Inc. |
4 | 4 | # Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com> |
8 | 8 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
9 | 9 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
10 | 10 | # 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> | |
11 | 13 | # Copyright (c) 2020 Anubhav <35621759+anubh-v@users.noreply.github.com> |
12 | 14 | # Copyright (c) 2020 Ashley Whetter <ashley@awhetter.co.uk> |
13 | 15 | |
235 | 237 | value = exceptions.AstroidImportError( |
236 | 238 | "Failed to import module {modname} with error:\n{error}.", |
237 | 239 | 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), | |
239 | 242 | ) |
240 | 243 | self._mod_file_cache[(modname, contextfile)] = value |
241 | 244 | 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) | |
243 | 247 | return value |
244 | 248 | |
245 | 249 | def ast_from_module(self, module, modname=None): |
15 | 15 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
16 | 16 | # Copyright (c) 2019 markmcclain <markmcclain@users.noreply.github.com> |
17 | 17 | # 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> | |
18 | 20 | |
19 | 21 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
20 | 22 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
30 | 32 | :type BUILTIN_MODULES: dict |
31 | 33 | :var BUILTIN_MODULES: dictionary with builtin module names has key |
32 | 34 | """ |
33 | import imp | |
35 | import importlib.util | |
34 | 36 | import os |
35 | 37 | import platform |
36 | 38 | import sys |
43 | 45 | # distutils is replaced by virtualenv with a module that does |
44 | 46 | # weird path manipulations in order to get to the |
45 | 47 | # real distutils module. |
46 | from typing import Optional, List | |
47 | 48 | |
48 | 49 | from .interpreter._import import spec |
49 | 50 | from .interpreter._import import util |
89 | 90 | pass |
90 | 91 | |
91 | 92 | 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)) | |
92 | 105 | _root = os.path.join(sys.prefix, "lib_pypy") |
93 | 106 | STD_LIB_DIRS.add(_root) |
94 | 107 | try: |
95 | 108 | # 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")) | |
97 | 110 | except AttributeError: |
98 | 111 | pass |
99 | 112 | del _root |
177 | 190 | return result |
178 | 191 | |
179 | 192 | |
180 | def load_module_from_name(dotted_name, path=None, use_sys=True): | |
193 | def load_module_from_name(dotted_name): | |
181 | 194 | """Load a Python module from its name. |
182 | 195 | |
183 | 196 | :type dotted_name: str |
184 | 197 | :param dotted_name: python name of a module or package |
185 | 198 | |
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 | ||
197 | 199 | :raise ImportError: if the module or package is not found |
198 | 200 | |
199 | 201 | :rtype: module |
200 | 202 | :return: the loaded module |
201 | 203 | """ |
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): | |
206 | 213 | """Load a python module from its split name. |
207 | 214 | |
208 | 215 | :type parts: list(str) or tuple(str) |
209 | 216 | :param parts: |
210 | 217 | python name of a module or package split on '.' |
211 | 218 | |
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 | ||
220 | 219 | :raise ImportError: if the module or package is not found |
221 | 220 | |
222 | 221 | :rtype: module |
223 | 222 | :return: the loaded module |
224 | 223 | """ |
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): | |
263 | 228 | """Load a Python module from it's path. |
264 | 229 | |
265 | 230 | :type filepath: str |
266 | 231 | :param filepath: path to the python module or package |
267 | 232 | |
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 | ||
277 | 233 | :raise ImportError: if the module or package is not found |
278 | 234 | |
279 | 235 | :rtype: module |
280 | 236 | :return: the loaded module |
281 | 237 | """ |
282 | 238 | modpath = modpath_from_file(filepath) |
283 | return load_module_from_modpath(modpath, path, use_sys) | |
239 | return load_module_from_modpath(modpath) | |
284 | 240 | |
285 | 241 | |
286 | 242 | def check_modpath_has_init(path, mod_path): |
417 | 373 | elif modpath == ["os", "path"]: |
418 | 374 | # FIXME: currently ignoring search_path... |
419 | 375 | 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, | |
421 | 379 | ) |
422 | 380 | return _spec_from_modpath(modpath, path, context) |
423 | 381 | |
613 | 571 | from_file = os.path.dirname(from_file) |
614 | 572 | if from_file in sys.path: |
615 | 573 | 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: | |
624 | 583 | 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 | |
625 | 589 | |
626 | 590 | |
627 | 591 | # internal only functions ##################################################### |
2 | 2 | # Copyright (c) 2010 Daniel Harding <dharding@gmail.com> |
3 | 3 | # Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com> |
4 | 4 | # 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> | |
6 | 6 | # Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com> |
7 | 7 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
8 | 8 | # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org> |
13 | 13 | # Copyright (c) 2017-2020 Ashley Whetter <ashley@awhetter.co.uk> |
14 | 14 | # Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com> |
15 | 15 | # 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> | |
17 | 18 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
18 | 19 | # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi> |
19 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> | |
20 | 20 | # Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com> |
21 | 21 | # Copyright (c) 2018 HoverHell <hoverhell@gmail.com> |
22 | 22 | # Copyright (c) 2019 kavins14 <kavin.singh@mail.utoronto.ca> |
23 | 23 | # 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> | |
24 | 26 | |
25 | 27 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
26 | 28 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
353 | 355 | # explicit_inference is not bound, give it self explicitly |
354 | 356 | try: |
355 | 357 | # pylint: disable=not-callable |
356 | return self._explicit_inference(self, context, **kwargs) | |
358 | yield from self._explicit_inference(self, context, **kwargs) | |
359 | return | |
357 | 360 | except exceptions.UseInferenceDefault: |
358 | 361 | pass |
359 | 362 | |
360 | 363 | if not context: |
361 | return self._infer(context, **kwargs) | |
364 | yield from self._infer(context, **kwargs) | |
365 | return | |
362 | 366 | |
363 | 367 | key = (self, context.lookupname, context.callcontext, context.boundnode) |
364 | 368 | 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 | |
369 | 389 | |
370 | 390 | def _repr_name(self): |
371 | 391 | """Get a name for nice representation. |
949 | 969 | try: |
950 | 970 | return stmts[index + 1] |
951 | 971 | except IndexError: |
952 | pass | |
972 | return None | |
953 | 973 | |
954 | 974 | def previous_sibling(self): |
955 | 975 | """The previous sibling statement. |
1148 | 1168 | _stmts = [] |
1149 | 1169 | _stmt_parents = [] |
1150 | 1170 | statements = self._get_filtered_node_statements(stmts) |
1151 | ||
1152 | 1171 | for node, stmt in statements: |
1153 | 1172 | # 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: | |
1155 | 1174 | break |
1156 | 1175 | # Ignore decorators with the same name as the |
1157 | 1176 | # decorated function |
2105 | 2124 | yield self.target |
2106 | 2125 | yield self.value |
2107 | 2126 | |
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 | ||
2108 | 2132 | |
2109 | 2133 | class Repr(NodeNG): |
2110 | 2134 | """Class representing an :class:`ast.Repr` node. |
3507 | 3531 | def has_elif_block(self): |
3508 | 3532 | return len(self.orelse) == 1 and isinstance(self.orelse[0], If) |
3509 | 3533 | |
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 | ||
3510 | 3539 | |
3511 | 3540 | class IfExp(NodeNG): |
3512 | 3541 | """Class representing an :class:`ast.IfExp` node. |
13 | 13 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
14 | 14 | # Copyright (c) 2018 HoverHell <hoverhell@gmail.com> |
15 | 15 | # 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> | |
16 | 19 | |
17 | 20 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
18 | 21 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
497 | 500 | elif isinstance(inferred, bases.Instance): |
498 | 501 | try: |
499 | 502 | 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 | |
502 | 505 | if not isinstance(enter, bases.BoundMethod): |
503 | 506 | raise exceptions.InferenceError(node=enter) |
504 | 507 | yield from enter.infer_call_result(self, context) |
685 | 688 | continue |
686 | 689 | |
687 | 690 | # We're done unpacking. |
688 | elts = list(elts) | |
689 | 691 | packed = nodes.List( |
690 | 692 | ctx=Store, parent=self, lineno=lhs.lineno, col_offset=lhs.col_offset |
691 | 693 | ) |
692 | packed.postinit(elts=elts) | |
694 | packed.postinit(elts=list(elts)) | |
693 | 695 | yield packed |
694 | 696 | break |
695 | 697 |
10 | 10 | # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi> |
11 | 11 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
12 | 12 | # 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> | |
13 | 15 | # Copyright (c) 2020 Robin Jarry <robin.jarry@6wind.com> |
14 | 16 | |
15 | 17 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
24 | 26 | import os |
25 | 27 | import sys |
26 | 28 | import types |
29 | import warnings | |
27 | 30 | |
28 | 31 | from astroid import bases |
29 | 32 | from astroid import manager |
323 | 326 | self._done[obj] = node |
324 | 327 | for name in dir(obj): |
325 | 328 | 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): | |
328 | 333 | # damned ExtensionClass.Base, I know you're there ! |
329 | 334 | attach_dummy_node(node, name) |
330 | 335 | continue |
14 | 14 | # Copyright (c) 2018 Serhiy Storchaka <storchaka@gmail.com> |
15 | 15 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
16 | 16 | # 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> | |
18 | 18 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
19 | 19 | # Copyright (c) 2019 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> |
20 | 20 | |
237 | 237 | |
238 | 238 | return type_object.value |
239 | 239 | |
240 | def check_function_type_comment(self, node): | |
240 | def check_function_type_comment(self, node, parent): | |
241 | 241 | type_comment = getattr(node, "type_comment", None) |
242 | 242 | if not type_comment: |
243 | 243 | return None |
250 | 250 | |
251 | 251 | returns = None |
252 | 252 | 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 []) | |
254 | 254 | ] |
255 | 255 | if type_comment_ast.returns: |
256 | returns = self.visit(type_comment_ast.returns, node) | |
256 | returns = self.visit(type_comment_ast.returns, parent) | |
257 | 257 | |
258 | 258 | return returns, argtypes |
259 | 259 | |
614 | 614 | returns = None |
615 | 615 | |
616 | 616 | 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) | |
618 | 618 | if type_comment_annotation: |
619 | 619 | type_comment_returns, type_comment_args = type_comment_annotation |
620 | 620 | newnode.postinit( |
19 | 19 | # Copyright (c) 2018 HoverHell <hoverhell@gmail.com> |
20 | 20 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
21 | 21 | # 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> | |
22 | 26 | |
23 | 27 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
24 | 28 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
1447 | 1451 | decorators.append(assign.value) |
1448 | 1452 | return decorators |
1449 | 1453 | |
1454 | # pylint: disable=invalid-overridden-method | |
1450 | 1455 | @decorators_mod.cachedproperty |
1451 | 1456 | def type( |
1452 | 1457 | self |
2570 | 2575 | else: |
2571 | 2576 | raise exceptions.InferenceError( |
2572 | 2577 | error.message, target=self, attribute=name, context=context |
2573 | ) | |
2578 | ) from error | |
2574 | 2579 | |
2575 | 2580 | def has_dynamic_getattr(self, context=None): |
2576 | 2581 | """Check if the class has a custom __getattr__ or __getattribute__. |
2857 | 2862 | |
2858 | 2863 | for stmt in self.bases: |
2859 | 2864 | try: |
2860 | baseobj = next(stmt.infer(context=context)) | |
2865 | baseobj = next(stmt.infer(context=context.clone())) | |
2861 | 2866 | except exceptions.InferenceError: |
2862 | 2867 | continue |
2863 | 2868 | if isinstance(baseobj, bases.Instance): |
0 | 0 | # Copyright (c) 2013-2014 Google, Inc. |
1 | 1 | # 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> | |
3 | 3 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
4 | 4 | # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net> |
5 | 5 | # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> |
6 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
6 | 7 | |
7 | 8 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
8 | 9 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
1 | 1 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
3 | 3 | # 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> | |
4 | 6 | |
5 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
6 | 8 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
7 | 9 | |
8 | 10 | import warnings |
9 | from itertools import islice | |
10 | 11 | |
11 | 12 | import importlib |
12 | 13 | import lazy_object_proxy |
138 | 139 | }, |
139 | 140 | ) |
140 | 141 | 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 |
0 | 0 | Metadata-Version: 1.2 |
1 | 1 | Name: astroid |
2 | Version: 2.4.2 | |
2 | Version: 2.5 | |
3 | 3 | Summary: An abstract syntax tree for Python with inference support. |
4 | 4 | Home-page: https://github.com/PyCQA/astroid |
5 | 5 | Author: Python Code Quality Authority |
86 | 86 | --------------- |
87 | 87 | |
88 | 88 | 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). | |
90 | 91 | |
91 | 92 | Test |
92 | 93 | ---- |
102 | 103 | Classifier: Topic :: Software Development :: Quality Assurance |
103 | 104 | Classifier: Programming Language :: Python |
104 | 105 | Classifier: Programming Language :: Python :: 3 |
105 | Classifier: Programming Language :: Python :: 3.5 | |
106 | 106 | Classifier: Programming Language :: Python :: 3.6 |
107 | 107 | Classifier: Programming Language :: Python :: 3.7 |
108 | 108 | Classifier: Programming Language :: Python :: 3.8 |
109 | Classifier: Programming Language :: Python :: 3.9 | |
109 | 110 | Classifier: Programming Language :: Python :: Implementation :: CPython |
110 | 111 | Classifier: Programming Language :: Python :: Implementation :: PyPy |
111 | Requires-Python: >=3.5 | |
112 | Requires-Python: >=3.6 |
49 | 49 | astroid/brain/brain_gi.py |
50 | 50 | astroid/brain/brain_hashlib.py |
51 | 51 | astroid/brain/brain_http.py |
52 | astroid/brain/brain_hypothesis.py | |
52 | 53 | astroid/brain/brain_io.py |
53 | 54 | astroid/brain/brain_mechanize.py |
54 | 55 | astroid/brain/brain_multiprocessing.py |
71 | 72 | astroid/brain/brain_responses.py |
72 | 73 | astroid/brain/brain_scipy_signal.py |
73 | 74 | astroid/brain/brain_six.py |
75 | astroid/brain/brain_sqlalchemy.py | |
74 | 76 | astroid/brain/brain_ssl.py |
75 | 77 | astroid/brain/brain_subprocess.py |
76 | 78 | astroid/brain/brain_threading.py |
79 | astroid/brain/brain_type.py | |
77 | 80 | astroid/brain/brain_typing.py |
78 | 81 | astroid/brain/brain_uuid.py |
79 | 82 | astroid/interpreter/__init__.py |
109 | 112 | tests/unittest_scoped_nodes.py |
110 | 113 | tests/unittest_transforms.py |
111 | 114 | 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 | |
171 | 115 | tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg |
172 | 116 | tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip |
173 | 117 | 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 | |
3 | 2 | |
4 | 3 | [:implementation_name == "cpython" and python_version < "3.8"] |
5 | 4 | typed-ast<1.5,>=1.4.0 |
0 | 0 | #!/usr/bin/env python |
1 | 1 | # Copyright (c) 2006, 2009-2010, 2012-2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
2 | 2 | # 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> | |
4 | 4 | # Copyright (c) 2014 Google, Inc. |
5 | 5 | # Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com> |
6 | 6 | # Copyright (c) 2018-2019 Ashley Whetter <ashley@awhetter.co.uk> |
7 | 7 | # 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> | |
8 | 11 | |
9 | 12 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
10 | 13 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
13 | 16 | """Setup script for astroid.""" |
14 | 17 | import os |
15 | 18 | import sys |
19 | import warnings | |
16 | 20 | from setuptools import find_packages, setup |
17 | 21 | from setuptools.command import easy_install # pylint: disable=unused-import |
18 | 22 | 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) | |
19 | 26 | |
20 | 27 | real_path = os.path.realpath(__file__) |
21 | 28 | astroid_dir = os.path.dirname(real_path) |
43 | 50 | author=author, |
44 | 51 | author_email=author_email, |
45 | 52 | url=web, |
46 | python_requires=">=3.5", | |
53 | python_requires=">=3.6", | |
47 | 54 | install_requires=install_requires, |
48 | 55 | extras_require=extras_require, |
49 | 56 | packages=find_packages(exclude=["tests"]) + ["astroid.brain"], |
0 | 0 | # 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> | |
2 | 2 | # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com> |
3 | 3 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
4 | 4 | # 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> | |
5 | 7 | |
6 | 8 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
7 | 9 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
14 | 16 | from astroid.bases import BUILTINS |
15 | 17 | |
16 | 18 | |
17 | DATA_DIR = os.path.join("testdata", "python{}".format(sys.version_info[0])) | |
19 | DATA_DIR = os.path.join("testdata", "python3") | |
18 | 20 | RESOURCE_PATH = os.path.join(os.path.dirname(__file__), DATA_DIR, "data") |
19 | 21 | |
20 | 22 |
0 | __revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $" |
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 | 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 | var = 42⏎ |
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 | """fake email module to test absolute import doesn't grab this one""" |
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 | """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 | 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 | """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 | from __future__ import absolute_import, print_function | |
1 | from . import core | |
2 | from .core import * | |
3 | print(sys.version) |
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 | from namespace_pep_420.submodule import var⏎ |
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 | 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 | 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 | 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 | # 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 | """package.subpackage""" |
0 | """package.subpackage.module""" |
0 | __import__('pkg_resources').declare_namespace(__name__)⏎ |
0 | __import__('pkg_resources').declare_namespace(__name__)⏎ |
0 | __import__('pkg_resources').declare_namespace(__name__)⏎ |
15 | 15 | print(v.get('yo')) |
16 | 16 | |
17 | 17 | |
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 | |
21 | 19 | |
22 | 20 | class OptionParser(s_opt.OptionParser): |
23 | 21 |
5 | 5 | # Copyright (c) 2015 raylu <lurayl@gmail.com> |
6 | 6 | # Copyright (c) 2015 Philip Lorenz <philip@bithub.de> |
7 | 7 | # Copyright (c) 2016 Florian Bruhin <me@the-compiler.org> |
8 | # Copyright (c) 2017-2018, 2020-2021 hippo91 <guillaume.peillex@gmail.com> | |
8 | 9 | # Copyright (c) 2017-2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
9 | # Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com> | |
10 | 10 | # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com> |
11 | 11 | # Copyright (c) 2017 David Euresti <github@euresti.com> |
12 | 12 | # Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com> |
17 | 17 | # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> |
18 | 18 | # Copyright (c) 2018 Ioana Tagirta <ioana.tagirta@gmail.com> |
19 | 19 | # Copyright (c) 2018 Ahmed Azzaoui <ahmed.azzaoui@engie.com> |
20 | # Copyright (c) 2019-2020 Bryce Guinta <bryce.guinta@protonmail.com> | |
20 | 21 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
21 | 22 | # Copyright (c) 2019 Tomas Novak <ext.Tomas.Novak@skoda-auto.cz> |
22 | 23 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
23 | 24 | # 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> | |
25 | 28 | |
26 | 29 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
27 | 30 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
30 | 33 | import io |
31 | 34 | import queue |
32 | 35 | import re |
36 | import os | |
33 | 37 | |
34 | 38 | try: |
35 | 39 | import multiprocessing # pylint: disable=unused-import |
77 | 81 | except ImportError: |
78 | 82 | HAS_ATTR = False |
79 | 83 | |
84 | try: | |
85 | import six # pylint: disable=unused-import | |
86 | ||
87 | HAS_SIX = True | |
88 | except ImportError: | |
89 | HAS_SIX = False | |
90 | ||
80 | 91 | from astroid import MANAGER |
81 | 92 | from astroid import bases |
82 | 93 | from astroid import builder |
83 | 94 | from astroid import nodes |
84 | 95 | from astroid import util |
85 | from astroid import test_utils | |
86 | 96 | import astroid |
97 | import astroid.test_utils as test_utils | |
87 | 98 | |
88 | 99 | |
89 | 100 | class HashlibTest(unittest.TestCase): |
106 | 117 | class_obj = hashlib_module[class_name] |
107 | 118 | self._assert_hashlib_class(class_obj) |
108 | 119 | |
109 | @test_utils.require_version(minver="3.6") | |
110 | 120 | def test_hashlib_py36(self): |
111 | 121 | hashlib_module = MANAGER.ast_from_module_name("hashlib") |
112 | 122 | for class_name in ["sha3_224", "sha3_512", "shake_128"]: |
132 | 142 | inferred = self._inferred_queue_instance() |
133 | 143 | self.assertTrue(inferred.getattr("__len__")) |
134 | 144 | |
135 | @test_utils.require_version(minver="3.5") | |
136 | 145 | def test_deque_py35methods(self): |
137 | 146 | inferred = self._inferred_queue_instance() |
138 | 147 | self.assertIn("copy", inferred.locals) |
139 | 148 | self.assertIn("insert", inferred.locals) |
140 | 149 | self.assertIn("index", inferred.locals) |
141 | 150 | |
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 | ||
142 | 162 | |
143 | 163 | class OrderedDictTest(unittest.TestCase): |
144 | 164 | def _inferred_ordered_dict_instance(self): |
151 | 171 | ) |
152 | 172 | return next(node.infer()) |
153 | 173 | |
154 | @test_utils.require_version(minver="3.4") | |
155 | 174 | def test_ordered_dict_py34method(self): |
156 | 175 | inferred = self._inferred_ordered_dict_instance() |
157 | 176 | self.assertIn("move_to_end", inferred.locals) |
203 | 222 | # namedtuple call and a mixin as base classes |
204 | 223 | result = builder.extract_node( |
205 | 224 | """ |
206 | import six | |
207 | ||
208 | result = __(six.moves.urllib.parse.urlparse('gopher://')) | |
225 | from urllib.parse import urlparse | |
226 | ||
227 | result = __(urlparse('gopher://')) | |
209 | 228 | """ |
210 | 229 | ) |
211 | 230 | instance = next(result.infer()) |
390 | 409 | self.assertEqual(assert_equals.qname(), "unittest.case.TestCase.assertEqual") |
391 | 410 | |
392 | 411 | |
412 | @unittest.skipUnless(HAS_SIX, "These tests require the six library") | |
393 | 413 | 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 | ||
394 | 420 | def test_attribute_access(self): |
395 | 421 | ast_nodes = builder.extract_node( |
396 | 422 | """ |
458 | 484 | ) |
459 | 485 | inferred = next(ast_node.infer()) |
460 | 486 | 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") | |
461 | 515 | |
462 | 516 | |
463 | 517 | @unittest.skipUnless( |
539 | 593 | obj = next(module[attr].infer()) |
540 | 594 | self.assertEqual(obj.qname(), "{}.{}".format(bases.BUILTINS, attr)) |
541 | 595 | |
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") | |
544 | 600 | |
545 | 601 | manager = next(module["manager"].infer()) |
546 | 602 | # Verify that we have these attributes |
799 | 855 | inferred_string = next(node.infer()) |
800 | 856 | assert inferred_string.value == "\N{NULL}" |
801 | 857 | |
802 | @test_utils.require_version(minver="3.6") | |
803 | 858 | def test_dont_crash_on_for_loops_in_body(self): |
804 | 859 | node = builder.extract_node( |
805 | 860 | """ |
837 | 892 | assert isinstance(inferred_list_node, astroid.List) |
838 | 893 | assert inferred_tuple_node.as_string() == "(1, 2)" |
839 | 894 | 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()) | |
840 | 905 | |
841 | 906 | |
842 | 907 | @unittest.skipUnless(HAS_DATEUTIL, "This test requires the dateutil library.") |
923 | 988 | self.assertEqual(raw.name, "FileIO") |
924 | 989 | |
925 | 990 | |
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 | ||
926 | 1027 | @test_utils.require_version("3.6") |
927 | 1028 | class TypingBrain(unittest.TestCase): |
928 | 1029 | def test_namedtuple_base(self): |
1101 | 1202 | self.assertEqual(next(re_ast[name].infer()).value, getattr(re, name)) |
1102 | 1203 | |
1103 | 1204 | |
1104 | @test_utils.require_version("3.6") | |
1105 | 1205 | class BrainFStrings(unittest.TestCase): |
1106 | 1206 | def test_no_crash_on_const_reconstruction(self): |
1107 | 1207 | node = builder.extract_node( |
1119 | 1219 | self.assertIs(inferred, util.Uninferable) |
1120 | 1220 | |
1121 | 1221 | |
1122 | @test_utils.require_version("3.6") | |
1123 | 1222 | class BrainNamedtupleAnnAssignTest(unittest.TestCase): |
1124 | 1223 | def test_no_crash_on_ann_assign_in_namedtuple(self): |
1125 | 1224 | node = builder.extract_node( |
1221 | 1320 | """ |
1222 | 1321 | next(astroid.extract_node(code).infer()) |
1223 | 1322 | |
1224 | @test_utils.require_version(minver="3.6") | |
1225 | 1323 | def test_attrs_with_annotation(self): |
1226 | 1324 | code = """ |
1227 | 1325 | import attr |
1277 | 1375 | # Can be either str or bytes |
1278 | 1376 | assert isinstance(inferred, astroid.Const) |
1279 | 1377 | 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 | |
1280 | 1385 | |
1281 | 1386 | |
1282 | 1387 | class TestIsinstanceInference: |
2019 | 2124 | assert isinstance(name[0], astroid.Unknown) |
2020 | 2125 | |
2021 | 2126 | |
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 | ||
2022 | 2158 | if __name__ == "__main__": |
2023 | 2159 | unittest.main() |
0 | 0 | # -*- encoding=utf-8 -*- |
1 | # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com> | |
1 | 2 | # 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> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # -*- encoding=utf-8 -*- |
1 | # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com> | |
1 | 2 | # 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> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # -*- encoding=utf-8 -*- |
1 | # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com> | |
1 | # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com> | |
2 | 2 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
3 | # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # -*- encoding=utf-8 -*- |
1 | # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com> | |
1 | 2 | # 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> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # -*- encoding=utf-8 -*- |
1 | 1 | # 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> | |
3 | 3 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
4 | 4 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
5 | 5 |
0 | 0 | # -*- encoding=utf-8 -*- |
1 | # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com> | |
1 | # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com> | |
2 | 2 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
3 | # Copyright (c) 2020 Claudiu Popa <pcmanticore@gmail.com> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
35 | 36 | "conjugate", |
36 | 37 | "cosh", |
37 | 38 | "deg2rad", |
39 | "degrees", | |
38 | 40 | "exp2", |
39 | 41 | "expm1", |
40 | 42 | "fabs", |
49 | 51 | "negative", |
50 | 52 | "positive", |
51 | 53 | "rad2deg", |
54 | "radians", | |
52 | 55 | "reciprocal", |
53 | 56 | "rint", |
54 | 57 | "sign", |
61 | 64 | ) |
62 | 65 | |
63 | 66 | two_args_ufunc = ( |
67 | "add", | |
64 | 68 | "bitwise_and", |
65 | 69 | "bitwise_or", |
66 | 70 | "bitwise_xor", |
88 | 92 | "logical_xor", |
89 | 93 | "maximum", |
90 | 94 | "minimum", |
95 | "multiply", | |
91 | 96 | "nextafter", |
92 | 97 | "not_equal", |
93 | 98 | "power", |
220 | 225 | with self.subTest(typ=func_): |
221 | 226 | inferred_values = list(self._inferred_numpy_func_call(func_)) |
222 | 227 | 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, | |
226 | 229 | msg="Too much inferred values ({}) for {:s}".format( |
227 | inferred_values[-1].pytype(), func_ | |
230 | inferred_values, func_ | |
228 | 231 | ), |
229 | 232 | ) |
230 | 233 | self.assertTrue( |
0 | 0 | # -*- encoding=utf-8 -*- |
1 | 1 | # 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> | |
3 | 3 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
4 | 4 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
5 | 5 | |
153 | 153 | Test that some numpy ndarray attributes are inferred as numpy.ndarray |
154 | 154 | """ |
155 | 155 | licit_array_types = ".ndarray" |
156 | for attr_ in ("real", "imag"): | |
156 | for attr_ in ("real", "imag", "shape", "T"): | |
157 | 157 | with self.subTest(typ=attr_): |
158 | 158 | inferred_values = list(self._inferred_ndarray_attribute(attr_)) |
159 | 159 | self.assertTrue( |
0 | 0 | # -*- encoding=utf-8 -*- |
1 | # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com> | |
1 | 2 | # 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> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
54 | 55 | "rand": (["args"], []), |
55 | 56 | "randint": (["low", "high", "size", "dtype"], [None, None, "l"]), |
56 | 57 | "randn": (["args"], []), |
58 | "random": (["size"], [None]), | |
57 | 59 | "random_integers": (["low", "high", "size"], [None, None]), |
58 | 60 | "random_sample": (["size"], [None]), |
59 | 61 | "rayleigh": (["scale", "size"], [1.0, None]), |
0 | 0 | # -*- coding: utf-8 -*- |
1 | 1 | # 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> | |
3 | 3 | # Copyright (c) 2014-2015 Google, Inc. |
4 | 4 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
5 | 5 | # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org> |
11 | 11 | # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> |
12 | 12 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
13 | 13 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
14 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
14 | 15 | |
15 | 16 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
16 | 17 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com> |
1 | 1 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
3 | # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com> | |
3 | 4 | |
4 | 5 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
5 | 6 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
13 | 14 | from astroid import helpers |
14 | 15 | from astroid import manager |
15 | 16 | from astroid import raw_building |
16 | from astroid import test_utils | |
17 | 17 | from astroid import util |
18 | 18 | |
19 | 19 | |
105 | 105 | expected_type = self._build_custom_builtin(expected) |
106 | 106 | self.assert_classes_equal(node_type, expected_type) |
107 | 107 | |
108 | @test_utils.require_version(minver="3.0") | |
109 | 108 | def test_object_type_metaclasses(self): |
110 | 109 | module = builder.parse( |
111 | 110 | """ |
122 | 121 | instance_type = helpers.object_type(meta_instance) |
123 | 122 | self.assert_classes_equal(instance_type, module["Meta"]) |
124 | 123 | |
125 | @test_utils.require_version(minver="3.0") | |
126 | 124 | def test_object_type_most_derived(self): |
127 | 125 | node = builder.extract_node( |
128 | 126 | """ |
1 | 1 | # Copyright (c) 2006-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
2 | 2 | # Copyright (c) 2007 Marien Zwart <marienz@gentoo.org> |
3 | 3 | # 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> | |
5 | 5 | # Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com> |
6 | 6 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
7 | 7 | # Copyright (c) 2015 Dmitry Pribysh <dmand@yandex.ru> |
13 | 13 | # Copyright (c) 2017 Calen Pennington <calen.pennington@gmail.com> |
14 | 14 | # Copyright (c) 2017 David Euresti <david@dropbox.com> |
15 | 15 | # Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com> |
16 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> | |
16 | 17 | # Copyright (c) 2018 Daniel Martin <daniel.martin@crowdstrike.com> |
17 | 18 | # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi> |
18 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> | |
19 | 19 | # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> |
20 | # Copyright (c) 2019-2021 hippo91 <guillaume.peillex@gmail.com> | |
20 | 21 | # Copyright (c) 2019 Stanislav Levin <slev@altlinux.org> |
21 | 22 | # Copyright (c) 2019 David Liu <david@cs.toronto.edu> |
22 | 23 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
23 | 24 | # 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> | |
24 | 30 | |
25 | 31 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
26 | 32 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
427 | 433 | del undefined_attr |
428 | 434 | """ |
429 | 435 | delete = extract_node(code, __name__) |
430 | self.assertRaises(InferenceError, delete.infer) | |
436 | self.assertRaises(InferenceError, next, delete.infer()) | |
431 | 437 | |
432 | 438 | def test_del2(self): |
433 | 439 | code = """ |
540 | 546 | self.assertEqual(ancestor.root().name, BUILTINS) |
541 | 547 | self.assertRaises(StopIteration, partial(next, ancestors)) |
542 | 548 | |
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 | ||
555 | 549 | def test_method_argument(self): |
556 | 550 | code = ''' |
557 | 551 | class ErudiEntitySchema: |
1003 | 997 | inferred = next(node.infer()) |
1004 | 998 | self.assertEqual(inferred.value, expected_value) |
1005 | 999 | |
1006 | @test_utils.require_version(minver="3.5") | |
1007 | 1000 | def test_matmul(self): |
1008 | 1001 | node = extract_node( |
1009 | 1002 | """ |
1248 | 1241 | self.assertEqual(variable_a.inferred()[0].value, 2) |
1249 | 1242 | |
1250 | 1243 | @pytest.mark.xfail(reason="Relying on path copy") |
1251 | @test_utils.require_version(minver="3.5") | |
1252 | 1244 | def test_nonregr_layed_dictunpack(self): |
1253 | 1245 | """Regression test for https://github.com/PyCQA/astroid/issues/483 |
1254 | 1246 | Make sure multiple dictunpack references are inferable |
1308 | 1300 | result = node.inferred() |
1309 | 1301 | assert len(result) == 2 |
1310 | 1302 | assert isinstance(result[0], nodes.Dict) |
1311 | assert result[1] is util.Uninferable | |
1303 | assert isinstance(result[1], nodes.Dict) | |
1312 | 1304 | |
1313 | 1305 | def test_python25_no_relative_import(self): |
1314 | 1306 | ast = resources.build_file("data/package/absimport.py") |
1743 | 1735 | self.assertIsInstance(inferred, Instance) |
1744 | 1736 | self.assertEqual(inferred.qname(), "{}.tuple".format(BUILTINS)) |
1745 | 1737 | |
1746 | @test_utils.require_version("3.5") | |
1747 | 1738 | def test_starred_in_tuple_literal(self): |
1748 | 1739 | code = """ |
1749 | 1740 | var = (1, 2, 3) |
1762 | 1753 | self.assertInferTuple(ast[3], [0, 1, 2, 3, 4, 5, 6, 7, 8]) |
1763 | 1754 | self.assertInferTuple(ast[4], [0, 1, 2, 3, 4, 5, 6, 7, 999, 1000, 1001]) |
1764 | 1755 | |
1765 | @test_utils.require_version("3.5") | |
1766 | 1756 | def test_starred_in_list_literal(self): |
1767 | 1757 | code = """ |
1768 | 1758 | var = (1, 2, 3) |
1781 | 1771 | self.assertInferList(ast[3], [0, 1, 2, 3, 4, 5, 6, 7, 8]) |
1782 | 1772 | self.assertInferList(ast[4], [0, 1, 2, 3, 4, 5, 6, 7, 999, 1000, 1001]) |
1783 | 1773 | |
1784 | @test_utils.require_version("3.5") | |
1785 | 1774 | def test_starred_in_set_literal(self): |
1786 | 1775 | code = """ |
1787 | 1776 | var = (1, 2, 3) |
1800 | 1789 | self.assertInferSet(ast[3], [0, 1, 2, 3, 4, 5, 6, 7, 8]) |
1801 | 1790 | self.assertInferSet(ast[4], [0, 1, 2, 3, 4, 5, 6, 7, 999, 1000, 1001]) |
1802 | 1791 | |
1803 | @test_utils.require_version("3.5") | |
1804 | 1792 | def test_starred_in_literals_inference_issues(self): |
1805 | 1793 | code = """ |
1806 | 1794 | {0, *var} #@ |
1814 | 1802 | with self.assertRaises(InferenceError): |
1815 | 1803 | next(node.infer()) |
1816 | 1804 | |
1817 | @test_utils.require_version("3.5") | |
1818 | 1805 | def test_starred_in_mapping_literal(self): |
1819 | 1806 | code = """ |
1820 | 1807 | var = {1: 'b', 2: 'c'} |
1830 | 1817 | ast[2], {0: "a", 1: "b", 2: "c", 3: "d", 4: "e", 5: "f", 6: "g"} |
1831 | 1818 | ) |
1832 | 1819 | |
1833 | @test_utils.require_version("3.5") | |
1834 | 1820 | def test_starred_in_mapping_literal_no_inference_possible(self): |
1835 | 1821 | node = extract_node( |
1836 | 1822 | """ |
1848 | 1834 | ) |
1849 | 1835 | self.assertEqual(next(node.infer()), util.Uninferable) |
1850 | 1836 | |
1851 | @test_utils.require_version("3.5") | |
1852 | 1837 | def test_starred_in_mapping_inference_issues(self): |
1853 | 1838 | code = """ |
1854 | 1839 | {0: 'a', **var} #@ |
1860 | 1845 | with self.assertRaises(InferenceError): |
1861 | 1846 | next(node.infer()) |
1862 | 1847 | |
1863 | @test_utils.require_version("3.5") | |
1864 | 1848 | def test_starred_in_mapping_literal_non_const_keys_values(self): |
1865 | 1849 | code = """ |
1866 | 1850 | a, b, c, d, e, f, g, h, i, j = "ABCDEFGHIJ" |
1981 | 1965 | self.assertInferTuple(ast_nodes[3], [1, 3]) |
1982 | 1966 | self.assertInferSet(ast_nodes[4], [1, 2]) |
1983 | 1967 | |
1984 | @test_utils.require_version("3.0") | |
1985 | 1968 | def test_builtin_inference_py3k(self): |
1986 | 1969 | code = """ |
1987 | 1970 | list(b"abc") #@ |
2041 | 2024 | ast_node = extract_node("""dict(a=1, b=2, **{'c': 3})""") |
2042 | 2025 | self.assertInferDict(ast_node, {"a": 1, "b": 2, "c": 3}) |
2043 | 2026 | |
2044 | @test_utils.require_version("3.5") | |
2045 | 2027 | def test_dict_inference_for_multiple_starred(self): |
2046 | 2028 | pairs = [ |
2047 | 2029 | ('dict(a=1, **{"b": 2}, **{"c":3})', {"a": 1, "b": 2, "c": 3}), |
2052 | 2034 | node = extract_node(code) |
2053 | 2035 | self.assertInferDict(node, expected_value) |
2054 | 2036 | |
2055 | @test_utils.require_version("3.5") | |
2056 | 2037 | def test_dict_inference_unpack_repeated_key(self): |
2057 | 2038 | """Make sure astroid does not infer repeated keys in a dictionary |
2058 | 2039 | |
2082 | 2063 | def test_str_methods(self): |
2083 | 2064 | code = """ |
2084 | 2065 | ' '.decode() #@ |
2085 | ||
2086 | ' '.encode() #@ | |
2087 | 2066 | ' '.join('abcd') #@ |
2088 | 2067 | ' '.replace('a', 'b') #@ |
2089 | 2068 | ' '.format('a') #@ |
2105 | 2084 | """ |
2106 | 2085 | ast = extract_node(code, __name__) |
2107 | 2086 | self.assertInferConst(ast[0], "") |
2108 | for i in range(1, 16): | |
2087 | for i in range(1, 15): | |
2109 | 2088 | self.assertInferConst(ast[i], "") |
2110 | for i in range(16, 19): | |
2089 | for i in range(15, 18): | |
2111 | 2090 | self.assertInferConst(ast[i], 0) |
2112 | 2091 | |
2113 | 2092 | def test_unicode_methods(self): |
2114 | 2093 | code = """ |
2115 | u' '.encode() #@ | |
2116 | ||
2117 | 2094 | u' '.decode() #@ |
2118 | 2095 | u' '.join('abcd') #@ |
2119 | 2096 | u' '.replace('a', 'b') #@ |
2136 | 2113 | """ |
2137 | 2114 | ast = extract_node(code, __name__) |
2138 | 2115 | self.assertInferConst(ast[0], "") |
2139 | for i in range(1, 16): | |
2116 | for i in range(1, 15): | |
2140 | 2117 | self.assertInferConst(ast[i], "") |
2141 | for i in range(16, 19): | |
2118 | for i in range(15, 18): | |
2142 | 2119 | self.assertInferConst(ast[i], 0) |
2143 | 2120 | |
2144 | 2121 | def test_scope_lookup_same_attributes(self): |
2458 | 2435 | 1 ** (lambda x: x) #@ |
2459 | 2436 | {} * {} #@ |
2460 | 2437 | {} - {} #@ |
2461 | {} | {} #@ | |
2462 | 2438 | {} >> {} #@ |
2463 | 2439 | [] + () #@ |
2464 | 2440 | () + [] #@ |
2503 | 2479 | msg.format(op="**", lhs="int", rhs="function"), |
2504 | 2480 | msg.format(op="*", lhs="dict", rhs="dict"), |
2505 | 2481 | msg.format(op="-", lhs="dict", rhs="dict"), |
2506 | msg.format(op="|", lhs="dict", rhs="dict"), | |
2507 | 2482 | msg.format(op=">>", lhs="dict", rhs="dict"), |
2508 | 2483 | msg.format(op="+", lhs="list", rhs="tuple"), |
2509 | 2484 | msg.format(op="+", lhs="tuple", rhs="list"), |
2518 | 2493 | msg.format(op="+=", lhs="int", rhs="A"), |
2519 | 2494 | msg.format(op="+=", lhs="int", rhs="list"), |
2520 | 2495 | ] |
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 | ||
2521 | 2502 | for node, expected_value in zip(ast_nodes, expected): |
2522 | 2503 | errors = node.type_errors() |
2523 | 2504 | self.assertEqual(len(errors), 1) |
2992 | 2973 | class Meta(type): |
2993 | 2974 | def __getitem__(cls, arg): |
2994 | 2975 | return 24 |
2995 | import six | |
2996 | @six.add_metaclass(Meta) | |
2997 | class A(object): | |
2976 | class A(object, metaclass=Meta): | |
2998 | 2977 | pass |
2999 | 2978 | |
3000 | 2979 | A['Awesome'] #@ |
3004 | 2983 | self.assertIsInstance(inferred, nodes.Const) |
3005 | 2984 | self.assertEqual(inferred.value, 24) |
3006 | 2985 | |
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 | ||
3007 | 3003 | 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): | |
3008 | 3020 | ast_node = extract_node( |
3009 | 3021 | """ |
3010 | 3022 | class Meta(type): |
3011 | 3023 | def __or__(self, other): |
3012 | 3024 | return 24 |
3013 | 3025 | import six |
3014 | @six.add_metaclass(Meta) | |
3015 | class A(object): | |
3026 | class A(six.with_metaclass(Meta)): | |
3016 | 3027 | pass |
3017 | 3028 | |
3018 | 3029 | A | A |
3347 | 3358 | def test_unary_op_classes(self): |
3348 | 3359 | ast_node = extract_node( |
3349 | 3360 | """ |
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 | """ | |
3350 | 3376 | import six |
3351 | 3377 | class Meta(type): |
3352 | 3378 | def __invert__(self): |
3353 | 3379 | return 42 |
3354 | @six.add_metaclass(Meta) | |
3355 | class A(object): | |
3380 | class A(six.with_metaclass(Meta)): | |
3356 | 3381 | pass |
3357 | 3382 | ~A |
3358 | 3383 | """ |
3631 | 3656 | # they will be in the future. |
3632 | 3657 | ast_node = extract_node( |
3633 | 3658 | """ |
3634 | import six | |
3635 | ||
3636 | 3659 | class BookMeta(type): |
3637 | 3660 | author = 'Rushdie' |
3638 | 3661 | |
3639 | 3662 | def metaclass_function(*args): |
3640 | 3663 | return BookMeta |
3641 | 3664 | |
3642 | @six.add_metaclass(metaclass_function) | |
3643 | class Book(object): | |
3665 | class Book(object, metaclass=metaclass_function): | |
3644 | 3666 | pass |
3645 | 3667 | Book #@ |
3646 | 3668 | """ |
3663 | 3685 | flow = AttributeDict() |
3664 | 3686 | flow['app'] = AttributeDict() |
3665 | 3687 | flow['app']['config'] = AttributeDict() |
3666 | flow['app']['config']['doffing'] = AttributeDict() #@ | |
3688 | flow['app']['config']['doffing'] = AttributeDict() | |
3689 | flow['app']['config']['doffing']['thinkto'] = AttributeDict() #@ | |
3667 | 3690 | """ |
3668 | 3691 | ) |
3669 | 3692 | self.assertIsNone(helpers.safe_infer(ast_node.targets[0])) |
3744 | 3767 | class A(type): |
3745 | 3768 | def test(cls): |
3746 | 3769 | 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 | |
3747 | 3786 | 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)): | |
3750 | 3805 | pass |
3751 | 3806 | |
3752 | 3807 | B.test() #@ |
3786 | 3841 | self.assertIsInstance(inferred, nodes.ClassDef) |
3787 | 3842 | self.assertEqual(inferred.name, "A") |
3788 | 3843 | |
3789 | @test_utils.require_version(minver="3.0") | |
3790 | 3844 | def test_metaclass_with_keyword_args(self): |
3791 | 3845 | ast_node = extract_node( |
3792 | 3846 | """ |
4420 | 4474 | self.assertIsInstance(inferred, nodes.Tuple) |
4421 | 4475 | self.assertEqual(self._get_tuple_value(inferred), expected_value) |
4422 | 4476 | |
4423 | @test_utils.require_version("3.5") | |
4424 | 4477 | def test_multiple_starred_args(self): |
4425 | 4478 | expected_values = [(1, 2, 3), (1, 4, 2, 3, 5, 6, 7)] |
4426 | 4479 | ast_nodes = extract_node( |
4453 | 4506 | self.assertIsInstance(inferred, nodes.Const) |
4454 | 4507 | self.assertEqual(inferred.value, expected_value) |
4455 | 4508 | |
4456 | @test_utils.require_version("3.0") | |
4457 | 4509 | def test_kwonly_args(self): |
4458 | 4510 | expected_values = [24, 24, 42, 23, 24, 24, 54] |
4459 | 4511 | ast_nodes = extract_node( |
4536 | 4588 | self.assertIsInstance(inferred, nodes.Const, inferred) |
4537 | 4589 | self.assertEqual(inferred.value, value) |
4538 | 4590 | |
4539 | @test_utils.require_version("3.5") | |
4540 | 4591 | def test_multiple_kwargs(self): |
4541 | 4592 | expected_value = [("a", 1), ("b", 2), ("c", 3), ("d", 4), ("f", 42)] |
4542 | 4593 | ast_node = extract_node( |
4683 | 4734 | for pair in pairs: |
4684 | 4735 | self._test_call_site_pair(*pair) |
4685 | 4736 | |
4686 | @test_utils.require_version("3.5") | |
4687 | 4737 | def test_call_site_starred_args(self): |
4688 | 4738 | pairs = [ |
4689 | 4739 | ( |
5173 | 5223 | assert as_string.strip() == "(ValueError, TypeError)" |
5174 | 5224 | |
5175 | 5225 | |
5176 | @test_utils.require_version(minver="3.6") | |
5177 | 5226 | def test_cannot_getattr_ann_assigns(): |
5178 | 5227 | node = extract_node( |
5179 | 5228 | """ |
5446 | 5495 | def test(self): |
5447 | 5496 | return 42 |
5448 | 5497 | |
5498 | @test.setter | |
5499 | def test(self, value): | |
5500 | return "banco" | |
5501 | ||
5449 | 5502 | A.test #@ |
5450 | 5503 | A().test #@ |
5451 | 5504 | A.test.fget(A) #@ |
5505 | A.test.fset(A, "a_value") #@ | |
5452 | 5506 | A.test.setter #@ |
5453 | 5507 | A.test.getter #@ |
5454 | 5508 | A.test.deleter #@ |
5455 | 5509 | """ |
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( | |
5457 | 5511 | code |
5458 | 5512 | ) |
5459 | 5513 | |
5470 | 5524 | inferred = next(prop_fget_result.infer()) |
5471 | 5525 | assert isinstance(inferred, nodes.Const) |
5472 | 5526 | assert inferred.value == 42 |
5527 | ||
5528 | inferred = next(prop_fset_result.infer()) | |
5529 | assert isinstance(inferred, nodes.Const) | |
5530 | assert inferred.value == "banco" | |
5473 | 5531 | |
5474 | 5532 | for prop_func in prop_setter, prop_getter, prop_deleter: |
5475 | 5533 | inferred = next(prop_func.infer()) |
5666 | 5724 | |
5667 | 5725 | |
5668 | 5726 | @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 | ) | |
5669 | 5731 | def test_dataclasses_subscript_inference_recursion_error(): |
5670 | 5732 | code = """ |
5671 | 5733 | from dataclasses import dataclass, replace |
5684 | 5746 | node = extract_node(code) |
5685 | 5747 | # Reproduces only with safe_infer() |
5686 | 5748 | 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" | |
5687 | 5774 | |
5688 | 5775 | |
5689 | 5776 | def test_self_reference_infer_does_not_trigger_recursion_error(): |
5862 | 5949 | assert list(inferred.nodes_of_class(nodes.Const)) == [] |
5863 | 5950 | |
5864 | 5951 | |
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 | ||
5865 | 5966 | if __name__ == "__main__": |
5866 | 5967 | unittest.main() |
0 | 0 | # Copyright (c) 2007-2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
1 | 1 | # 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> | |
3 | 3 | # Copyright (c) 2014 Google, Inc. |
4 | 4 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
5 | 5 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
6 | 6 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
7 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
7 | 8 | |
8 | 9 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
9 | 10 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # -*- coding: utf-8 -*- |
1 | 1 | # Copyright (c) 2006, 2009-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
2 | 2 | # 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> | |
4 | 4 | # Copyright (c) 2014 Google, Inc. |
5 | 5 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
6 | 6 | # Copyright (c) 2017 Chris Philip <chrisp533@gmail.com> |
10 | 10 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
11 | 11 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
12 | 12 | # 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> | |
13 | 15 | # Copyright (c) 2020 Anubhav <35621759+anubh-v@users.noreply.github.com> |
14 | 16 | |
15 | 17 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
16 | 18 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
17 | 19 | |
20 | import builtins | |
18 | 21 | import os |
19 | 22 | import platform |
20 | 23 | import site |
22 | 25 | import unittest |
23 | 26 | |
24 | 27 | import pkg_resources |
25 | import six | |
26 | 28 | import time |
27 | 29 | |
28 | 30 | import astroid |
31 | 33 | from . import resources |
32 | 34 | |
33 | 35 | |
34 | BUILTINS = six.moves.builtins.__name__ | |
36 | BUILTINS = builtins.__name__ | |
35 | 37 | |
36 | 38 | |
37 | 39 | def _get_file_from_object(obj): |
9 | 9 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
10 | 10 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
11 | 11 | # 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> | |
12 | 14 | |
13 | 15 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
14 | 16 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
81 | 83 | |
82 | 84 | def test_raise_load_module_from_name_1(self): |
83 | 85 | 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_" | |
85 | 87 | ) |
86 | 88 | |
87 | 89 | |
296 | 298 | def test_knownValues_is_relative_3(self): |
297 | 299 | self.assertFalse(modutils.is_relative("astroid", astroid.__path__[0])) |
298 | 300 | |
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 | ||
299 | 318 | |
300 | 319 | class GetModuleFilesTest(unittest.TestCase): |
301 | 320 | def test_get_module_files_1(self): |
0 | 0 | # Copyright (c) 2006-2007, 2009-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
1 | 1 | # 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> | |
3 | 3 | # Copyright (c) 2014 Google, Inc. |
4 | 4 | # Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com> |
5 | 5 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
11 | 11 | # Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com> |
12 | 12 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
13 | 13 | # 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> | |
15 | 15 | # Copyright (c) 2019 Alex Hall <alex.mojaki@gmail.com> |
16 | 16 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
17 | # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com> | |
17 | 18 | |
18 | 19 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
19 | 20 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
20 | 21 | |
21 | 22 | """tests for specific behaviour of astroid nodes |
22 | 23 | """ |
24 | import builtins | |
23 | 25 | import os |
24 | 26 | import sys |
25 | 27 | import textwrap |
28 | 30 | import platform |
29 | 31 | |
30 | 32 | import pytest |
31 | import six | |
32 | 33 | |
33 | 34 | import astroid |
34 | 35 | from astroid import bases |
45 | 46 | |
46 | 47 | |
47 | 48 | abuilder = builder.AstroidBuilder() |
48 | BUILTINS = six.moves.builtins.__name__ | |
49 | BUILTINS = builtins.__name__ | |
49 | 50 | PY38 = sys.version_info[:2] >= (3, 8) |
50 | 51 | try: |
51 | 52 | import typed_ast # pylint: disable=unused-import |
66 | 67 | self.assertEqual(build("(1, )").as_string(), "(1, )") |
67 | 68 | self.assertEqual(build("1, 2, 3").as_string(), "(1, 2, 3)") |
68 | 69 | |
69 | @test_utils.require_version(minver="3.0") | |
70 | 70 | def test_func_signature_issue_185(self): |
71 | 71 | code = textwrap.dedent( |
72 | 72 | """ |
135 | 135 | ast = abuilder.string_build(code) |
136 | 136 | self.assertMultiLineEqual(ast.as_string(), code) |
137 | 137 | |
138 | @test_utils.require_version("3.0") | |
139 | 138 | def test_3k_as_string(self): |
140 | 139 | """check as_string for python 3k syntax""" |
141 | 140 | code = """print() |
400 | 399 | self.assertEqual(self.astroid.body[0].block_range(6), (6, 6)) |
401 | 400 | |
402 | 401 | |
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 | ||
417 | 402 | class ImportNodeTest(resources.SysPathSetup, unittest.TestCase): |
418 | 403 | def setUp(self): |
419 | 404 | super(ImportNodeTest, self).setUp() |
579 | 564 | |
580 | 565 | |
581 | 566 | class AnnAssignNodeTest(unittest.TestCase): |
582 | @test_utils.require_version(minver="3.6") | |
583 | 567 | def test_primitive(self): |
584 | 568 | code = textwrap.dedent( |
585 | 569 | """ |
593 | 577 | self.assertEqual(assign.value.value, 5) |
594 | 578 | self.assertEqual(assign.simple, 1) |
595 | 579 | |
596 | @test_utils.require_version(minver="3.6") | |
597 | 580 | def test_primitive_without_initial_value(self): |
598 | 581 | code = textwrap.dedent( |
599 | 582 | """ |
606 | 589 | self.assertEqual(assign.annotation.name, "str") |
607 | 590 | self.assertEqual(assign.value, None) |
608 | 591 | |
609 | @test_utils.require_version(minver="3.6") | |
610 | 592 | def test_complex(self): |
611 | 593 | code = textwrap.dedent( |
612 | 594 | """ |
619 | 601 | self.assertIsInstance(assign.annotation, astroid.Subscript) |
620 | 602 | self.assertIsInstance(assign.value, astroid.Dict) |
621 | 603 | |
622 | @test_utils.require_version(minver="3.6") | |
623 | 604 | def test_as_string(self): |
624 | 605 | code = textwrap.dedent( |
625 | 606 | """ |
653 | 634 | "(no line number on function args)" |
654 | 635 | ) |
655 | 636 | |
656 | @test_utils.require_version(minver="3.0") | |
657 | 637 | def test_kwoargs(self): |
658 | 638 | ast = builder.parse( |
659 | 639 | """ |
861 | 841 | self.assertIsInstance(module.body[6].value, nodes.GeneratorExp) |
862 | 842 | |
863 | 843 | |
864 | @test_utils.require_version("3.5") | |
865 | 844 | class Python35AsyncTest(unittest.TestCase): |
866 | 845 | def test_async_await_keywords(self): |
867 | 846 | async_def, async_for, async_with, await_node = builder.extract_node( |
961 | 940 | with self.assertRaises(exceptions.AstroidSyntaxError): |
962 | 941 | builder.extract_node("(1, ) = 3") |
963 | 942 | |
964 | @test_utils.require_version(minver="3.5") | |
965 | 943 | def test_starred_load(self): |
966 | 944 | node = builder.extract_node("a = *b") |
967 | 945 | starred = node.value |
968 | 946 | self.assertIs(starred.ctx, astroid.Load) |
969 | 947 | |
970 | @test_utils.require_version(minver="3.0") | |
971 | 948 | def test_starred_store(self): |
972 | 949 | node = builder.extract_node("a, *b = 1, 2") |
973 | 950 | starred = node.targets[0].elts[1] |
1180 | 1157 | assert actual_arg.as_string() == expected_arg |
1181 | 1158 | |
1182 | 1159 | |
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 | ||
1183 | 1173 | def test_is_generator_for_yield_assignments(): |
1184 | 1174 | node = astroid.extract_node( |
1185 | 1175 | """ |
1199 | 1189 | |
1200 | 1190 | |
1201 | 1191 | class AsyncGeneratorTest: |
1202 | @test_utils.require_version(minver="3.6") | |
1203 | 1192 | def test_async_generator(self): |
1204 | 1193 | node = astroid.extract_node( |
1205 | 1194 | """ |
1217 | 1206 | assert inferred.pytype() == "builtins.async_generator" |
1218 | 1207 | assert inferred.display_type() == "AsyncGenerator" |
1219 | 1208 | |
1220 | @test_utils.require_version(maxver="3.5") | |
1221 | 1209 | def test_async_generator_is_generator_on_older_python(self): |
1222 | 1210 | node = astroid.extract_node( |
1223 | 1211 | """ |
1346 | 1334 | assert bool(node.is_generator()) |
1347 | 1335 | |
1348 | 1336 | |
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 | ||
1349 | 1361 | if __name__ == "__main__": |
1350 | 1362 | unittest.main() |
3 | 3 | # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com> |
4 | 4 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
5 | 5 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
6 | # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com> | |
6 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
7 | 8 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
8 | 9 | |
430 | 431 | for ast_node in ast_nodes[7:9]: |
431 | 432 | self.assertIs(next(ast_node.infer()), astroid.Uninferable) |
432 | 433 | |
433 | @test_utils.require_version(minver="3.0") | |
434 | 434 | def test_empty_return_annotation(self): |
435 | 435 | ast_node = builder.extract_node( |
436 | 436 | """ |
442 | 442 | self.assertIsInstance(annotations, astroid.Dict) |
443 | 443 | self.assertEqual(len(annotations.items), 0) |
444 | 444 | |
445 | @test_utils.require_version(minver="3.0") | |
446 | 445 | def test_builtin_dunder_init_does_not_crash_when_accessing_annotations(self): |
447 | 446 | ast_node = builder.extract_node( |
448 | 447 | """ |
456 | 455 | self.assertIsInstance(inferred, astroid.Dict) |
457 | 456 | self.assertEqual(len(inferred.items), 0) |
458 | 457 | |
459 | @test_utils.require_version(minver="3.0") | |
460 | 458 | def test_annotations_kwdefaults(self): |
461 | 459 | ast_node = builder.extract_node( |
462 | 460 | """ |
584 | 582 | inferred = next(node.infer()) |
585 | 583 | assert isinstance(inferred, astroid.Const) |
586 | 584 | 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) | |
587 | 596 | |
588 | 597 | def test_import_error(self): |
589 | 598 | ast_nodes = builder.extract_node( |
1 | 1 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
3 | 3 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
4 | # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com> | |
4 | 5 | |
5 | 6 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
6 | 7 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
13 | 14 | from astroid import exceptions |
14 | 15 | from astroid import nodes |
15 | 16 | from astroid import objects |
16 | from astroid import test_utils | |
17 | 17 | |
18 | 18 | |
19 | 19 | class ObjectsTest(unittest.TestCase): |
96 | 96 | self.assertIsInstance(second, bases.Instance) |
97 | 97 | self.assertEqual(second.qname(), "%s.super" % bases.BUILTINS) |
98 | 98 | |
99 | @test_utils.require_version(minver="3.0") | |
100 | 99 | def test_no_arguments_super(self): |
101 | 100 | ast_nodes = builder.extract_node( |
102 | 101 | """ |
0 | 0 | # -*- coding: utf-8 -*- |
1 | # Copyright (c) 2015-2019 Claudiu Popa <pcmanticore@gmail.com> | |
1 | # Copyright (c) 2015-2020 Claudiu Popa <pcmanticore@gmail.com> | |
2 | 2 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
3 | 3 | # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net> |
4 | 4 | # Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com> |
5 | 5 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
6 | 6 | # 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> | |
7 | 9 | |
8 | 10 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
9 | 11 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
17 | 19 | |
18 | 20 | import astroid |
19 | 21 | from astroid import extract_node |
20 | from astroid.test_utils import require_version | |
21 | 22 | from astroid import InferenceError |
22 | 23 | from astroid import nodes |
23 | 24 | from astroid import util |
66 | 67 | for2_assnode = next(assign_stmts[1].nodes_of_class(AssignName)) |
67 | 68 | self.assertRaises(InferenceError, list, for2_assnode.assigned_stmts()) |
68 | 69 | |
69 | @require_version(minver="3.0") | |
70 | 70 | def test_assigned_stmts_starred_for(self): |
71 | 71 | assign_stmts = extract_node( |
72 | 72 | """ |
100 | 100 | starred = next(assign_stmt.nodes_of_class(Starred)) |
101 | 101 | self.assertRaises(InferenceError, list, starred.assigned_stmts()) |
102 | 102 | |
103 | @require_version(minver="3.0") | |
104 | 103 | def test_assigned_stmts_starred_assnames(self): |
105 | 104 | self._helper_starred_expected_const("a, *b = (1, 2, 3, 4) #@", [2, 3, 4]) |
106 | 105 | self._helper_starred_expected_const("*a, b = (1, 2, 3) #@", [1, 2]) |
109 | 108 | self._helper_starred_expected_const("*b, a = (1, 2) #@", [1]) |
110 | 109 | self._helper_starred_expected_const("[*b] = (1, 2) #@", [1, 2]) |
111 | 110 | |
112 | @require_version(minver="3.0") | |
113 | 111 | def test_assigned_stmts_starred_yes(self): |
114 | 112 | # Not something iterable and known |
115 | 113 | self._helper_starred_expected("a, *b = range(3) #@", util.Uninferable) |
127 | 125 | "a, (*b, c), d = (1, (2, 3, 4), 5) #@", util.Uninferable |
128 | 126 | ) |
129 | 127 | |
130 | @require_version(minver="3.0") | |
131 | 128 | def test_assign_stmts_starred_fails(self): |
132 | 129 | # Too many starred |
133 | 130 | self._helper_starred_inference_error("a, *b, *c = (1, 2, 3) #@") |
158 | 155 | assigned = list(simple_mul_assnode_2.assigned_stmts()) |
159 | 156 | self.assertNameNodesEqual(["c"], assigned) |
160 | 157 | |
161 | @require_version(minver="3.6") | |
162 | 158 | def test_assigned_stmts_annassignments(self): |
163 | 159 | annassign_stmts = extract_node( |
164 | 160 | """ |
0 | 0 | # -*- coding: utf-8 -*- |
1 | 1 | # Copyright (c) 2010, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
2 | 2 | # 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> | |
4 | 4 | # Copyright (c) 2014 Google, Inc. |
5 | 5 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
6 | 6 | # Copyright (c) 2016 Jared Garst <jgarst@users.noreply.github.com> |
7 | 7 | # Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com> |
8 | 8 | # Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com> |
9 | 9 | # 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> | |
10 | 12 | |
11 | 13 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
12 | 14 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
26 | 28 | def setUpClass(cls): |
27 | 29 | cls.builder = AstroidBuilder() |
28 | 30 | |
29 | @require_version("3.4") | |
30 | 31 | def test_starred_notation(self): |
31 | 32 | astroid = self.builder.string_build("*a, b = [1, 2, 3]", "test", "test") |
32 | 33 | |
35 | 36 | |
36 | 37 | self.assertTrue(isinstance(node.assign_type(), Assign)) |
37 | 38 | |
38 | @require_version("3.4") | |
39 | 39 | def test_yield_from(self): |
40 | 40 | body = dedent( |
41 | 41 | """ |
52 | 52 | self.assertIsInstance(yieldfrom_stmt.value, YieldFrom) |
53 | 53 | self.assertEqual(yieldfrom_stmt.as_string(), "yield from iter([1, 2])") |
54 | 54 | |
55 | @require_version("3.4") | |
56 | 55 | def test_yield_from_is_generator(self): |
57 | 56 | body = dedent( |
58 | 57 | """ |
65 | 64 | self.assertIsInstance(func, FunctionDef) |
66 | 65 | self.assertTrue(func.is_generator()) |
67 | 66 | |
68 | @require_version("3.4") | |
69 | 67 | def test_yield_from_as_string(self): |
70 | 68 | body = dedent( |
71 | 69 | """ |
80 | 78 | |
81 | 79 | # metaclass tests |
82 | 80 | |
83 | @require_version("3.4") | |
84 | 81 | def test_simple_metaclass(self): |
85 | 82 | astroid = self.builder.string_build("class Test(metaclass=type): pass") |
86 | 83 | klass = astroid.body[0] |
89 | 86 | self.assertIsInstance(metaclass, ClassDef) |
90 | 87 | self.assertEqual(metaclass.name, "type") |
91 | 88 | |
92 | @require_version("3.4") | |
93 | 89 | def test_metaclass_error(self): |
94 | 90 | astroid = self.builder.string_build("class Test(metaclass=typ): pass") |
95 | 91 | klass = astroid.body[0] |
96 | 92 | self.assertFalse(klass.metaclass()) |
97 | 93 | |
98 | @require_version("3.4") | |
99 | 94 | def test_metaclass_imported(self): |
100 | 95 | astroid = self.builder.string_build( |
101 | 96 | dedent( |
110 | 105 | self.assertIsInstance(metaclass, ClassDef) |
111 | 106 | self.assertEqual(metaclass.name, "ABCMeta") |
112 | 107 | |
113 | @require_version("3.4") | |
114 | 108 | def test_metaclass_multiple_keywords(self): |
115 | 109 | astroid = self.builder.string_build( |
116 | 110 | "class Test(magic=None, metaclass=type): pass" |
121 | 115 | self.assertIsInstance(metaclass, ClassDef) |
122 | 116 | self.assertEqual(metaclass.name, "type") |
123 | 117 | |
124 | @require_version("3.4") | |
125 | 118 | def test_as_string(self): |
126 | 119 | body = dedent( |
127 | 120 | """ |
135 | 128 | klass.as_string(), "\n\nclass Test(metaclass=ABCMeta):\n pass\n" |
136 | 129 | ) |
137 | 130 | |
138 | @require_version("3.4") | |
139 | 131 | def test_old_syntax_works(self): |
140 | 132 | astroid = self.builder.string_build( |
141 | 133 | dedent( |
150 | 142 | metaclass = klass.metaclass() |
151 | 143 | self.assertIsNone(metaclass) |
152 | 144 | |
153 | @require_version("3.4") | |
154 | 145 | def test_metaclass_yes_leak(self): |
155 | 146 | astroid = self.builder.string_build( |
156 | 147 | dedent( |
165 | 156 | klass = astroid["Meta"] |
166 | 157 | self.assertIsNone(klass.metaclass()) |
167 | 158 | |
168 | @require_version("3.4") | |
169 | 159 | def test_parent_metaclass(self): |
170 | 160 | astroid = self.builder.string_build( |
171 | 161 | dedent( |
182 | 172 | self.assertIsInstance(metaclass, ClassDef) |
183 | 173 | self.assertEqual(metaclass.name, "ABCMeta") |
184 | 174 | |
185 | @require_version("3.4") | |
186 | 175 | def test_metaclass_ancestors(self): |
187 | 176 | astroid = self.builder.string_build( |
188 | 177 | dedent( |
211 | 200 | self.assertIsInstance(meta, ClassDef) |
212 | 201 | self.assertEqual(meta.name, metaclass) |
213 | 202 | |
214 | @require_version("3.4") | |
215 | 203 | def test_annotation_support(self): |
216 | 204 | astroid = self.builder.string_build( |
217 | 205 | dedent( |
254 | 242 | self.assertEqual(func.args.annotations[1].name, "str") |
255 | 243 | self.assertIsNone(func.returns) |
256 | 244 | |
257 | @require_version("3.4") | |
258 | 245 | def test_kwonlyargs_annotations_supper(self): |
259 | 246 | node = self.builder.string_build( |
260 | 247 | dedent( |
275 | 262 | self.assertIsNone(arguments.kwonlyargs_annotations[3]) |
276 | 263 | self.assertIsNone(arguments.kwonlyargs_annotations[4]) |
277 | 264 | |
278 | @require_version("3.4") | |
279 | 265 | def test_annotation_as_string(self): |
280 | 266 | code1 = dedent( |
281 | 267 | """ |
291 | 277 | func = extract_node(code) |
292 | 278 | self.assertEqual(func.as_string(), code) |
293 | 279 | |
294 | @require_version("3.5") | |
295 | 280 | def test_unpacking_in_dicts(self): |
296 | 281 | code = "{'x': 1, **{'y': 2}}" |
297 | 282 | node = extract_node(code) |
300 | 285 | self.assertIsInstance(keys[0], nodes.Const) |
301 | 286 | self.assertIsInstance(keys[1], nodes.DictUnpack) |
302 | 287 | |
303 | @require_version("3.5") | |
304 | 288 | def test_nested_unpacking_in_dicts(self): |
305 | 289 | code = "{'x': 1, **{'y': 2, **{'z': 3}}}" |
306 | 290 | node = extract_node(code) |
307 | 291 | self.assertEqual(node.as_string(), code) |
308 | 292 | |
309 | @require_version("3.5") | |
310 | 293 | def test_unpacking_in_dict_getitem(self): |
311 | 294 | node = extract_node("{1:2, **{2:3, 3:4}, **{5: 6}}") |
312 | 295 | for key, expected in ((1, 2), (2, 3), (3, 4), (5, 6)): |
314 | 297 | self.assertIsInstance(value, nodes.Const) |
315 | 298 | self.assertEqual(value.value, expected) |
316 | 299 | |
317 | @require_version("3.6") | |
318 | 300 | def test_format_string(self): |
319 | 301 | code = "f'{greetings} {person}'" |
320 | 302 | node = extract_node(code) |
321 | 303 | self.assertEqual(node.as_string(), code) |
322 | 304 | |
323 | @require_version("3.6") | |
324 | 305 | def test_underscores_in_numeral_literal(self): |
325 | 306 | pairs = [("10_1000", 101000), ("10_000_000", 10000000), ("0x_FF_FF", 65535)] |
326 | 307 | for value, expected in pairs: |
329 | 310 | self.assertIsInstance(inferred, nodes.Const) |
330 | 311 | self.assertEqual(inferred.value, expected) |
331 | 312 | |
332 | @require_version("3.6") | |
333 | 313 | def test_async_comprehensions(self): |
334 | 314 | async_comprehensions = [ |
335 | 315 | extract_node( |
378 | 358 | node = extract_node(comp) |
379 | 359 | self.assertTrue(node.generators[0].is_async) |
380 | 360 | |
381 | @require_version("3.6") | |
382 | 361 | def test_async_comprehensions_as_string(self): |
383 | 362 | func_bodies = [ |
384 | 363 | "return [i async for i in aiter() if condition(i)]", |
0 | 0 | # 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> | |
2 | 2 | # Copyright (c) 2014 Google, Inc. |
3 | 3 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
4 | 4 | # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> |
5 | 5 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
6 | 6 | # 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> | |
7 | 9 | |
8 | 10 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
9 | 11 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
20 | 22 | build_function, |
21 | 23 | build_from_import, |
22 | 24 | ) |
23 | from astroid import test_utils | |
24 | 25 | |
25 | 26 | |
26 | 27 | class RawBuildingTC(unittest.TestCase): |
68 | 69 | self.assertEqual(len(names), len(node.names)) |
69 | 70 | |
70 | 71 | @unittest.skipIf(platform.python_implementation() == "PyPy", "Only affects CPython") |
71 | @test_utils.require_version(minver="3.0") | |
72 | 72 | def test_io_is__io(self): |
73 | 73 | # _io module calls itself io. This leads |
74 | 74 | # to cyclic dependencies when astroid tries to resolve |
6 | 6 | # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net> |
7 | 7 | # Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com> |
8 | 8 | # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> |
9 | # Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com> | |
9 | 10 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
11 | # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com> | |
10 | 12 | |
11 | 13 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
12 | 14 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
21 | 23 | from astroid import exceptions |
22 | 24 | from astroid.raw_building import build_module |
23 | 25 | from astroid.manager import AstroidManager |
24 | from astroid.test_utils import require_version | |
25 | 26 | from astroid import transforms |
26 | 27 | from . import resources |
27 | 28 | |
92 | 93 | data = """ |
93 | 94 | from numpy import multiply |
94 | 95 | |
95 | multiply(1, 2, 3) | |
96 | multiply([1, 2], [3, 4]) | |
96 | 97 | """ |
97 | 98 | astroid = builder.string_build(data, __name__, __file__) |
98 | 99 | callfunc = astroid.body[1].value.func |
99 | 100 | inferred = callfunc.inferred() |
100 | 101 | self.assertEqual(len(inferred), 1) |
101 | 102 | |
102 | @require_version("3.0") | |
103 | 103 | def test_nameconstant(self): |
104 | 104 | # used to fail for Python 3.4 |
105 | 105 | builder = AstroidBuilder() |
323 | 323 | a = property(lambda x: x, lambda x: x) |
324 | 324 | |
325 | 325 | |
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 | ||
326 | 356 | if __name__ == "__main__": |
327 | 357 | unittest.main() |
14 | 14 | # Copyright (c) 2018-2019 Ville Skyttä <ville.skytta@iki.fi> |
15 | 15 | # Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com> |
16 | 16 | # Copyright (c) 2018 Anthony Sottile <asottile@umich.edu> |
17 | # Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com> | |
17 | 18 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
18 | 19 | # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
19 | 20 | # 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> | |
21 | 23 | |
22 | 24 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
23 | 25 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
51 | 53 | from astroid.bases import BUILTINS, Instance, BoundMethod, UnboundMethod, Generator |
52 | 54 | from astroid import test_utils |
53 | 55 | 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 | |
54 | 63 | |
55 | 64 | |
56 | 65 | def _test_dict_interface(self, node, test_attr): |
333 | 342 | func = self.module["four_args"] |
334 | 343 | self.assertEqual(func.args.format_args(), "a, b, c, d") |
335 | 344 | |
336 | @test_utils.require_version("3.0") | |
337 | 345 | def test_format_args_keyword_only_args(self): |
338 | 346 | node = ( |
339 | 347 | builder.parse( |
594 | 602 | self.assertIsInstance(inferred, nodes.Const) |
595 | 603 | self.assertEqual(inferred.value, 42) |
596 | 604 | |
597 | @test_utils.require_version(minver="3.0") | |
598 | 605 | def test_return_annotation_is_not_the_last(self): |
599 | 606 | func = builder.extract_node( |
600 | 607 | """ |
608 | 615 | self.assertIsInstance(last_child, nodes.Return) |
609 | 616 | self.assertEqual(func.tolineno, 5) |
610 | 617 | |
611 | @test_utils.require_version(minver="3.6") | |
612 | 618 | def test_method_init_subclass(self): |
613 | 619 | klass = builder.extract_node( |
614 | 620 | """ |
621 | 627 | self.assertEqual([n.name for n in method.args.args], ["cls"]) |
622 | 628 | self.assertEqual(method.type, "classmethod") |
623 | 629 | |
624 | @test_utils.require_version(minver="3.0") | |
625 | 630 | def test_dunder_class_local_to_method(self): |
626 | 631 | node = builder.extract_node( |
627 | 632 | """ |
634 | 639 | self.assertIsInstance(inferred, nodes.ClassDef) |
635 | 640 | self.assertEqual(inferred.name, "MyClass") |
636 | 641 | |
637 | @test_utils.require_version(minver="3.0") | |
638 | 642 | def test_dunder_class_local_to_function(self): |
639 | 643 | node = builder.extract_node( |
640 | 644 | """ |
645 | 649 | with self.assertRaises(NameInferenceError): |
646 | 650 | next(node.infer()) |
647 | 651 | |
648 | @test_utils.require_version(minver="3.0") | |
649 | 652 | def test_dunder_class_local_to_classmethod(self): |
650 | 653 | node = builder.extract_node( |
651 | 654 | """ |
1090 | 1093 | for klass in ast_nodes: |
1091 | 1094 | self.assertEqual(None, klass.metaclass()) |
1092 | 1095 | |
1096 | @unittest.skipUnless(HAS_SIX, "These tests require the six library") | |
1093 | 1097 | def test_metaclass_generator_hack(self): |
1094 | 1098 | klass = builder.extract_node( |
1095 | 1099 | """ |
1102 | 1106 | self.assertEqual(["object"], [base.name for base in klass.ancestors()]) |
1103 | 1107 | self.assertEqual("type", klass.metaclass().name) |
1104 | 1108 | |
1105 | def test_using_six_add_metaclass(self): | |
1109 | def test_add_metaclass(self): | |
1106 | 1110 | klass = builder.extract_node( |
1107 | 1111 | """ |
1108 | import six | |
1109 | 1112 | import abc |
1110 | 1113 | |
1111 | @six.add_metaclass(abc.ABCMeta) | |
1112 | class WithMeta(object): | |
1114 | class WithMeta(object, metaclass=abc.ABCMeta): | |
1113 | 1115 | pass |
1114 | 1116 | """ |
1115 | 1117 | ) |
1118 | 1120 | self.assertIsInstance(metaclass, scoped_nodes.ClassDef) |
1119 | 1121 | self.assertIn(metaclass.qname(), ("abc.ABCMeta", "_py_abc.ABCMeta")) |
1120 | 1122 | |
1123 | @unittest.skipUnless(HAS_SIX, "These tests require the six library") | |
1121 | 1124 | def test_using_invalid_six_add_metaclass_call(self): |
1122 | 1125 | klass = builder.extract_node( |
1123 | 1126 | """ |
1270 | 1273 | def assertEqualMro(self, klass, expected_mro): |
1271 | 1274 | self.assertEqual([member.name for member in klass.mro()], expected_mro) |
1272 | 1275 | |
1276 | @unittest.skipUnless(HAS_SIX, "These tests require the six library") | |
1273 | 1277 | def test_with_metaclass_mro(self): |
1274 | 1278 | astroid = builder.parse( |
1275 | 1279 | """ |
1416 | 1420 | ], |
1417 | 1421 | ) |
1418 | 1422 | |
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 | ||
1419 | 1439 | def test_generator_from_infer_call_result_parent(self): |
1420 | 1440 | func = builder.extract_node( |
1421 | 1441 | """ |
1481 | 1501 | def test_metaclass_lookup_inference_errors(self): |
1482 | 1502 | module = builder.parse( |
1483 | 1503 | """ |
1484 | import six | |
1485 | ||
1486 | 1504 | class Metaclass(type): |
1487 | 1505 | foo = lala |
1488 | 1506 | |
1489 | @six.add_metaclass(Metaclass) | |
1490 | class B(object): pass | |
1507 | class B(object, metaclass=Metaclass): pass | |
1491 | 1508 | """ |
1492 | 1509 | ) |
1493 | 1510 | cls = module["B"] |
1496 | 1513 | def test_metaclass_lookup(self): |
1497 | 1514 | module = builder.parse( |
1498 | 1515 | """ |
1499 | import six | |
1500 | ||
1501 | 1516 | class Metaclass(type): |
1502 | 1517 | foo = 42 |
1503 | 1518 | @classmethod |
1512 | 1527 | def static(): |
1513 | 1528 | pass |
1514 | 1529 | |
1515 | @six.add_metaclass(Metaclass) | |
1516 | class A(object): | |
1530 | class A(object, metaclass=Metaclass): | |
1517 | 1531 | pass |
1518 | 1532 | """ |
1519 | 1533 | ) |
1733 | 1747 | parent = bind.scope() |
1734 | 1748 | self.assertEqual(len(parent.extra_decorators), 0) |
1735 | 1749 | |
1736 | @test_utils.require_version(minver="3.0") | |
1737 | 1750 | def test_class_keywords(self): |
1738 | 1751 | data = """ |
1739 | 1752 | 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> | |
1 | 1 | # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com> |
2 | 2 | # Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net> |
3 | 3 | # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com> |
4 | 4 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
5 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
5 | 6 | |
6 | 7 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
7 | 8 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |
0 | 0 | # Copyright (c) 2008-2010, 2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr> |
1 | 1 | # 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> | |
3 | 3 | # Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com> |
4 | 4 | # Copyright (c) 2016 Dave Baum <dbaum@google.com> |
5 | 5 | # Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk> |
6 | # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> | |
6 | 7 | |
7 | 8 | # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html |
8 | 9 | # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER |