summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorhippo91 <guillaume.peillex@gmail.com>2020-06-20 11:37:37 +0200
committerhippo91 <guillaume.peillex@gmail.com>2020-06-20 11:37:37 +0200
commit1322e5d7790b7e3aa629a4e86e3b9f9b5846886b (patch)
treea6041c102f12f5cbb2a9f9f9e57edfb573d4a37f /tests
parent14de71c7838e4bae329292035f1a225aa5218317 (diff)
parent92f556842c84a2b3cc33a1638fc625b4f67d0d1f (diff)
downloadastroid-git-1322e5d7790b7e3aa629a4e86e3b9f9b5846886b.tar.gz
Merge branch 'master' into sum_and_multiply
Diffstat (limited to 'tests')
-rw-r--r--tests/resources.py5
-rw-r--r--tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.eggbin1222 -> 0 bytes
-rw-r--r--tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zipbin1222 -> 0 bytes
-rw-r--r--tests/testdata/python2/data/SSL1/Connection1.py5
-rw-r--r--tests/testdata/python2/data/SSL1/__init__.py1
-rw-r--r--tests/testdata/python2/data/__init__.py1
-rw-r--r--tests/testdata/python2/data/absimp/__init__.py5
-rw-r--r--tests/testdata/python2/data/absimp/sidepackage/__init__.py3
-rw-r--r--tests/testdata/python2/data/absimp/string.py3
-rw-r--r--tests/testdata/python2/data/absimport.py3
-rw-r--r--tests/testdata/python2/data/all.py9
-rw-r--r--tests/testdata/python2/data/appl/__init__.py3
-rw-r--r--tests/testdata/python2/data/appl/myConnection.py12
-rw-r--r--tests/testdata/python2/data/contribute_to_namespace/namespace_pep_420/submodule.py1
-rw-r--r--tests/testdata/python2/data/descriptor_crash.py11
-rw-r--r--tests/testdata/python2/data/email.py1
-rw-r--r--tests/testdata/python2/data/find_test/module.py0
-rw-r--r--tests/testdata/python2/data/find_test/module2.py0
-rw-r--r--tests/testdata/python2/data/find_test/noendingnewline.py0
-rw-r--r--tests/testdata/python2/data/find_test/nonregr.py0
-rw-r--r--tests/testdata/python2/data/foogle/fax/__init__.py0
-rw-r--r--tests/testdata/python2/data/foogle/fax/a.py1
-rw-r--r--tests/testdata/python2/data/foogle_fax-0.12.5-py2.7-nspkg.pth2
-rw-r--r--tests/testdata/python2/data/format.py34
-rw-r--r--tests/testdata/python2/data/invalid_encoding.py1
-rw-r--r--tests/testdata/python2/data/lmfp/__init__.py2
-rw-r--r--tests/testdata/python2/data/lmfp/foo.py6
-rw-r--r--tests/testdata/python2/data/module.py90
-rw-r--r--tests/testdata/python2/data/module1abs/__init__.py4
-rw-r--r--tests/testdata/python2/data/module1abs/core.py1
-rw-r--r--tests/testdata/python2/data/module2.py143
-rw-r--r--tests/testdata/python2/data/namespace_pep_420/module.py1
-rw-r--r--tests/testdata/python2/data/noendingnewline.py36
-rw-r--r--tests/testdata/python2/data/nonregr.py57
-rw-r--r--tests/testdata/python2/data/notall.py7
-rw-r--r--tests/testdata/python2/data/notamodule/file.py0
-rw-r--r--tests/testdata/python2/data/operator_precedence.py27
-rw-r--r--tests/testdata/python2/data/package/__init__.py4
-rw-r--r--tests/testdata/python2/data/package/absimport.py6
-rw-r--r--tests/testdata/python2/data/package/hello.py2
-rw-r--r--tests/testdata/python2/data/package/import_package_subpackage_module.py49
-rw-r--r--tests/testdata/python2/data/package/subpackage/__init__.py1
-rw-r--r--tests/testdata/python2/data/package/subpackage/module.py1
-rw-r--r--tests/testdata/python2/data/path_pkg_resources_1/package/__init__.py1
-rw-r--r--tests/testdata/python2/data/path_pkg_resources_1/package/foo.py0
-rw-r--r--tests/testdata/python2/data/path_pkg_resources_2/package/__init__.py1
-rw-r--r--tests/testdata/python2/data/path_pkg_resources_2/package/bar.py0
-rw-r--r--tests/testdata/python2/data/path_pkg_resources_3/package/__init__.py1
-rw-r--r--tests/testdata/python2/data/path_pkg_resources_3/package/baz.py0
-rw-r--r--tests/testdata/python2/data/path_pkgutil_1/package/__init__.py2
-rw-r--r--tests/testdata/python2/data/path_pkgutil_1/package/foo.py0
-rw-r--r--tests/testdata/python2/data/path_pkgutil_2/package/__init__.py2
-rw-r--r--tests/testdata/python2/data/path_pkgutil_2/package/bar.py0
-rw-r--r--tests/testdata/python2/data/path_pkgutil_3/package/__init__.py2
-rw-r--r--tests/testdata/python2/data/path_pkgutil_3/package/baz.py0
-rw-r--r--tests/testdata/python2/data/recursion.py3
-rw-r--r--tests/testdata/python2/data/tmp__init__.py0
-rw-r--r--tests/testdata/python2/data/unicode_package/__init__.py1
-rw-r--r--tests/testdata/python2/data/unicode_package/core/__init__.py0
-rw-r--r--tests/testdata/python3/data/metaclass_recursion/__init__.py (renamed from tests/testdata/python2/data/find_test/__init__.py)0
-rw-r--r--tests/testdata/python3/data/metaclass_recursion/monkeypatch.py17
-rw-r--r--tests/testdata/python3/data/metaclass_recursion/parent.py3
-rw-r--r--tests/unittest_brain.py52
-rw-r--r--tests/unittest_brain_numpy_core_fromnumeric.py3
-rw-r--r--tests/unittest_brain_numpy_core_function_base.py3
-rw-r--r--tests/unittest_brain_numpy_core_multiarray.py3
-rw-r--r--tests/unittest_brain_numpy_core_numeric.py3
-rw-r--r--tests/unittest_brain_numpy_core_numerictypes.py33
-rw-r--r--tests/unittest_brain_numpy_core_umath.py3
-rw-r--r--tests/unittest_brain_numpy_ndarray.py36
-rw-r--r--tests/unittest_brain_numpy_random_mtrand.py5
-rw-r--r--tests/unittest_builder.py5
-rw-r--r--tests/unittest_helpers.py18
-rw-r--r--tests/unittest_inference.py417
-rw-r--r--tests/unittest_lookup.py4
-rw-r--r--tests/unittest_manager.py18
-rw-r--r--tests/unittest_modutils.py13
-rw-r--r--tests/unittest_nodes.py93
-rw-r--r--tests/unittest_object_model.py73
-rw-r--r--tests/unittest_objects.py25
-rw-r--r--tests/unittest_protocols.py3
-rw-r--r--tests/unittest_python3.py3
-rw-r--r--tests/unittest_raw_building.py3
-rw-r--r--tests/unittest_regrtest.py45
-rw-r--r--tests/unittest_scoped_nodes.py249
-rw-r--r--tests/unittest_transforms.py3
-rw-r--r--tests/unittest_utils.py3
87 files changed, 725 insertions, 962 deletions
diff --git a/tests/resources.py b/tests/resources.py
index ee57b9fe..7113f2b1 100644
--- a/tests/resources.py
+++ b/tests/resources.py
@@ -1,7 +1,8 @@
# Copyright (c) 2014 Google, Inc.
-# Copyright (c) 2015-2016 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2015-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -14,7 +15,7 @@ from astroid import MANAGER
from astroid.bases import BUILTINS
-DATA_DIR = os.path.join("testdata", "python{}".format(sys.version_info[0]))
+DATA_DIR = os.path.join("testdata", "python3")
RESOURCE_PATH = os.path.join(os.path.dirname(__file__), DATA_DIR, "data")
diff --git a/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg b/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg
deleted file mode 100644
index f62599c7..00000000
--- a/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip b/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip
deleted file mode 100644
index f62599c7..00000000
--- a/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/python2/data/SSL1/Connection1.py b/tests/testdata/python2/data/SSL1/Connection1.py
deleted file mode 100644
index 1307b239..00000000
--- a/tests/testdata/python2/data/SSL1/Connection1.py
+++ /dev/null
@@ -1,5 +0,0 @@
-
-class Connection:
-
- def __init__(self, ctx, sock=None):
- print('init Connection')
diff --git a/tests/testdata/python2/data/SSL1/__init__.py b/tests/testdata/python2/data/SSL1/__init__.py
deleted file mode 100644
index a007b049..00000000
--- a/tests/testdata/python2/data/SSL1/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from Connection1 import Connection
diff --git a/tests/testdata/python2/data/__init__.py b/tests/testdata/python2/data/__init__.py
deleted file mode 100644
index 332e2e72..00000000
--- a/tests/testdata/python2/data/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $"
diff --git a/tests/testdata/python2/data/absimp/__init__.py b/tests/testdata/python2/data/absimp/__init__.py
deleted file mode 100644
index b98444df..00000000
--- a/tests/testdata/python2/data/absimp/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-"""a package with absolute import activated
-"""
-
-from __future__ import absolute_import
-
diff --git a/tests/testdata/python2/data/absimp/sidepackage/__init__.py b/tests/testdata/python2/data/absimp/sidepackage/__init__.py
deleted file mode 100644
index 239499a6..00000000
--- a/tests/testdata/python2/data/absimp/sidepackage/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""a side package with nothing in it
-"""
-
diff --git a/tests/testdata/python2/data/absimp/string.py b/tests/testdata/python2/data/absimp/string.py
deleted file mode 100644
index e68e7496..00000000
--- a/tests/testdata/python2/data/absimp/string.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from __future__ import absolute_import, print_function
-import string
-print(string)
diff --git a/tests/testdata/python2/data/absimport.py b/tests/testdata/python2/data/absimport.py
deleted file mode 100644
index f98effa6..00000000
--- a/tests/testdata/python2/data/absimport.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from __future__ import absolute_import
-import email
-from email import message
diff --git a/tests/testdata/python2/data/all.py b/tests/testdata/python2/data/all.py
deleted file mode 100644
index 23f7d2b6..00000000
--- a/tests/testdata/python2/data/all.py
+++ /dev/null
@@ -1,9 +0,0 @@
-
-name = 'a'
-_bla = 2
-other = 'o'
-class Aaa: pass
-
-def func(): print 'yo'
-
-__all__ = 'Aaa', '_bla', 'name'
diff --git a/tests/testdata/python2/data/appl/__init__.py b/tests/testdata/python2/data/appl/__init__.py
deleted file mode 100644
index d652ffd9..00000000
--- a/tests/testdata/python2/data/appl/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Init
-"""
diff --git a/tests/testdata/python2/data/appl/myConnection.py b/tests/testdata/python2/data/appl/myConnection.py
deleted file mode 100644
index 5b24b259..00000000
--- a/tests/testdata/python2/data/appl/myConnection.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from __future__ import print_function
-from data import SSL1
-class MyConnection(SSL1.Connection):
-
- """An SSL connection."""
-
- def __init__(self, dummy):
- print('MyConnection init')
-
-if __name__ == '__main__':
- myConnection = MyConnection(' ')
- raw_input('Press Enter to continue...')
diff --git a/tests/testdata/python2/data/contribute_to_namespace/namespace_pep_420/submodule.py b/tests/testdata/python2/data/contribute_to_namespace/namespace_pep_420/submodule.py
deleted file mode 100644
index 6fbcff41..00000000
--- a/tests/testdata/python2/data/contribute_to_namespace/namespace_pep_420/submodule.py
+++ /dev/null
@@ -1 +0,0 @@
-var = 42 \ No newline at end of file
diff --git a/tests/testdata/python2/data/descriptor_crash.py b/tests/testdata/python2/data/descriptor_crash.py
deleted file mode 100644
index 11fbb4a2..00000000
--- a/tests/testdata/python2/data/descriptor_crash.py
+++ /dev/null
@@ -1,11 +0,0 @@
-
-import urllib
-
-class Page(object):
- _urlOpen = staticmethod(urllib.urlopen)
-
- def getPage(self, url):
- handle = self._urlOpen(url)
- data = handle.read()
- handle.close()
- return data
diff --git a/tests/testdata/python2/data/email.py b/tests/testdata/python2/data/email.py
deleted file mode 100644
index dc593564..00000000
--- a/tests/testdata/python2/data/email.py
+++ /dev/null
@@ -1 +0,0 @@
-"""fake email module to test absolute import doesn't grab this one"""
diff --git a/tests/testdata/python2/data/find_test/module.py b/tests/testdata/python2/data/find_test/module.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/find_test/module.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/find_test/module2.py b/tests/testdata/python2/data/find_test/module2.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/find_test/module2.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/find_test/noendingnewline.py b/tests/testdata/python2/data/find_test/noendingnewline.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/find_test/noendingnewline.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/find_test/nonregr.py b/tests/testdata/python2/data/find_test/nonregr.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/find_test/nonregr.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/foogle/fax/__init__.py b/tests/testdata/python2/data/foogle/fax/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/foogle/fax/__init__.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/foogle/fax/a.py b/tests/testdata/python2/data/foogle/fax/a.py
deleted file mode 100644
index 3d2b4b14..00000000
--- a/tests/testdata/python2/data/foogle/fax/a.py
+++ /dev/null
@@ -1 +0,0 @@
-x = 1 \ No newline at end of file
diff --git a/tests/testdata/python2/data/foogle_fax-0.12.5-py2.7-nspkg.pth b/tests/testdata/python2/data/foogle_fax-0.12.5-py2.7-nspkg.pth
deleted file mode 100644
index eeb7ecac..00000000
--- a/tests/testdata/python2/data/foogle_fax-0.12.5-py2.7-nspkg.pth
+++ /dev/null
@@ -1,2 +0,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)
-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)
diff --git a/tests/testdata/python2/data/format.py b/tests/testdata/python2/data/format.py
deleted file mode 100644
index 73797061..00000000
--- a/tests/testdata/python2/data/format.py
+++ /dev/null
@@ -1,34 +0,0 @@
-"""A multiline string
-"""
-
-function('aeozrijz\
-earzer', hop)
-# XXX write test
-x = [i for i in range(5)
- if i % 4]
-
-fonction(1,
- 2,
- 3,
- 4)
-
-def definition(a,
- b,
- c):
- return a + b + c
-
-class debile(dict,
- object):
- pass
-
-if aaaa: pass
-else:
- aaaa,bbbb = 1,2
- aaaa,bbbb = bbbb,aaaa
-# XXX write test
-hop = \
- aaaa
-
-
-__revision__.lower();
-
diff --git a/tests/testdata/python2/data/invalid_encoding.py b/tests/testdata/python2/data/invalid_encoding.py
deleted file mode 100644
index dddd208e..00000000
--- a/tests/testdata/python2/data/invalid_encoding.py
+++ /dev/null
@@ -1 +0,0 @@
-# -*- coding: lala -*- \ No newline at end of file
diff --git a/tests/testdata/python2/data/lmfp/__init__.py b/tests/testdata/python2/data/lmfp/__init__.py
deleted file mode 100644
index 74b26b82..00000000
--- a/tests/testdata/python2/data/lmfp/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# force a "direct" python import
-from . import foo
diff --git a/tests/testdata/python2/data/lmfp/foo.py b/tests/testdata/python2/data/lmfp/foo.py
deleted file mode 100644
index 8f7de1e8..00000000
--- a/tests/testdata/python2/data/lmfp/foo.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import sys
-if not getattr(sys, 'bar', None):
- sys.just_once = []
-# there used to be two numbers here because
-# of a load_module_from_path bug
-sys.just_once.append(42)
diff --git a/tests/testdata/python2/data/module.py b/tests/testdata/python2/data/module.py
deleted file mode 100644
index 1205c1dd..00000000
--- a/tests/testdata/python2/data/module.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""test module for astroid
-"""
-
-__revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $'
-from astroid.node_classes import Name as NameNode
-from astroid import modutils
-from astroid.utils import *
-import os.path
-MY_DICT = {}
-
-def global_access(key, val):
- """function test"""
- local = 1
- MY_DICT[key] = val
- for i in val:
- if i:
- del MY_DICT[i]
- continue
- else:
- break
- else:
- return local
-
-
-class YO:
- """hehe
- haha"""
- a = 1
-
- def __init__(self):
- try:
- self.yo = 1
- except ValueError, ex:
- pass
- except (NameError, TypeError):
- raise XXXError()
- except:
- raise
-
-
-
-class YOUPI(YO):
- class_attr = None
-
- def __init__(self):
- self.member = None
-
- def method(self):
- """method
- test"""
- global MY_DICT
- try:
- MY_DICT = {}
- local = None
- autre = [a for (a, b) in MY_DICT if b]
- if b in autre:
- return b
- elif a in autre:
- return a
- global_access(local, val=autre)
- finally:
- return local
-
- def static_method():
- """static method test"""
- assert MY_DICT, '???'
- static_method = staticmethod(static_method)
-
- def class_method(cls):
- """class method test"""
- exec a in b
- class_method = classmethod(class_method)
-
-
-def four_args(a, b, c, d):
- """four arguments (was nested_args)"""
- pass
- while 1:
- if a:
- break
- a += +1
- else:
- b += -2
- if c:
- d = a and (b or c)
- else:
- c = a and b or d
- map(lambda x, y: (y, x), a)
-redirect = four_args
-
diff --git a/tests/testdata/python2/data/module1abs/__init__.py b/tests/testdata/python2/data/module1abs/__init__.py
deleted file mode 100644
index 42949a44..00000000
--- a/tests/testdata/python2/data/module1abs/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import absolute_import, print_function
-from . import core
-from .core import *
-print(sys.version)
diff --git a/tests/testdata/python2/data/module1abs/core.py b/tests/testdata/python2/data/module1abs/core.py
deleted file mode 100644
index de101117..00000000
--- a/tests/testdata/python2/data/module1abs/core.py
+++ /dev/null
@@ -1 +0,0 @@
-import sys
diff --git a/tests/testdata/python2/data/module2.py b/tests/testdata/python2/data/module2.py
deleted file mode 100644
index 7042a4c1..00000000
--- a/tests/testdata/python2/data/module2.py
+++ /dev/null
@@ -1,143 +0,0 @@
-from data.module import YO, YOUPI
-import data
-
-
-class Specialization(YOUPI, YO):
- pass
-
-
-
-class Metaclass(type):
- pass
-
-
-
-class Interface:
- pass
-
-
-
-class MyIFace(Interface):
- pass
-
-
-
-class AnotherIFace(Interface):
- pass
-
-
-
-class MyException(Exception):
- pass
-
-
-
-class MyError(MyException):
- pass
-
-
-
-class AbstractClass(object):
-
- def to_override(self, whatever):
- raise NotImplementedError()
-
- def return_something(self, param):
- if param:
- return 'toto'
- return
-
-
-
-class Concrete0:
- __implements__ = MyIFace
-
-
-
-class Concrete1:
- __implements__ = (MyIFace, AnotherIFace)
-
-
-
-class Concrete2:
- __implements__ = (MyIFace, AnotherIFace)
-
-
-
-class Concrete23(Concrete1):
- pass
-
-del YO.member
-del YO
-[SYN1, SYN2] = (Concrete0, Concrete1)
-assert '1'
-b = (1 | 2) & (3 ^ 8)
-bb = 1 | (two | 6)
-ccc = one & two & three
-dddd = x ^ (o ^ r)
-exec 'c = 3'
-exec 'c = 3' in {}, {}
-
-def raise_string(a=2, *args, **kwargs):
- raise Exception, 'yo'
- yield 'coucou'
- yield
-a = b + 2
-c = b * 2
-c = b / 2
-c = b // 2
-c = b - 2
-c = b % 2
-c = b**2
-c = b << 2
-c = b >> 2
-c = ~b
-c = not b
-d = [c]
-e = d[:]
-e = d[a:b:c]
-raise_string(*args, **kwargs)
-print >> stream, 'bonjour'
-print >> stream, 'salut',
-
-def make_class(any, base=data.module.YO, *args, **kwargs):
- """check base is correctly resolved to Concrete0"""
-
-
- class Aaaa(base):
- """dynamic class"""
-
-
- return Aaaa
-from os.path import abspath
-import os as myos
-
-
-class A:
- pass
-
-
-
-class A(A):
- pass
-
-
-def generator():
- """A generator."""
- yield
-
-def not_a_generator():
- """A function that contains generator, but is not one."""
-
- def generator():
- yield
- genl = lambda: (yield)
-
-def with_metaclass(meta, *bases):
- return meta('NewBase', bases, {})
-
-
-class NotMetaclass(with_metaclass(Metaclass)):
- pass
-
-
diff --git a/tests/testdata/python2/data/namespace_pep_420/module.py b/tests/testdata/python2/data/namespace_pep_420/module.py
deleted file mode 100644
index a4d111e6..00000000
--- a/tests/testdata/python2/data/namespace_pep_420/module.py
+++ /dev/null
@@ -1 +0,0 @@
-from namespace_pep_420.submodule import var \ No newline at end of file
diff --git a/tests/testdata/python2/data/noendingnewline.py b/tests/testdata/python2/data/noendingnewline.py
deleted file mode 100644
index e1d6e4a1..00000000
--- a/tests/testdata/python2/data/noendingnewline.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import unittest
-
-
-class TestCase(unittest.TestCase):
-
- def setUp(self):
- unittest.TestCase.setUp(self)
-
-
- def tearDown(self):
- unittest.TestCase.tearDown(self)
-
- def testIt(self):
- self.a = 10
- self.xxx()
-
-
- def xxx(self):
- if False:
- pass
- print 'a'
-
- if False:
- pass
- pass
-
- if False:
- pass
- print 'rara'
-
-
-if __name__ == '__main__':
- print 'test2'
- unittest.main()
-
-
diff --git a/tests/testdata/python2/data/nonregr.py b/tests/testdata/python2/data/nonregr.py
deleted file mode 100644
index 813469fe..00000000
--- a/tests/testdata/python2/data/nonregr.py
+++ /dev/null
@@ -1,57 +0,0 @@
-from __future__ import generators, print_function
-
-try:
- enumerate = enumerate
-except NameError:
-
- def enumerate(iterable):
- """emulates the python2.3 enumerate() function"""
- i = 0
- for val in iterable:
- yield i, val
- i += 1
-
-def toto(value):
- for k, v in value:
- print(v.get('yo'))
-
-
-import imp
-fp, mpath, desc = imp.find_module('optparse',a)
-s_opt = imp.load_module('std_optparse', fp, mpath, desc)
-
-class OptionParser(s_opt.OptionParser):
-
- def parse_args(self, args=None, values=None, real_optparse=False):
- if real_optparse:
- pass
-## return super(OptionParser, self).parse_args()
- else:
- import optcomp
- optcomp.completion(self)
-
-
-class Aaa(object):
- """docstring"""
- def __init__(self):
- self.__setattr__('a','b')
- pass
-
- def one_public(self):
- """docstring"""
- pass
-
- def another_public(self):
- """docstring"""
- pass
-
-class Ccc(Aaa):
- """docstring"""
-
- class Ddd(Aaa):
- """docstring"""
- pass
-
- class Eee(Ddd):
- """docstring"""
- pass
diff --git a/tests/testdata/python2/data/notall.py b/tests/testdata/python2/data/notall.py
deleted file mode 100644
index 042491e0..00000000
--- a/tests/testdata/python2/data/notall.py
+++ /dev/null
@@ -1,7 +0,0 @@
-name = 'a'
-_bla = 2
-other = 'o'
-class Aaa: pass
-
-def func(): return 'yo'
-
diff --git a/tests/testdata/python2/data/notamodule/file.py b/tests/testdata/python2/data/notamodule/file.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/notamodule/file.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/operator_precedence.py b/tests/testdata/python2/data/operator_precedence.py
deleted file mode 100644
index 07a3c772..00000000
--- a/tests/testdata/python2/data/operator_precedence.py
+++ /dev/null
@@ -1,27 +0,0 @@
-assert not not True == True
-assert (not False or True) == True
-assert True or False and True
-assert (True or False) and True
-
-assert True is not (False is True) == False
-assert True is (not False is True == False)
-
-assert 1 + 2 + 3 == 6
-assert 5 - 4 + 3 == 4
-assert 4 - 5 - 6 == -7
-assert 7 - (8 - 9) == 8
-assert 2**3**4 == 2**81
-assert (2**3)**4 == 8**4
-
-assert 1 + 2 if (0.5 if True else 0.2) else 1 if True else 2 == 3
-assert (0 if True else 1) if False else 2 == 2
-assert lambda x: x if (0 if False else 0) else 0 if False else 0
-assert (lambda x: x) if (0 if True else 0.2) else 1 if True else 2 == 1
-
-assert ('1' + '2').replace('1', '3') == '32'
-assert (lambda x: x)(1) == 1
-assert ([0] + [1])[1] == 1
-assert (lambda x: lambda: x + 1)(2)() == 3
-
-f = lambda x, y, z: y(x, z)
-assert f(1, lambda x, y: x + y[1], (2, 3)) == 4
diff --git a/tests/testdata/python2/data/package/__init__.py b/tests/testdata/python2/data/package/__init__.py
deleted file mode 100644
index 575d18b1..00000000
--- a/tests/testdata/python2/data/package/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-"""package's __init__ file"""
-
-
-from . import subpackage
diff --git a/tests/testdata/python2/data/package/absimport.py b/tests/testdata/python2/data/package/absimport.py
deleted file mode 100644
index 33ed117c..00000000
--- a/tests/testdata/python2/data/package/absimport.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import absolute_import, print_function
-import import_package_subpackage_module # fail
-print(import_package_subpackage_module)
-
-from . import hello as hola
-
diff --git a/tests/testdata/python2/data/package/hello.py b/tests/testdata/python2/data/package/hello.py
deleted file mode 100644
index b154c844..00000000
--- a/tests/testdata/python2/data/package/hello.py
+++ /dev/null
@@ -1,2 +0,0 @@
-"""hello module"""
-
diff --git a/tests/testdata/python2/data/package/import_package_subpackage_module.py b/tests/testdata/python2/data/package/import_package_subpackage_module.py
deleted file mode 100644
index ad442c16..00000000
--- a/tests/testdata/python2/data/package/import_package_subpackage_module.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# pylint: disable-msg=I0011,C0301,W0611
-"""I found some of my scripts trigger off an AttributeError in pylint
-0.8.1 (with common 0.12.0 and astroid 0.13.1).
-
-Traceback (most recent call last):
- File "/usr/bin/pylint", line 4, in ?
- lint.Run(sys.argv[1:])
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__
- linter.check(args)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check
- self.check_file(filepath, modname, checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file
- astroid = self._check_file(filepath, modname, checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file
- self.check_astroid_module(astroid, checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module
- self.astroid_events(astroid, [checker for checker in checkers
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
- self.astroid_events(child, checkers, _reversed_checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
- self.astroid_events(child, checkers, _reversed_checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events
- checker.visit(astroid)
- File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit
- method(node)
- File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import
- self._check_module_attrs(node, module, name_parts[1:])
- File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs
- self.add_message('E0611', args=(name, module.name),
-AttributeError: Import instance has no attribute 'name'
-
-
-You can reproduce it by:
-(1) create package structure like the following:
-
-package/
- __init__.py
- subpackage/
- __init__.py
- module.py
-
-(2) in package/__init__.py write:
-
-import subpackage
-
-(3) run pylint with a script importing package.subpackage.module.
-"""
-__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $'
-import package.subpackage.module
diff --git a/tests/testdata/python2/data/package/subpackage/__init__.py b/tests/testdata/python2/data/package/subpackage/__init__.py
deleted file mode 100644
index dc4782e6..00000000
--- a/tests/testdata/python2/data/package/subpackage/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-"""package.subpackage"""
diff --git a/tests/testdata/python2/data/package/subpackage/module.py b/tests/testdata/python2/data/package/subpackage/module.py
deleted file mode 100644
index 4b7244ba..00000000
--- a/tests/testdata/python2/data/package/subpackage/module.py
+++ /dev/null
@@ -1 +0,0 @@
-"""package.subpackage.module"""
diff --git a/tests/testdata/python2/data/path_pkg_resources_1/package/__init__.py b/tests/testdata/python2/data/path_pkg_resources_1/package/__init__.py
deleted file mode 100644
index b0d64337..00000000
--- a/tests/testdata/python2/data/path_pkg_resources_1/package/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__import__('pkg_resources').declare_namespace(__name__) \ No newline at end of file
diff --git a/tests/testdata/python2/data/path_pkg_resources_1/package/foo.py b/tests/testdata/python2/data/path_pkg_resources_1/package/foo.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/path_pkg_resources_1/package/foo.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/path_pkg_resources_2/package/__init__.py b/tests/testdata/python2/data/path_pkg_resources_2/package/__init__.py
deleted file mode 100644
index b0d64337..00000000
--- a/tests/testdata/python2/data/path_pkg_resources_2/package/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__import__('pkg_resources').declare_namespace(__name__) \ No newline at end of file
diff --git a/tests/testdata/python2/data/path_pkg_resources_2/package/bar.py b/tests/testdata/python2/data/path_pkg_resources_2/package/bar.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/path_pkg_resources_2/package/bar.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/path_pkg_resources_3/package/__init__.py b/tests/testdata/python2/data/path_pkg_resources_3/package/__init__.py
deleted file mode 100644
index b0d64337..00000000
--- a/tests/testdata/python2/data/path_pkg_resources_3/package/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__import__('pkg_resources').declare_namespace(__name__) \ No newline at end of file
diff --git a/tests/testdata/python2/data/path_pkg_resources_3/package/baz.py b/tests/testdata/python2/data/path_pkg_resources_3/package/baz.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/path_pkg_resources_3/package/baz.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/path_pkgutil_1/package/__init__.py b/tests/testdata/python2/data/path_pkgutil_1/package/__init__.py
deleted file mode 100644
index 0bfb5a62..00000000
--- a/tests/testdata/python2/data/path_pkgutil_1/package/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__) \ No newline at end of file
diff --git a/tests/testdata/python2/data/path_pkgutil_1/package/foo.py b/tests/testdata/python2/data/path_pkgutil_1/package/foo.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/path_pkgutil_1/package/foo.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/path_pkgutil_2/package/__init__.py b/tests/testdata/python2/data/path_pkgutil_2/package/__init__.py
deleted file mode 100644
index 0bfb5a62..00000000
--- a/tests/testdata/python2/data/path_pkgutil_2/package/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__) \ No newline at end of file
diff --git a/tests/testdata/python2/data/path_pkgutil_2/package/bar.py b/tests/testdata/python2/data/path_pkgutil_2/package/bar.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/path_pkgutil_2/package/bar.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/path_pkgutil_3/package/__init__.py b/tests/testdata/python2/data/path_pkgutil_3/package/__init__.py
deleted file mode 100644
index 0bfb5a62..00000000
--- a/tests/testdata/python2/data/path_pkgutil_3/package/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__) \ No newline at end of file
diff --git a/tests/testdata/python2/data/path_pkgutil_3/package/baz.py b/tests/testdata/python2/data/path_pkgutil_3/package/baz.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/path_pkgutil_3/package/baz.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/recursion.py b/tests/testdata/python2/data/recursion.py
deleted file mode 100644
index a34dad32..00000000
--- a/tests/testdata/python2/data/recursion.py
+++ /dev/null
@@ -1,3 +0,0 @@
-""" For issue #25 """
-class Base(object):
- pass \ No newline at end of file
diff --git a/tests/testdata/python2/data/tmp__init__.py b/tests/testdata/python2/data/tmp__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/tmp__init__.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/unicode_package/__init__.py b/tests/testdata/python2/data/unicode_package/__init__.py
deleted file mode 100644
index 713e5591..00000000
--- a/tests/testdata/python2/data/unicode_package/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-x = "șțîâ" \ No newline at end of file
diff --git a/tests/testdata/python2/data/unicode_package/core/__init__.py b/tests/testdata/python2/data/unicode_package/core/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/tests/testdata/python2/data/unicode_package/core/__init__.py
+++ /dev/null
diff --git a/tests/testdata/python2/data/find_test/__init__.py b/tests/testdata/python3/data/metaclass_recursion/__init__.py
index e69de29b..e69de29b 100644
--- a/tests/testdata/python2/data/find_test/__init__.py
+++ b/tests/testdata/python3/data/metaclass_recursion/__init__.py
diff --git a/tests/testdata/python3/data/metaclass_recursion/monkeypatch.py b/tests/testdata/python3/data/metaclass_recursion/monkeypatch.py
new file mode 100644
index 00000000..757bb3f8
--- /dev/null
+++ b/tests/testdata/python3/data/metaclass_recursion/monkeypatch.py
@@ -0,0 +1,17 @@
+# https://github.com/PyCQA/astroid/issues/749
+# Not an actual module but allows us to reproduce the issue
+from tests.testdata.python3.data.metaclass_recursion import parent
+
+class MonkeyPatchClass(parent.OriginalClass):
+ _original_class = parent.OriginalClass
+
+ @classmethod
+ def patch(cls):
+ if parent.OriginalClass != MonkeyPatchClass:
+ cls._original_class = parent.OriginalClass
+ parent.OriginalClass = MonkeyPatchClass
+
+ @classmethod
+ def unpatch(cls):
+ if parent.OriginalClass == MonkeyPatchClass:
+ parent.OriginalClass = cls._original_class
diff --git a/tests/testdata/python3/data/metaclass_recursion/parent.py b/tests/testdata/python3/data/metaclass_recursion/parent.py
new file mode 100644
index 00000000..5cff73e0
--- /dev/null
+++ b/tests/testdata/python3/data/metaclass_recursion/parent.py
@@ -0,0 +1,3 @@
+# https://github.com/PyCQA/astroid/issues/749
+class OriginalClass:
+ pass
diff --git a/tests/unittest_brain.py b/tests/unittest_brain.py
index 1a082d12..0a833664 100644
--- a/tests/unittest_brain.py
+++ b/tests/unittest_brain.py
@@ -1,20 +1,28 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2013-2014 Google, Inc.
-# Copyright (c) 2014-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2015 raylu <lurayl@gmail.com>
# Copyright (c) 2015 Philip Lorenz <philip@bithub.de>
# Copyright (c) 2016 Florian Bruhin <me@the-compiler.org>
-# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
# Copyright (c) 2017-2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
-# Copyright (c) 2017 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
# Copyright (c) 2017 David Euresti <github@euresti.com>
# Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com>
+# Copyright (c) 2018 Tomas Gavenciak <gavento@ucw.cz>
+# Copyright (c) 2018 David Poirier <david-poirier-csn@users.noreply.github.com>
+# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
# Copyright (c) 2018 Ioana Tagirta <ioana.tagirta@gmail.com>
# Copyright (c) 2018 Ahmed Azzaoui <ahmed.azzaoui@engie.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 Tomas Novak <ext.Tomas.Novak@skoda-auto.cz>
+# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
+# Copyright (c) 2019 Grygorii Iermolenko <gyermolenko@gmail.com>
+# Copyright (c) 2019 Bryce Guinta <bryce.guinta@protonmail.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -323,6 +331,18 @@ class NamedTupleTest(unittest.TestCase):
self.assertIsInstance(inferred.bases[0], astroid.Name)
self.assertEqual(inferred.bases[0].name, "tuple")
+ def test_invalid_label_does_not_crash_inference(self):
+ code = """
+ import collections
+ a = collections.namedtuple( 'a', ['b c'] )
+ a
+ """
+ node = builder.extract_node(code)
+ inferred = next(node.infer())
+ assert isinstance(inferred, astroid.ClassDef)
+ assert "b" not in inferred.locals
+ assert "c" not in inferred.locals
+
class DefaultDictTest(unittest.TestCase):
def test_1(self):
@@ -622,6 +642,21 @@ class EnumBrainTest(unittest.TestCase):
test = next(enumeration.igetattr("test"))
self.assertEqual(test.value, 42)
+ def test_ignores_with_nodes_from_body_of_enum(self):
+ code = """
+ import enum
+
+ class Error(enum.Enum):
+ Foo = "foo"
+ Bar = "bar"
+ with "error" as err:
+ pass
+ """
+ node = builder.extract_node(code)
+ inferred = next(node.infer())
+ assert "err" in inferred.locals
+ assert len(inferred.locals["err"]) == 1
+
def test_enum_multiple_base_classes(self):
module = builder.parse(
"""
@@ -1633,10 +1668,13 @@ class TestLenBuiltinInference:
)
assert next(node.infer()).as_string() == "3"
- @pytest.mark.xfail(reason="Can't retrieve subclassed type value ")
def test_int_subclass_result(self):
- """I am unable to figure out the value of an
- object which subclasses int"""
+ """Check that a subclass of an int can still be inferred
+
+ This test does not properly infer the value passed to the
+ int subclass (5) but still returns a proper integer as we
+ fake the result of the `len()` call.
+ """
node = astroid.extract_node(
"""
class IntSubclass(int):
@@ -1648,7 +1686,7 @@ class TestLenBuiltinInference:
len(F())
"""
)
- assert next(node.infer()).as_string() == "5"
+ assert next(node.infer()).as_string() == "0"
@pytest.mark.xfail(reason="Can't use list special astroid fields")
def test_int_subclass_argument(self):
diff --git a/tests/unittest_brain_numpy_core_fromnumeric.py b/tests/unittest_brain_numpy_core_fromnumeric.py
index 16d73e2e..fd571f30 100644
--- a/tests/unittest_brain_numpy_core_fromnumeric.py
+++ b/tests/unittest_brain_numpy_core_fromnumeric.py
@@ -1,5 +1,6 @@
# -*- encoding=utf-8 -*-
-# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_brain_numpy_core_function_base.py b/tests/unittest_brain_numpy_core_function_base.py
index 06a940c8..109238a2 100644
--- a/tests/unittest_brain_numpy_core_function_base.py
+++ b/tests/unittest_brain_numpy_core_function_base.py
@@ -1,5 +1,6 @@
# -*- encoding=utf-8 -*-
-# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_brain_numpy_core_multiarray.py b/tests/unittest_brain_numpy_core_multiarray.py
index e02db6cc..9e945d21 100644
--- a/tests/unittest_brain_numpy_core_multiarray.py
+++ b/tests/unittest_brain_numpy_core_multiarray.py
@@ -1,5 +1,6 @@
# -*- encoding=utf-8 -*-
-# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_brain_numpy_core_numeric.py b/tests/unittest_brain_numpy_core_numeric.py
index 56b7d0d6..a39fb19e 100644
--- a/tests/unittest_brain_numpy_core_numeric.py
+++ b/tests/unittest_brain_numpy_core_numeric.py
@@ -1,5 +1,6 @@
# -*- encoding=utf-8 -*-
-# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_brain_numpy_core_numerictypes.py b/tests/unittest_brain_numpy_core_numerictypes.py
index 768a5570..db4fdd23 100644
--- a/tests/unittest_brain_numpy_core_numerictypes.py
+++ b/tests/unittest_brain_numpy_core_numerictypes.py
@@ -1,7 +1,8 @@
# -*- encoding=utf-8 -*-
-# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
-# Copyright (c) 2017 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2017-2020 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2017-2018 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -314,6 +315,34 @@ class NumpyBrainCoreNumericTypesTest(unittest.TestCase):
with self.subTest(attr=attr):
self.assertNotEqual(len(inferred.getattr(attr)), 0)
+ def test_datetime_astype_return(self):
+ """
+ Test that the return of astype method of the datetime object
+ is inferred as a ndarray.
+
+ PyCQA/pylint#3332
+ """
+ node = builder.extract_node(
+ """
+ import numpy as np
+ import datetime
+ test_array = np.datetime64(1, 'us')
+ test_array.astype(datetime.datetime)
+ """
+ )
+ licit_array_types = ".ndarray"
+ inferred_values = list(node.infer())
+ self.assertTrue(
+ len(inferred_values) == 1,
+ msg="Too much inferred value for {:s}".format("datetime64.astype"),
+ )
+ self.assertTrue(
+ inferred_values[-1].pytype() in licit_array_types,
+ msg="Illicit type for {:s} ({})".format(
+ "datetime64.astype", inferred_values[-1].pytype()
+ ),
+ )
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/unittest_brain_numpy_core_umath.py b/tests/unittest_brain_numpy_core_umath.py
index e6fb1c5e..3db3f149 100644
--- a/tests/unittest_brain_numpy_core_umath.py
+++ b/tests/unittest_brain_numpy_core_umath.py
@@ -1,5 +1,6 @@
# -*- encoding=utf-8 -*-
-# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_brain_numpy_ndarray.py b/tests/unittest_brain_numpy_ndarray.py
index d982f7f6..defce47d 100644
--- a/tests/unittest_brain_numpy_ndarray.py
+++ b/tests/unittest_brain_numpy_ndarray.py
@@ -1,7 +1,8 @@
# -*- encoding=utf-8 -*-
-# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
-# Copyright (c) 2017 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2017-2020 hippo91 <guillaume.peillex@gmail.com>
+# Copyright (c) 2017-2018 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -117,6 +118,18 @@ class NumpyBrainNdarrayTest(unittest.TestCase):
)
return node.infer()
+ def _inferred_ndarray_attribute(self, attr_name):
+ node = builder.extract_node(
+ """
+ import numpy as np
+ test_array = np.ndarray((2, 2))
+ test_array.{:s}
+ """.format(
+ attr_name
+ )
+ )
+ return node.infer()
+
def test_numpy_function_calls_inferred_as_ndarray(self):
"""
Test that some calls to numpy functions are inferred as numpy.ndarray
@@ -136,6 +149,25 @@ class NumpyBrainNdarrayTest(unittest.TestCase):
),
)
+ def test_numpy_ndarray_attribute_inferred_as_ndarray(self):
+ """
+ Test that some numpy ndarray attributes are inferred as numpy.ndarray
+ """
+ licit_array_types = ".ndarray"
+ for attr_ in ("real", "imag"):
+ with self.subTest(typ=attr_):
+ inferred_values = list(self._inferred_ndarray_attribute(attr_))
+ self.assertTrue(
+ len(inferred_values) == 1,
+ msg="Too much inferred value for {:s}".format(attr_),
+ )
+ self.assertTrue(
+ inferred_values[-1].pytype() in licit_array_types,
+ msg="Illicit type for {:s} ({})".format(
+ attr_, inferred_values[-1].pytype()
+ ),
+ )
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/unittest_brain_numpy_random_mtrand.py b/tests/unittest_brain_numpy_random_mtrand.py
index 4ca296f1..20a5d310 100644
--- a/tests/unittest_brain_numpy_random_mtrand.py
+++ b/tests/unittest_brain_numpy_random_mtrand.py
@@ -1,7 +1,6 @@
# -*- encoding=utf-8 -*-
-# Copyright (c) 2017-2018 hippo91 <guillaume.peillex@gmail.com>
-# Copyright (c) 2017 Claudiu Popa <pcmanticore@gmail.com>
-# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_builder.py b/tests/unittest_builder.py
index 9ea597c8..22e49e60 100644
--- a/tests/unittest_builder.py
+++ b/tests/unittest_builder.py
@@ -1,14 +1,17 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
-# Copyright (c) 2014-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2014-2019 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2014-2015 Google, Inc.
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
# Copyright (c) 2017 Bryce Guinta <bryce.paul.guinta@gmail.com>
# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
+# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
# Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_helpers.py b/tests/unittest_helpers.py
index 8ed07ede..ced5fc0a 100644
--- a/tests/unittest_helpers.py
+++ b/tests/unittest_helpers.py
@@ -1,5 +1,6 @@
-# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -192,21 +193,6 @@ class TestHelpers(unittest.TestCase):
self.assertFalse(helpers.is_subtype(cls_a, cls_b))
self.assertFalse(helpers.is_subtype(cls_a, cls_b))
- @test_utils.require_version(maxver="3.0")
- def test_is_subtype_supertype_old_style_classes(self):
- cls_a, cls_b = builder.extract_node(
- """
- class A: #@
- pass
- class B(A): #@
- pass
- """
- )
- self.assertFalse(helpers.is_subtype(cls_a, cls_b))
- self.assertFalse(helpers.is_subtype(cls_b, cls_a))
- self.assertFalse(helpers.is_supertype(cls_a, cls_b))
- self.assertFalse(helpers.is_supertype(cls_b, cls_a))
-
def test_is_subtype_supertype_mro_error(self):
cls_e, cls_f = builder.extract_node(
"""
diff --git a/tests/unittest_inference.py b/tests/unittest_inference.py
index b541eb28..b3df5f6c 100644
--- a/tests/unittest_inference.py
+++ b/tests/unittest_inference.py
@@ -2,7 +2,7 @@
# Copyright (c) 2006-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2007 Marien Zwart <marienz@gentoo.org>
# Copyright (c) 2013-2014 Google, Inc.
-# Copyright (c) 2014-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2015 Dmitry Pribysh <dmand@yandex.ru>
@@ -14,8 +14,14 @@
# Copyright (c) 2017 Calen Pennington <calen.pennington@gmail.com>
# Copyright (c) 2017 David Euresti <david@dropbox.com>
# Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com>
+# Copyright (c) 2018 Daniel Martin <daniel.martin@crowdstrike.com>
+# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
+# Copyright (c) 2019 Stanislav Levin <slev@altlinux.org>
+# Copyright (c) 2019 David Liu <david@cs.toronto.edu>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -24,6 +30,7 @@
"""
# pylint: disable=too-many-lines
import platform
+import textwrap
from functools import partial
import unittest
from unittest.mock import patch
@@ -499,18 +506,7 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
self.assertEqual(inferred.name, "set")
self.assertIn("remove", inferred._proxied.locals)
- @test_utils.require_version(maxver="3.0")
- def test_unicode_type(self):
- code = '''u = u""'''
- ast = parse(code, __name__)
- n = ast["u"]
- inferred = next(n.infer())
- self.assertIsInstance(inferred, nodes.Const)
- self.assertIsInstance(inferred, Instance)
- self.assertEqual(inferred.name, "unicode")
- self.assertIn("lower", inferred._proxied.locals)
-
- @unittest.expectedFailure
+ @pytest.mark.xfail(reason="Descriptors are not properly inferred as callable")
def test_descriptor_are_callable(self):
code = """
class A:
@@ -1701,7 +1697,9 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
pass
"""
)
- self.assertIn("object", [base.name for base in klass.ancestors()])
+ ancestors = [base.name for base in klass.ancestors()]
+ expected_subset = ["datetime", "date"]
+ self.assertEqual(expected_subset, ancestors[:2])
def test_stop_iteration_leak(self):
code = """
@@ -3256,7 +3254,7 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.name, "B")
- @unittest.expectedFailure
+ @pytest.mark.xfail(reason="String interpolation is incorrect for modulo formatting")
def test_string_interpolation(self):
ast_nodes = extract_node(
"""
@@ -3628,7 +3626,7 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
]
self.assertEqual(titles, ["Catch 22", "Ubik", "Grimus"])
- @unittest.expectedFailure
+ @pytest.mark.xfail(reason="Does not support function metaclasses")
def test_function_metaclasses(self):
# These are not supported right now, although
# they will be in the future.
@@ -3776,7 +3774,7 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
second = next(ast_nodes[1].infer())
self.assertIsInstance(second, Instance)
- @unittest.expectedFailure
+ @pytest.mark.xfail(reason="Metaclass arguments not inferred as classes")
def test_metaclass_arguments_are_classes_not_instances(self):
ast_node = extract_node(
"""
@@ -3859,19 +3857,6 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
inferred.getattr("teta")
inferred.getattr("a")
- @test_utils.require_version(maxver="3.0")
- def test_delayed_attributes_with_old_style_classes(self):
- ast_node = extract_node(
- """
- class A:
- __slots__ = ('a', )
- a = A()
- a.teta = 42
- a #@
- """
- )
- next(ast_node.infer()).getattr("teta")
-
def test_lambda_as_methods(self):
ast_node = extract_node(
"""
@@ -3906,7 +3891,7 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, 25)
- @unittest.expectedFailure
+ @pytest.mark.xfail(reason="Cannot reuse inner value due to inference context reuse")
def test_inner_value_redefined_by_subclass_with_mro(self):
# This might work, but it currently doesn't due to not being able
# to reuse inference contexts.
@@ -5169,10 +5154,25 @@ def test_builtin_inference_list_of_exceptions():
inferred = next(node.infer())
assert isinstance(inferred, nodes.Tuple)
assert len(inferred.elts) == 2
- assert isinstance(inferred.elts[0], nodes.ClassDef)
- assert inferred.elts[0].name == "ValueError"
- assert isinstance(inferred.elts[1], nodes.ClassDef)
- assert inferred.elts[1].name == "TypeError"
+ assert isinstance(inferred.elts[0], nodes.EvaluatedObject)
+ assert isinstance(inferred.elts[0].value, nodes.ClassDef)
+ assert inferred.elts[0].value.name == "ValueError"
+ assert isinstance(inferred.elts[1], nodes.EvaluatedObject)
+ assert isinstance(inferred.elts[1].value, nodes.ClassDef)
+ assert inferred.elts[1].value.name == "TypeError"
+
+ # Test that inference of evaluated objects returns what is expected
+ first_elem = next(inferred.elts[0].infer())
+ assert isinstance(first_elem, nodes.ClassDef)
+ assert first_elem.name == "ValueError"
+
+ second_elem = next(inferred.elts[1].infer())
+ assert isinstance(second_elem, nodes.ClassDef)
+ assert second_elem.name == "TypeError"
+
+ # Test that as_string() also works
+ as_string = inferred.as_string()
+ assert as_string.strip() == "(ValueError, TypeError)"
@test_utils.require_version(minver="3.6")
@@ -5478,6 +5478,28 @@ def test_property_inference():
assert isinstance(inferred, nodes.FunctionDef)
+def test_property_as_string():
+ code = """
+ class A:
+ @property
+ def test(self):
+ return 42
+
+ A.test #@
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ assert isinstance(inferred, objects.Property)
+ property_body = textwrap.dedent(
+ """
+ @property
+ def test(self):
+ return 42
+ """
+ )
+ assert inferred.as_string().strip() == property_body.strip()
+
+
def test_property_callable_inference():
code = """
class A:
@@ -5517,5 +5539,330 @@ def test_recursion_error_inferring_builtin_containers():
helpers.safe_infer(node.targets[0])
+def test_inferaugassign_picking_parent_instead_of_stmt():
+ code = """
+ from collections import namedtuple
+ SomeClass = namedtuple('SomeClass', ['name'])
+ items = [SomeClass(name='some name')]
+
+ some_str = ''
+ some_str += ', '.join(__(item) for item in items)
+ """
+ # item needs to be inferrd as `SomeClass` but it was inferred
+ # as a string because the entire `AugAssign` node was inferred
+ # as a string.
+ node = extract_node(code)
+ inferred = next(node.infer())
+ assert isinstance(inferred, Instance)
+ assert inferred.name == "SomeClass"
+
+
+def test_classmethod_from_builtins_inferred_as_bound():
+ code = """
+ import builtins
+
+ class Foo():
+ @classmethod
+ def bar1(cls, text):
+ pass
+
+ @builtins.classmethod
+ def bar2(cls, text):
+ pass
+
+ Foo.bar1 #@
+ Foo.bar2 #@
+ """
+ first_node, second_node = extract_node(code)
+ assert isinstance(next(first_node.infer()), BoundMethod)
+ assert isinstance(next(second_node.infer()), BoundMethod)
+
+
+def test_infer_dict_passes_context():
+ code = """
+ k = {}
+ (_ for k in __(dict(**k)))
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ assert isinstance(inferred, Instance)
+ assert inferred.qname() == "builtins.dict"
+
+
+@pytest.mark.parametrize(
+ "code,obj,obj_type",
+ [
+ (
+ """
+ def klassmethod1(method):
+ @classmethod
+ def inner(cls):
+ return method(cls)
+ return inner
+
+ class X(object):
+ @klassmethod1
+ def x(cls):
+ return 'X'
+ X.x
+ """,
+ BoundMethod,
+ "classmethod",
+ ),
+ (
+ """
+ def staticmethod1(method):
+ @staticmethod
+ def inner(cls):
+ return method(cls)
+ return inner
+
+ class X(object):
+ @staticmethod1
+ def x(cls):
+ return 'X'
+ X.x
+ """,
+ nodes.FunctionDef,
+ "staticmethod",
+ ),
+ (
+ """
+ def klassmethod1(method):
+ def inner(cls):
+ return method(cls)
+ return classmethod(inner)
+
+ class X(object):
+ @klassmethod1
+ def x(cls):
+ return 'X'
+ X.x
+ """,
+ BoundMethod,
+ "classmethod",
+ ),
+ (
+ """
+ def staticmethod1(method):
+ def inner(cls):
+ return method(cls)
+ return staticmethod(inner)
+
+ class X(object):
+ @staticmethod1
+ def x(cls):
+ return 'X'
+ X.x
+ """,
+ nodes.FunctionDef,
+ "staticmethod",
+ ),
+ ],
+)
+def test_custom_decorators_for_classmethod_and_staticmethods(code, obj, obj_type):
+ node = extract_node(code)
+ inferred = next(node.infer())
+ assert isinstance(inferred, obj)
+ assert inferred.type == obj_type
+
+
+@pytest.mark.skipif(sys.version_info < (3, 8), reason="Needs dataclasses available")
+def test_dataclasses_subscript_inference_recursion_error():
+ code = """
+ from dataclasses import dataclass, replace
+
+ @dataclass
+ class ProxyConfig:
+ auth: str = "/auth"
+
+
+ a = ProxyConfig("")
+ test_dict = {"proxy" : {"auth" : "", "bla" : "f"}}
+
+ foo = test_dict['proxy']
+ replace(a, **test_dict['proxy']) # This fails
+ """
+ node = extract_node(code)
+ # Reproduces only with safe_infer()
+ assert helpers.safe_infer(node) is None
+
+
+def test_self_reference_infer_does_not_trigger_recursion_error():
+ # Prevents https://github.com/PyCQA/pylint/issues/1285
+ code = """
+ def func(elems):
+ return elems
+
+ class BaseModel(object):
+
+ def __init__(self, *args, **kwargs):
+ self._reference = func(*self._reference.split('.'))
+ BaseModel()._reference
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ assert inferred is util.Uninferable
+
+
+def test_inferring_properties_multiple_time_does_not_mutate_locals_multiple_times():
+ code = """
+ class A:
+ @property
+ def a(self):
+ return 42
+
+ A()
+ """
+ node = extract_node(code)
+ # Infer the class
+ cls = next(node.infer())
+ prop, = cls.getattr("a")
+
+ # Try to infer the property function *multiple* times. `A.locals` should be modified only once
+ for _ in range(3):
+ prop.inferred()
+ a_locals = cls.locals["a"]
+ # [FunctionDef, Property]
+ assert len(a_locals) == 2
+
+
+def test_getattr_fails_on_empty_values():
+ code = """
+ import collections
+ collections
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ with pytest.raises(exceptions.InferenceError):
+ next(inferred.igetattr(""))
+
+ with pytest.raises(exceptions.AttributeInferenceError):
+ inferred.getattr("")
+
+
+def test_infer_first_argument_of_static_method_in_metaclass():
+ code = """
+ class My(type):
+ @staticmethod
+ def test(args):
+ args #@
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ assert inferred is util.Uninferable
+
+
+def test_recursion_error_metaclass_monkeypatching():
+ module = resources.build_file(
+ "data/metaclass_recursion/monkeypatch.py", "data.metaclass_recursion"
+ )
+ cls = next(module.igetattr("MonkeyPatchClass"))
+ assert isinstance(cls, nodes.ClassDef)
+ assert cls.declared_metaclass() is None
+
+
+@pytest.mark.xfail(reason="Cannot fully infer all the base classes properly.")
+def test_recursion_error_self_reference_type_call():
+ # Fix for https://github.com/PyCQA/astroid/issues/199
+ code = """
+ class A(object):
+ pass
+ class SomeClass(object):
+ route_class = A
+ def __init__(self):
+ self.route_class = type('B', (self.route_class, ), {})
+ self.route_class() #@
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ assert isinstance(inferred, Instance)
+ assert inferred.name == "B"
+ # TODO: Cannot infer [B, A, object] but at least the recursion error is gone.
+ assert [cls.name for cls in inferred.mro()] == ["B", "A", "object"]
+
+
+def test_allow_retrieving_instance_attrs_and_special_attrs_for_functions():
+ code = """
+ class A:
+ def test(self):
+ "a"
+ # Add `__doc__` to `FunctionDef.instance_attrs` via an `AugAssign`
+ test.__doc__ += 'b'
+ test #@
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ attrs = inferred.getattr("__doc__")
+ # One from the `AugAssign`, one from the special attributes
+ assert len(attrs) == 2
+
+
+def test_implicit_parameters_bound_method():
+ code = """
+ class A(type):
+ @classmethod
+ def test(cls, first): return first
+ def __new__(cls, name, bases, dictionary):
+ return super().__new__(cls, name, bases, dictionary)
+
+ A.test #@
+ A.__new__ #@
+ """
+ test, dunder_new = extract_node(code)
+ test = next(test.infer())
+ assert isinstance(test, BoundMethod)
+ assert test.implicit_parameters() == 1
+
+ dunder_new = next(dunder_new.infer())
+ assert isinstance(dunder_new, BoundMethod)
+ assert dunder_new.implicit_parameters() == 0
+
+
+def test_super_inference_of_abstract_property():
+ code = """
+ from abc import abstractmethod
+
+ class A:
+ @property
+ def test(self):
+ return "super"
+
+ class C:
+ @property
+ @abstractmethod
+ def test(self):
+ "abstract method"
+
+ class B(A, C):
+
+ @property
+ def test(self):
+ super() #@
+
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ test = inferred.getattr("test")
+ assert len(test) == 2
+
+
+def test_infer_generated_setter():
+ code = """
+ class A:
+ @property
+ def test(self):
+ pass
+ A.test.setter
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ assert isinstance(inferred, nodes.FunctionDef)
+ assert isinstance(inferred.args, nodes.Arguments)
+ # This line used to crash because property generated functions
+ # did not have args properly set
+ assert list(inferred.nodes_of_class(nodes.Const)) == []
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/unittest_lookup.py b/tests/unittest_lookup.py
index 58effd53..84fd5433 100644
--- a/tests/unittest_lookup.py
+++ b/tests/unittest_lookup.py
@@ -1,8 +1,10 @@
# Copyright (c) 2007-2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2010 Daniel Harding <dharding@gmail.com>
-# Copyright (c) 2014-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2014-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2014 Google, Inc.
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_manager.py b/tests/unittest_manager.py
index b56a0580..d7878b59 100644
--- a/tests/unittest_manager.py
+++ b/tests/unittest_manager.py
@@ -1,12 +1,17 @@
+# -*- coding: utf-8 -*-
# Copyright (c) 2006, 2009-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2013 AndroWiiid <androwiiid@gmail.com>
-# Copyright (c) 2014-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2014-2019 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2014 Google, Inc.
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2017 Chris Philip <chrisp533@gmail.com>
# Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com>
# Copyright (c) 2017 ioanatia <ioanatia@users.noreply.github.com>
+# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
+# Copyright (c) 2020 Anubhav <35621759+anubh-v@users.noreply.github.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -67,6 +72,17 @@ class AstroidManagerTest(
exceptions.AstroidBuildingError, self.manager.ast_from_file, "unhandledName"
)
+ def test_ast_from_string(self):
+ filepath = unittest.__file__
+ dirname = os.path.dirname(filepath)
+ modname = os.path.basename(dirname)
+ with open(filepath, "r") as file:
+ data = file.read()
+ ast = self.manager.ast_from_string(data, modname, filepath)
+ self.assertEqual(ast.name, "unittest")
+ self.assertEqual(ast.file, filepath)
+ self.assertIn("unittest", self.manager.astroid_cache)
+
def test_do_not_expose_main(self):
obj = self.manager.ast_from_module_name("__main__")
self.assertEqual(obj.name, "__main__")
diff --git a/tests/unittest_modutils.py b/tests/unittest_modutils.py
index 1747dc22..b5c41bf0 100644
--- a/tests/unittest_modutils.py
+++ b/tests/unittest_modutils.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2014-2016 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2014-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2014 Google, Inc.
# Copyright (c) 2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
@@ -7,6 +7,9 @@
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2018 Mario Corchero <mcorcherojim@bloomberg.net>
# Copyright (c) 2018 Mario Corchero <mariocj89@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
+# Copyright (c) 2019 markmcclain <markmcclain@users.noreply.github.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -127,14 +130,6 @@ class ModPathFromFileTest(unittest.TestCase):
["xml", "etree", "ElementTree"],
)
- def test_knownValues_modpath_from_file_2(self):
- self.assertEqual(
- modutils.modpath_from_file(
- "unittest_modutils.py", {os.getcwd(): "arbitrary.pkg"}
- ),
- ["arbitrary", "pkg", "unittest_modutils"],
- )
-
def test_raise_modpath_from_file_Exception(self):
self.assertRaises(Exception, modutils.modpath_from_file, "/turlututu")
diff --git a/tests/unittest_nodes.py b/tests/unittest_nodes.py
index 5fbef628..5b6a39e3 100644
--- a/tests/unittest_nodes.py
+++ b/tests/unittest_nodes.py
@@ -1,6 +1,6 @@
# Copyright (c) 2006-2007, 2009-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
-# Copyright (c) 2013-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2013-2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2014 Google, Inc.
# Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
@@ -8,9 +8,13 @@
# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
# Copyright (c) 2017 rr- <rr-@sakuya.pl>
# Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com>
+# Copyright (c) 2018 Serhiy Storchaka <storchaka@gmail.com>
# Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
+# Copyright (c) 2019-2020 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 Alex Hall <alex.mojaki@gmail.com>
+# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -22,6 +26,7 @@ import sys
import textwrap
import unittest
import copy
+import platform
import pytest
import six
@@ -147,21 +152,20 @@ def function(var):
ast = abuilder.string_build(code)
self.assertEqual(ast.as_string(), code)
- @test_utils.require_version("3.0")
- @unittest.expectedFailure
def test_3k_annotations_and_metaclass(self):
- code_annotations = textwrap.dedent(
- '''
- def function(var:int):
+ code = '''
+ def function(var: int):
nonlocal counter
class Language(metaclass=Natural):
"""natural language"""
'''
- )
+ code_annotations = textwrap.dedent(code)
+ # pylint: disable=line-too-long
+ expected = 'def function(var: int):\n nonlocal counter\n\n\nclass Language(metaclass=Natural):\n """natural language"""'
ast = abuilder.string_build(code_annotations)
- self.assertEqual(ast.as_string(), code_annotations)
+ self.assertEqual(ast.as_string().strip(), expected)
def test_ellipsis(self):
ast = abuilder.string_build("a[...]").body[0]
@@ -254,7 +258,12 @@ class D(metaclass=abc.ABCMeta):
ast = abuilder.string_build(code)
self.assertEqual(ast.as_string().strip(), code.strip())
- @pytest.mark.skipif(sys.version_info[:2] < (3, 6), reason="needs f-string support")
+ # This test is disabled on PyPy because we cannot get a proper release on TravisCI that has
+ # proper support for f-strings (we need 7.2 at least)
+ @pytest.mark.skipif(
+ sys.version_info[:2] < (3, 6) or platform.python_implementation() == "PyPy",
+ reason="Needs f-string support.",
+ )
def test_f_strings(self):
code = r'''
a = f"{'a'}"
@@ -1131,6 +1140,47 @@ def test_type_comments_arguments():
assert actual_arg.as_string() == expected_arg
+@pytest.mark.skipif(
+ not PY38, reason="needs to be able to parse positional only arguments"
+)
+def test_type_comments_posonly_arguments():
+ module = builder.parse(
+ """
+ def f_arg_comment(
+ a, # type: int
+ b, # type: int
+ /,
+ c, # type: Optional[int]
+ d, # type: Optional[int]
+ *,
+ e, # type: float
+ f, # type: float
+ ):
+ # type: (...) -> None
+ pass
+ """
+ )
+ expected_annotations = [
+ [["int", "int"], ["Optional[int]", "Optional[int]"], ["float", "float"]]
+ ]
+ for node, expected_types in zip(module.body, expected_annotations):
+ assert len(node.type_comment_args) == 1
+ if PY38:
+ assert isinstance(node.type_comment_args[0], astroid.Const)
+ assert node.type_comment_args[0].value == Ellipsis
+ else:
+ assert isinstance(node.type_comment_args[0], astroid.Ellipsis)
+ type_comments = [
+ node.args.type_comment_posonlyargs,
+ node.args.type_comment_args,
+ node.args.type_comment_kwonlyargs,
+ ]
+ for expected_args, actual_args in zip(expected_types, type_comments):
+ assert len(expected_args) == len(actual_args)
+ for expected_arg, actual_arg in zip(expected_args, actual_args):
+ assert actual_arg.as_string() == expected_arg
+
+
def test_is_generator_for_yield_assignments():
node = astroid.extract_node(
"""
@@ -1285,5 +1335,30 @@ def test_const_itered():
assert [elem.value for elem in itered] == list("string")
+def test_is_generator_for_yield_in_while():
+ code = """
+ def paused_iter(iterable):
+ while True:
+ # Continue to yield the same item until `next(i)` or `i.send(False)`
+ while (yield value):
+ pass
+ """
+ node = astroid.extract_node(code)
+ assert bool(node.is_generator())
+
+
+def test_is_generator_for_yield_in_if():
+ code = """
+ import asyncio
+
+ def paused_iter(iterable):
+ if (yield from asyncio.sleep(0.01)):
+ pass
+ return
+ """
+ node = astroid.extract_node(code)
+ assert bool(node.is_generator())
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/unittest_object_model.py b/tests/unittest_object_model.py
index ac42485a..5301a992 100644
--- a/tests/unittest_object_model.py
+++ b/tests/unittest_object_model.py
@@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2016-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2016-2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -58,7 +59,7 @@ class InstanceModelTest(unittest.TestCase):
self.assertIsInstance(attr, astroid.Const)
self.assertEqual(attr.value, 42)
- @unittest.expectedFailure
+ @pytest.mark.xfail(reason="Instance lookup cannot override object model")
def test_instance_local_attributes_overrides_object_model(self):
# The instance lookup needs to be changed in order for this to work.
ast_node = builder.extract_node(
@@ -144,30 +145,6 @@ class ClassModelTest(unittest.TestCase):
self.assertIsInstance(inferred, astroid.Const)
self.assertEqual(inferred.value, "first")
- @test_utils.require_version(maxver="3.0")
- def test__mro__old_style(self):
- ast_node = builder.extract_node(
- """
- class A:
- pass
- A.__mro__
- """
- )
- with self.assertRaises(exceptions.InferenceError):
- next(ast_node.infer())
-
- @test_utils.require_version(maxver="3.0")
- def test__subclasses__old_style(self):
- ast_node = builder.extract_node(
- """
- class A:
- pass
- A.__subclasses__
- """
- )
- with self.assertRaises(exceptions.InferenceError):
- next(ast_node.infer())
-
def test_class_model_correct_mro_subclasses_proxied(self):
ast_nodes = builder.extract_node(
"""
@@ -354,7 +331,7 @@ class FunctionModelTest(unittest.TestCase):
inferred = next(node.infer())
assert inferred is util.Uninferable
- @unittest.expectedFailure
+ @pytest.mark.xfail(reason="Descriptors cannot infer what self is")
def test_descriptor_not_inferrring_self(self):
# We can't infer __get__(X, Y)() when the bounded function
# uses self, because of the tree's parent not being propagating good enough.
@@ -506,37 +483,6 @@ class FunctionModelTest(unittest.TestCase):
self.assertIsInstance(kwdefaults, astroid.Dict)
# self.assertEqual(kwdefaults.getitem('f').value, 'lala')
- @test_utils.require_version(maxver="3.0")
- def test_function_model_for_python2(self):
- ast_nodes = builder.extract_node(
- """
- def test(a=1):
- "a"
-
- test.func_name #@
- test.func_doc #@
- test.func_dict #@
- test.func_globals #@
- test.func_defaults #@
- test.func_code #@
- test.func_closure #@
- """
- )
- name = next(ast_nodes[0].infer())
- self.assertIsInstance(name, astroid.Const)
- self.assertEqual(name.value, "test")
- doc = next(ast_nodes[1].infer())
- self.assertIsInstance(doc, astroid.Const)
- self.assertEqual(doc.value, "a")
- pydict = next(ast_nodes[2].infer())
- self.assertIsInstance(pydict, astroid.Dict)
- pyglobals = next(ast_nodes[3].infer())
- self.assertIsInstance(pyglobals, astroid.Dict)
- defaults = next(ast_nodes[4].infer())
- self.assertIsInstance(defaults, astroid.Tuple)
- for node in ast_nodes[5:]:
- self.assertIs(next(node.infer()), astroid.Uninferable)
-
@test_utils.require_version(minver="3.8")
def test_annotation_positional_only(self):
ast_node = builder.extract_node(
@@ -640,6 +586,17 @@ class ExceptionModelTest(unittest.TestCase):
assert isinstance(inferred, astroid.Const)
assert inferred.value == value
+ def test_unicodedecodeerror(self):
+ code = """
+ try:
+ raise UnicodeDecodeError("utf-8", "blob", 0, 1, "reason")
+ except UnicodeDecodeError as error:
+ error.object[:1] #@
+ """
+ node = builder.extract_node(code)
+ inferred = next(node.infer())
+ assert isinstance(inferred, astroid.Const)
+
def test_import_error(self):
ast_nodes = builder.extract_node(
"""
diff --git a/tests/unittest_objects.py b/tests/unittest_objects.py
index 8c56c9fd..a9de6eb2 100644
--- a/tests/unittest_objects.py
+++ b/tests/unittest_objects.py
@@ -1,6 +1,7 @@
-# Copyright (c) 2015-2016 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2015-2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -96,28 +97,6 @@ class SuperTests(unittest.TestCase):
self.assertIsInstance(second, bases.Instance)
self.assertEqual(second.qname(), "%s.super" % bases.BUILTINS)
- @test_utils.require_version(maxver="3.0")
- def test_super_on_old_style_class(self):
- # super doesn't work on old style class, but leave
- # that as an error for pylint. We'll infer Super objects,
- # but every call will result in a failure at some point.
- node = builder.extract_node(
- """
- class OldStyle:
- def __init__(self):
- super(OldStyle, self) #@
- """
- )
- old = next(node.infer())
- self.assertIsInstance(old, objects.Super)
- self.assertIsInstance(old.mro_pointer, nodes.ClassDef)
- self.assertEqual(old.mro_pointer.name, "OldStyle")
- with self.assertRaises(exceptions.SuperError) as cm:
- old.super_mro()
- self.assertEqual(
- str(cm.exception), "Unable to call super on old-style classes."
- )
-
@test_utils.require_version(minver="3.0")
def test_no_arguments_super(self):
ast_nodes = builder.extract_node(
diff --git a/tests/unittest_protocols.py b/tests/unittest_protocols.py
index 1b70a423..babff51e 100644
--- a/tests/unittest_protocols.py
+++ b/tests/unittest_protocols.py
@@ -1,9 +1,10 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2015-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2015-2019 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_python3.py b/tests/unittest_python3.py
index bc450227..b1759f03 100644
--- a/tests/unittest_python3.py
+++ b/tests/unittest_python3.py
@@ -5,8 +5,9 @@
# Copyright (c) 2014 Google, Inc.
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2016 Jared Garst <jgarst@users.noreply.github.com>
+# Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com>
# Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com>
-# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_raw_building.py b/tests/unittest_raw_building.py
index db32e7da..f782cdb2 100644
--- a/tests/unittest_raw_building.py
+++ b/tests/unittest_raw_building.py
@@ -1,9 +1,10 @@
# Copyright (c) 2013 AndroWiiid <androwiiid@gmail.com>
-# Copyright (c) 2014-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2014-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2014 Google, Inc.
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_regrtest.py b/tests/unittest_regrtest.py
index 91fa8f16..79a86cb2 100644
--- a/tests/unittest_regrtest.py
+++ b/tests/unittest_regrtest.py
@@ -1,12 +1,13 @@
# Copyright (c) 2006-2008, 2010-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2007 Marien Zwart <marienz@gentoo.org>
# Copyright (c) 2013-2014 Google, Inc.
-# Copyright (c) 2014-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2014-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -306,25 +307,41 @@ def test():
)
next(node.infer())
- @require_version(maxver="3.0")
- def test_reassignment_in_except_handler(self):
- node = extract_node(
- """
- import exceptions
- try:
- {}["a"]
- except KeyError, exceptions.IndexError:
- pass
-
- IndexError #@
+ def test_regression_inference_of_self_in_lambda(self):
+ code = """
+ class A:
+ @b(lambda self: __(self))
+ def d(self):
+ pass
"""
- )
- self.assertEqual(len(node.inferred()), 1)
+ node = extract_node(code)
+ inferred = next(node.infer())
+ assert isinstance(inferred, Instance)
+ assert inferred.qname() == ".A"
class Whatever:
a = property(lambda x: x, lambda x: x)
+def test_ancestor_looking_up_redefined_function():
+ code = """
+ class Foo:
+ def _format(self):
+ pass
+
+ def format(self):
+ self.format = self._format
+ self.format()
+ Foo
+ """
+ node = extract_node(code)
+ inferred = next(node.infer())
+ ancestor = next(inferred.ancestors())
+ _, found = ancestor.lookup("format")
+ assert len(found) == 1
+ assert isinstance(found[0], nodes.FunctionDef)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/unittest_scoped_nodes.py b/tests/unittest_scoped_nodes.py
index d70b7351..c4597fa6 100644
--- a/tests/unittest_scoped_nodes.py
+++ b/tests/unittest_scoped_nodes.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2011, 2013-2015 Google, Inc.
-# Copyright (c) 2013-2018 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2013-2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2013 Phil Schaf <flying-sheep@web.de>
# Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
@@ -9,11 +9,16 @@
# Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
# Copyright (c) 2015 Philip Lorenz <philip@bithub.de>
# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
+# Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com>
# Copyright (c) 2017-2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
-# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
# Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com>
+# Copyright (c) 2018-2019 Ville Skyttä <ville.skytta@iki.fi>
# Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
+# Copyright (c) 2019 Peter de Blanc <peter@standard.ai>
+# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -1005,19 +1010,6 @@ class ClassNodeTest(ModuleLoader, unittest.TestCase):
self.assertEqual(astroid["g2"].fromlineno, 9)
self.assertEqual(astroid["g2"].tolineno, 10)
- @test_utils.require_version(maxver="3.0")
- def test_simple_metaclass(self):
- astroid = builder.parse(
- """
- class Test(object):
- __metaclass__ = type
- """
- )
- klass = astroid["Test"]
- metaclass = klass.metaclass()
- self.assertIsInstance(metaclass, scoped_nodes.ClassDef)
- self.assertEqual(metaclass.name, "type")
-
def test_metaclass_error(self):
astroid = builder.parse(
"""
@@ -1028,21 +1020,6 @@ class ClassNodeTest(ModuleLoader, unittest.TestCase):
klass = astroid["Test"]
self.assertFalse(klass.metaclass())
- @test_utils.require_version(maxver="3.0")
- def test_metaclass_imported(self):
- astroid = builder.parse(
- """
- from abc import ABCMeta
- class Test(object):
- __metaclass__ = ABCMeta
- """
- )
- klass = astroid["Test"]
-
- metaclass = klass.metaclass()
- self.assertIsInstance(metaclass, scoped_nodes.ClassDef)
- self.assertEqual(metaclass.name, "ABCMeta")
-
def test_metaclass_yes_leak(self):
astroid = builder.parse(
"""
@@ -1056,100 +1033,6 @@ class ClassNodeTest(ModuleLoader, unittest.TestCase):
klass = astroid["Meta"]
self.assertIsNone(klass.metaclass())
- @test_utils.require_version(maxver="3.0")
- def test_newstyle_and_metaclass_good(self):
- astroid = builder.parse(
- """
- from abc import ABCMeta
- class Test:
- __metaclass__ = ABCMeta
- """
- )
- klass = astroid["Test"]
- self.assertTrue(klass.newstyle)
- self.assertEqual(klass.metaclass().name, "ABCMeta")
- astroid = builder.parse(
- """
- from abc import ABCMeta
- __metaclass__ = ABCMeta
- class Test:
- pass
- """
- )
- klass = astroid["Test"]
- self.assertTrue(klass.newstyle)
- self.assertEqual(klass.metaclass().name, "ABCMeta")
-
- @test_utils.require_version(maxver="3.0")
- def test_nested_metaclass(self):
- astroid = builder.parse(
- """
- from abc import ABCMeta
- class A(object):
- __metaclass__ = ABCMeta
- class B: pass
-
- __metaclass__ = ABCMeta
- class C:
- __metaclass__ = type
- class D: pass
- """
- )
- a = astroid["A"]
- b = a.locals["B"][0]
- c = astroid["C"]
- d = c.locals["D"][0]
- self.assertEqual(a.metaclass().name, "ABCMeta")
- self.assertFalse(b.newstyle)
- self.assertIsNone(b.metaclass())
- self.assertEqual(c.metaclass().name, "type")
- self.assertEqual(d.metaclass().name, "ABCMeta")
-
- @test_utils.require_version(maxver="3.0")
- def test_parent_metaclass(self):
- astroid = builder.parse(
- """
- from abc import ABCMeta
- class Test:
- __metaclass__ = ABCMeta
- class SubTest(Test): pass
- """
- )
- klass = astroid["SubTest"]
- self.assertTrue(klass.newstyle)
- metaclass = klass.metaclass()
- self.assertIsInstance(metaclass, scoped_nodes.ClassDef)
- self.assertEqual(metaclass.name, "ABCMeta")
-
- @test_utils.require_version(maxver="3.0")
- def test_metaclass_ancestors(self):
- astroid = builder.parse(
- """
- from abc import ABCMeta
-
- class FirstMeta(object):
- __metaclass__ = ABCMeta
-
- class SecondMeta(object):
- __metaclass__ = type
-
- class Simple(object):
- pass
-
- class FirstImpl(FirstMeta): pass
- class SecondImpl(FirstImpl): pass
- class ThirdImpl(Simple, SecondMeta):
- pass
- """
- )
- classes = {"ABCMeta": ("FirstImpl", "SecondImpl"), "type": ("ThirdImpl",)}
- for metaclass, names in classes.items():
- for name in names:
- impl = astroid[name]
- meta = impl.metaclass()
- self.assertIsInstance(meta, nodes.ClassDef)
- self.assertEqual(meta.name, metaclass)
-
def test_metaclass_type(self):
klass = builder.extract_node(
"""
@@ -1314,33 +1197,6 @@ class ClassNodeTest(ModuleLoader, unittest.TestCase):
else:
self.assertEqual(list(expected_value), [node.value for node in slots])
- @test_utils.require_version(maxver="3.0")
- def test_slots_py2(self):
- module = builder.parse(
- """
- class UnicodeSlots(object):
- __slots__ = (u"a", u"b", "c")
- """
- )
- slots = module["UnicodeSlots"].slots()
- self.assertEqual(len(slots), 3)
- self.assertEqual(slots[0].value, "a")
- self.assertEqual(slots[1].value, "b")
- self.assertEqual(slots[2].value, "c")
-
- @test_utils.require_version(maxver="3.0")
- def test_slots_py2_not_implemented(self):
- module = builder.parse(
- """
- class OldStyle:
- __slots__ = ("a", "b")
- """
- )
- msg = "The concept of slots is undefined for old-style classes."
- with self.assertRaises(NotImplementedError) as cm:
- module["OldStyle"].slots()
- self.assertEqual(str(cm.exception), msg)
-
def test_slots_for_dict_keys(self):
module = builder.parse(
"""
@@ -1397,73 +1253,23 @@ class ClassNodeTest(ModuleLoader, unittest.TestCase):
cls = module["B"]
self.assertIsNone(cls.slots())
- def assertEqualMro(self, klass, expected_mro):
- self.assertEqual([member.name for member in klass.mro()], expected_mro)
+ def test_slots_added_dynamically_still_inferred(self):
+ code = """
+ class NodeBase(object):
+ __slots__ = "a", "b"
- @test_utils.require_version(maxver="3.0")
- def test_no_mro_for_old_style(self):
- node = builder.extract_node(
- """
- class Old: pass"""
- )
- with self.assertRaises(NotImplementedError) as cm:
- node.mro()
- self.assertEqual(
- str(cm.exception), "Could not obtain mro for " "old-style classes."
- )
+ if Options.isFullCompat():
+ __slots__ += ("c",)
- @test_utils.require_version(maxver="3.0")
- def test_mro_for_classes_with_old_style_in_mro(self):
- node = builder.extract_node(
- """
- class Factory:
- pass
- class ClientFactory(Factory):
- pass
- class ReconnectingClientFactory(ClientFactory):
- pass
- class WebSocketAdapterFactory(object):
- pass
- class WebSocketClientFactory(WebSocketAdapterFactory, ClientFactory):
- pass
- class WampWebSocketClientFactory(WebSocketClientFactory):
- pass
- class RetryFactory(WampWebSocketClientFactory, ReconnectingClientFactory):
- pas
"""
- )
- self.assertEqualMro(
- node,
- [
- "RetryFactory",
- "WampWebSocketClientFactory",
- "WebSocketClientFactory",
- "WebSocketAdapterFactory",
- "object",
- "ReconnectingClientFactory",
- "ClientFactory",
- "Factory",
- ],
- )
+ node = builder.extract_node(code)
+ inferred = next(node.infer())
+ slots = inferred.slots()
+ assert len(slots) == 3, slots
+ assert [slot.value for slot in slots] == ["a", "b", "c"]
- @test_utils.require_version(maxver="3.0")
- def test_combined_newstyle_oldstyle_in_mro(self):
- node = builder.extract_node(
- """
- class Old:
- pass
- class New(object):
- pass
- class New1(object):
- pass
- class New2(New, New1):
- pass
- class NewOld(New2, Old): #@
- pass
- """
- )
- self.assertEqualMro(node, ["NewOld", "New2", "New", "New1", "object", "Old"])
- self.assertTrue(node.newstyle)
+ def assertEqualMro(self, klass, expected_mro):
+ self.assertEqual([member.name for member in klass.mro()], expected_mro)
def test_with_metaclass_mro(self):
astroid = builder.parse(
@@ -1741,15 +1547,6 @@ class ClassNodeTest(ModuleLoader, unittest.TestCase):
static = next(acls.igetattr("static"))
self.assertIsInstance(static, scoped_nodes.FunctionDef)
- @test_utils.require_version(maxver="3.0")
- def test_implicit_metaclass_is_none(self):
- cls = builder.extract_node(
- """
- class A: pass
- """
- )
- self.assertIsNone(cls.implicit_metaclass())
-
def test_local_attr_invalid_mro(self):
cls = builder.extract_node(
"""
@@ -2021,6 +1818,12 @@ def test_metaclass_cannot_infer_call_yields_an_instance():
pass
"""
),
+ textwrap.dedent(
+ """
+ def __init__(self: int, other: float, /, **kw):
+ pass
+ """
+ ),
],
)
@test_utils.require_version("3.8")
diff --git a/tests/unittest_transforms.py b/tests/unittest_transforms.py
index 5df7ffad..922f10f9 100644
--- a/tests/unittest_transforms.py
+++ b/tests/unittest_transforms.py
@@ -1,7 +1,8 @@
-# Copyright (c) 2015-2017 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2015-2018 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
diff --git a/tests/unittest_utils.py b/tests/unittest_utils.py
index 3ae3d6b7..428026b1 100644
--- a/tests/unittest_utils.py
+++ b/tests/unittest_utils.py
@@ -1,8 +1,9 @@
# Copyright (c) 2008-2010, 2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
# Copyright (c) 2014 Google, Inc.
-# Copyright (c) 2015-2016 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2016 Dave Baum <dbaum@google.com>
+# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER