Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Copy ClassVar upstream#280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
gvanrossum merged 13 commits intopython:masterfromilevkivskyi:copy-classvar
Sep 10, 2016
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
13 commits
Select commitHold shift + click to select a range
d20c39e
Copy typing upstream (including ClassVar for Python2)
ilevkivskyiSep 9, 2016
5d19448
update docstring for Python2
ilevkivskyiSep 9, 2016
69ff019
Make Python3 tests backward compatible
ilevkivskyiSep 9, 2016
66921dc
Fixed metaclass for Python2
ilevkivskyiSep 9, 2016
5a706c0
Fixed ChainMap also in tpying for 3.2
ilevkivskyiSep 9, 2016
69a4502
ClassVar must be defined before Any in Python2
ilevkivskyiSep 9, 2016
0b9092d
Attempt at prohibiting subclasses of ClassVar in Python2
ilevkivskyiSep 9, 2016
7089f66
Try alternative location for test modules
ilevkivskyiSep 9, 2016
c43cac5
Corrected import
ilevkivskyiSep 9, 2016
37f14ad
Remove test modules
ilevkivskyiSep 9, 2016
b1d3d1e
Restructured test_typing a bit. ann_modules still imported
ilevkivskyiSep 9, 2016
3c08107
Fixed bugs after refoactorig tests
ilevkivskyiSep 9, 2016
33f55d7
Trigger TRavis CI
ilevkivskyiSep 10, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletionpython2/test_typing.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@
from typing import Union, Optional
from typing import Tuple
from typing import Callable
from typing import Generic
from typing import Generic, ClassVar
from typing import cast
from typing import Type
from typing import NewType
Expand DownExpand Up@@ -802,6 +802,43 @@ class D(C):
with self.assertRaises(Exception):
D[T]

class ClassVarTests(BaseTestCase):

def test_basics(self):
with self.assertRaises(TypeError):
ClassVar[1]
with self.assertRaises(TypeError):
ClassVar[int, str]
with self.assertRaises(TypeError):
ClassVar[int][str]

def test_repr(self):
self.assertEqual(repr(ClassVar), 'typing.ClassVar')
cv = ClassVar[int]
self.assertEqual(repr(cv), 'typing.ClassVar[int]')
cv = ClassVar[Employee]
self.assertEqual(repr(cv), 'typing.ClassVar[%s.Employee]' % __name__)

def test_cannot_subclass(self):
with self.assertRaises(TypeError):
class C(type(ClassVar)):
pass
with self.assertRaises(TypeError):
class C(type(ClassVar[int])):
pass

def test_cannot_init(self):
with self.assertRaises(TypeError):
type(ClassVar)()
with self.assertRaises(TypeError):
type(ClassVar[Optional[int]])()

def test_no_isinstance(self):
with self.assertRaises(TypeError):
isinstance(1, ClassVar[int])
with self.assertRaises(TypeError):
issubclass(int, ClassVar)


class VarianceTests(BaseTestCase):

Expand Down
77 changes: 75 additions & 2 deletionspython2/typing.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,6 +18,7 @@
# Super-special typing primitives.
'Any',
'Callable',
'ClassVar',
'Generic',
'Optional',
'Tuple',
Expand DownExpand Up@@ -265,7 +266,7 @@ def __subclasscheck__(self, cls):

def _get_type_vars(types, tvars):
for t in types:
if isinstance(t, TypingMeta):
if isinstance(t, TypingMeta) or isinstance(t, _ClassVar):
t._get_type_vars(tvars)


Expand All@@ -276,7 +277,7 @@ def _type_vars(types):


def _eval_type(t, globalns, localns):
if isinstance(t, TypingMeta):
if isinstance(t, TypingMeta) or isinstance(t, _ClassVar):
return t._eval_type(globalns, localns)
else:
return t
Expand DownExpand Up@@ -320,6 +321,78 @@ def _type_repr(obj):
return repr(obj)


class ClassVarMeta(TypingMeta):
"""Metaclass for _ClassVar"""

def __new__(cls, name, bases, namespace):
cls.assert_no_subclassing(bases)
self = super(ClassVarMeta, cls).__new__(cls, name, bases, namespace)
return self


class _ClassVar(object):
"""Special type construct to mark class variables.

An annotation wrapped in ClassVar indicates that a given
attribute is intended to be used as a class variable and
should not be set on instances of that class. Usage::

class Starship:
stats = {} # type: ClassVar[Dict[str, int]] # class variable
damage = 10 # type: int # instance variable

ClassVar accepts only types and cannot be further subscribed.

Note that ClassVar is not a class itself, and should not
be used with isinstance() or issubclass().
"""

__metaclass__ = ClassVarMeta

def __init__(self, tp=None, _root=False):
cls = type(self)
if _root:
self.__type__ = tp
else:
raise TypeError('Cannot initialize {}'.format(cls.__name__[1:]))

def __getitem__(self, item):
cls = type(self)
if self.__type__ is None:
return cls(_type_check(item,
'{} accepts only types.'.format(cls.__name__[1:])),
_root=True)
raise TypeError('{} cannot be further subscripted'
.format(cls.__name__[1:]))

def _eval_type(self, globalns, localns):
return type(self)(_eval_type(self.__type__, globalns, localns),
_root=True)

def _get_type_vars(self, tvars):
if self.__type__:
_get_type_vars(self.__type__, tvars)

def __repr__(self):
cls = type(self)
if not self.__type__:
return '{}.{}'.format(cls.__module__, cls.__name__[1:])
return '{}.{}[{}]'.format(cls.__module__, cls.__name__[1:],
_type_repr(self.__type__))

def __hash__(self):
return hash((type(self).__name__, self.__type__))

def __eq__(self, other):
if not isinstance(other, _ClassVar):
return NotImplemented
if self.__type__ is not None:
return self.__type__ == other.__type__
return self is other

ClassVar = _ClassVar(_root=True)


class AnyMeta(TypingMeta):
"""Metaclass for Any."""

Expand Down
103 changes: 101 additions & 2 deletionssrc/test_typing.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,9 +9,9 @@
from typing import TypeVar, AnyStr
from typing import T, KT, VT # Not in __all__.
from typing import Union, Optional
from typing import Tuple
from typing import Tuple, List
from typing import Callable
from typing import Generic
from typing import Generic, ClassVar
from typing import cast
from typing import get_type_hints
from typing import no_type_check, no_type_check_decorator
Expand DownExpand Up@@ -827,6 +827,43 @@ class D(C):
with self.assertRaises(Exception):
D[T]

class ClassVarTests(BaseTestCase):

def test_basics(self):
with self.assertRaises(TypeError):
ClassVar[1]
with self.assertRaises(TypeError):
ClassVar[int, str]
with self.assertRaises(TypeError):
ClassVar[int][str]

def test_repr(self):
self.assertEqual(repr(ClassVar), 'typing.ClassVar')
cv = ClassVar[int]
self.assertEqual(repr(cv), 'typing.ClassVar[int]')
cv = ClassVar[Employee]
self.assertEqual(repr(cv), 'typing.ClassVar[%s.Employee]' % __name__)

def test_cannot_subclass(self):
with self.assertRaises(TypeError):
class C(type(ClassVar)):
pass
with self.assertRaises(TypeError):
class C(type(ClassVar[int])):
pass

def test_cannot_init(self):
with self.assertRaises(TypeError):
type(ClassVar)()
with self.assertRaises(TypeError):
type(ClassVar[Optional[int]])()

def test_no_isinstance(self):
with self.assertRaises(TypeError):
isinstance(1, ClassVar[int])
with self.assertRaises(TypeError):
issubclass(int, ClassVar)


class VarianceTests(BaseTestCase):

Expand DownExpand Up@@ -1119,6 +1156,68 @@ def __anext__(self) -> T_a:
if PY35:
exec(PY35_TESTS)

PY36 = sys.version_info[:2] >= (3, 6)

PY36_TESTS = """
from test import ann_module, ann_module2, ann_module3
from collections import ChainMap

class B:
x: ClassVar[Optional['B']] = None
y: int
class CSub(B):
z: ClassVar['CSub'] = B()
class G(Generic[T]):
lst: ClassVar[List[T]] = []
"""

if PY36:
exec(PY36_TESTS)

gth = get_type_hints

class GetTypeHintTests(BaseTestCase):
@skipUnless(PY36, 'Python 3.6 required')
def test_get_type_hints_modules(self):
self.assertEqual(gth(ann_module), {'x': int, 'y': str})
self.assertEqual(gth(ann_module2), {})
self.assertEqual(gth(ann_module3), {})

@skipUnless(PY36, 'Python 3.6 required')
def test_get_type_hints_classes(self):
self.assertEqual(gth(ann_module.C, ann_module.__dict__),
ChainMap({'y': Optional[ann_module.C]}, {}))
self.assertEqual(repr(gth(ann_module.j_class)), 'ChainMap({}, {})')
self.assertEqual(gth(ann_module.M), ChainMap({'123': 123, 'o': type},
{}, {}))
self.assertEqual(gth(ann_module.D),
ChainMap({'j': str, 'k': str,
'y': Optional[ann_module.C]}, {}))
self.assertEqual(gth(ann_module.Y), ChainMap({'z': int}, {}))
self.assertEqual(gth(ann_module.h_class),
ChainMap({}, {'y': Optional[ann_module.C]}, {}))
self.assertEqual(gth(ann_module.S), ChainMap({'x': str, 'y': str},
{}))
self.assertEqual(gth(ann_module.foo), {'x': int})

@skipUnless(PY36, 'Python 3.6 required')
def test_respect_no_type_check(self):
self.assertEqual(gth(ann_module2.NTC.meth), {})

def test_previous_behavior(self):
def testf(x, y): ...
testf.__annotations__['x'] = 'int'
self.assertEqual(gth(testf), {'x': int})

@skipUnless(PY36, 'Python 3.6 required')
def test_get_type_hints_ClassVar(self):
self.assertEqual(gth(B, globals()),
ChainMap({'y': int, 'x': ClassVar[Optional[B]]}, {}))
self.assertEqual(gth(CSub, globals()),
ChainMap({'z': ClassVar[CSub]},
{'y': int, 'x': ClassVar[Optional[B]]}, {}))
self.assertEqual(gth(G), ChainMap({'lst': ClassVar[List[T]]},{},{}))


class CollectionsAbcTests(BaseTestCase):

Expand Down
Loading

[8]ページ先頭

©2009-2026 Movatter.jp