Reflow dataclasses comments (GH-6893)
To be more consistent with other code (and so people stop hassling me!), reflow the dataclasses comments to not use a single space indentation when continuing a paragraph of text.
This commit is contained in:
parent
98d50cb8f5
commit
f8e7549490
@ -25,8 +25,8 @@ __all__ = ['dataclass',
|
||||
# about init=, repr=, eq=, order=, unsafe_hash=, or frozen=, I'm
|
||||
# referring to the arguments to the @dataclass decorator. When
|
||||
# checking if a dunder method already exists, I mean check for an
|
||||
# entry in the class's __dict__. I never check to see if an
|
||||
# attribute is defined in a base class.
|
||||
# entry in the class's __dict__. I never check to see if an attribute
|
||||
# is defined in a base class.
|
||||
|
||||
# Key:
|
||||
# +=========+=========================================+
|
||||
@ -138,19 +138,20 @@ __all__ = ['dataclass',
|
||||
# For boxes that are blank, __hash__ is untouched and therefore
|
||||
# inherited from the base class. If the base is object, then
|
||||
# id-based hashing is used.
|
||||
#
|
||||
# Note that a class may already have __hash__=None if it specified an
|
||||
# __eq__ method in the class body (not one that was created by
|
||||
# @dataclass).
|
||||
#
|
||||
# See _hash_action (below) for a coded version of this table.
|
||||
|
||||
|
||||
# Raised when an attempt is made to modify a frozen class.
|
||||
class FrozenInstanceError(AttributeError): pass
|
||||
|
||||
# A sentinel object for default values to signal that a
|
||||
# default factory will be used.
|
||||
# This is given a nice repr() which will appear in the function
|
||||
# signature of dataclasses' constructors.
|
||||
# A sentinel object for default values to signal that a default
|
||||
# factory will be used. This is given a nice repr() which will appear
|
||||
# in the function signature of dataclasses' constructors.
|
||||
class _HAS_DEFAULT_FACTORY_CLASS:
|
||||
def __repr__(self):
|
||||
return '<factory>'
|
||||
@ -204,9 +205,11 @@ class InitVar(metaclass=_InitVarMeta):
|
||||
# Instances of Field are only ever created from within this module,
|
||||
# and only from the field() function, although Field instances are
|
||||
# exposed externally as (conceptually) read-only objects.
|
||||
# name and type are filled in after the fact, not in __init__. They're
|
||||
# not known at the time this class is instantiated, but it's
|
||||
#
|
||||
# name and type are filled in after the fact, not in __init__.
|
||||
# They're not known at the time this class is instantiated, but it's
|
||||
# convenient if they're available later.
|
||||
#
|
||||
# When cls._FIELDS is filled in with a list of Field objects, the name
|
||||
# and type fields will have been populated.
|
||||
class Field:
|
||||
@ -255,14 +258,15 @@ class Field:
|
||||
# case where we're using a field that contains a descriptor as a
|
||||
# defaul value. For details on __set_name__, see
|
||||
# https://www.python.org/dev/peps/pep-0487/#implementation-details.
|
||||
# Note that in _process_class, this Field object is overwritten with
|
||||
# the default value, so the end result is a descriptor that had
|
||||
# __set_name__ called on it at the right time.
|
||||
#
|
||||
# Note that in _process_class, this Field object is overwritten
|
||||
# with the default value, so the end result is a descriptor that
|
||||
# had __set_name__ called on it at the right time.
|
||||
def __set_name__(self, owner, name):
|
||||
func = getattr(type(self.default), '__set_name__', None)
|
||||
if func:
|
||||
# There is a __set_name__ method on the descriptor,
|
||||
# call it.
|
||||
# There is a __set_name__ method on the descriptor, call
|
||||
# it.
|
||||
func(self.default, owner, name)
|
||||
|
||||
|
||||
@ -306,9 +310,9 @@ def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True,
|
||||
is True, the field will be a parameter to the class's __init__()
|
||||
function. If repr is True, the field will be included in the
|
||||
object's repr(). If hash is True, the field will be included in
|
||||
the object's hash(). If compare is True, the field will be used in
|
||||
comparison functions. metadata, if specified, must be a mapping
|
||||
which is stored but not otherwise examined by dataclass.
|
||||
the object's hash(). If compare is True, the field will be used
|
||||
in comparison functions. metadata, if specified, must be a
|
||||
mapping which is stored but not otherwise examined by dataclass.
|
||||
|
||||
It is an error to specify both default and default_factory.
|
||||
"""
|
||||
@ -333,9 +337,9 @@ def _tuple_str(obj_name, fields):
|
||||
|
||||
def _create_fn(name, args, body, *, globals=None, locals=None,
|
||||
return_type=MISSING):
|
||||
# Note that we mutate locals when exec() is called. Caller beware!
|
||||
# The only callers are internal to this module, so no worries
|
||||
# about external callers.
|
||||
# Note that we mutate locals when exec() is called. Caller
|
||||
# beware! The only callers are internal to this module, so no
|
||||
# worries about external callers.
|
||||
if locals is None:
|
||||
locals = {}
|
||||
return_annotation = ''
|
||||
@ -356,6 +360,7 @@ def _field_assign(frozen, name, value, self_name):
|
||||
# If we're a frozen class, then assign to our fields in __init__
|
||||
# via object.__setattr__. Otherwise, just use a simple
|
||||
# assignment.
|
||||
#
|
||||
# self_name is what "self" is called in this function: don't
|
||||
# hard-code "self", since that might be a field name.
|
||||
if frozen:
|
||||
@ -403,8 +408,8 @@ def _field_init(f, frozen, globals, self_name):
|
||||
globals[default_name] = f.default
|
||||
value = f.name
|
||||
else:
|
||||
# This field does not need initialization. Signify that to
|
||||
# the caller by returning None.
|
||||
# This field does not need initialization. Signify that
|
||||
# to the caller by returning None.
|
||||
return None
|
||||
|
||||
# Only test this now, so that we can create variables for the
|
||||
@ -418,16 +423,17 @@ def _field_init(f, frozen, globals, self_name):
|
||||
|
||||
|
||||
def _init_param(f):
|
||||
# Return the __init__ parameter string for this field.
|
||||
# For example, the equivalent of 'x:int=3' (except instead of 'int',
|
||||
# Return the __init__ parameter string for this field. For
|
||||
# example, the equivalent of 'x:int=3' (except instead of 'int',
|
||||
# reference a variable set to int, and instead of '3', reference a
|
||||
# variable set to 3).
|
||||
if f.default is MISSING and f.default_factory is MISSING:
|
||||
# There's no default, and no default_factory, just
|
||||
# output the variable name and type.
|
||||
# There's no default, and no default_factory, just output the
|
||||
# variable name and type.
|
||||
default = ''
|
||||
elif f.default is not MISSING:
|
||||
# There's a default, this will be the name that's used to look it up.
|
||||
# There's a default, this will be the name that's used to look
|
||||
# it up.
|
||||
default = f'=_dflt_{f.name}'
|
||||
elif f.default_factory is not MISSING:
|
||||
# There's a factory function. Set a marker.
|
||||
@ -493,8 +499,8 @@ def _repr_fn(fields):
|
||||
|
||||
|
||||
def _frozen_get_del_attr(cls, fields):
|
||||
# XXX: globals is modified on the first call to _create_fn, then the
|
||||
# modified version is used in the second call. Is this okay?
|
||||
# XXX: globals is modified on the first call to _create_fn, then
|
||||
# the modified version is used in the second call. Is this okay?
|
||||
globals = {'cls': cls,
|
||||
'FrozenInstanceError': FrozenInstanceError}
|
||||
if fields:
|
||||
@ -573,25 +579,25 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate):
|
||||
# instead only a module (global) lookup), there are some things it
|
||||
# gets wrong.
|
||||
|
||||
# With string annotations, this will work:
|
||||
# With string annotations, cv0 will be detected as a ClassVar:
|
||||
# CV = ClassVar
|
||||
# @dataclass
|
||||
# class C0:
|
||||
# cv0: CV
|
||||
|
||||
# But this will not:
|
||||
# But in this example cv1 will not be detected as a ClassVar:
|
||||
# @dataclass
|
||||
# class C1:
|
||||
# CV = ClassVar
|
||||
# cv1: CV
|
||||
|
||||
# In C1, the code in this function will look up "CV" in the module
|
||||
# and not find it, so it will not consider cv1 as a ClassVar.
|
||||
# This is a fairly obscure corner case, and the best way to fix it
|
||||
# would be to eval() the string "CV" with the correct global and
|
||||
# local namespaces. However that would involve a eval() penalty
|
||||
# for every single field of every dataclass that's defined. It
|
||||
# was judged not worth it.
|
||||
# In C1, the code in this function (_is_type) will look up "CV" in
|
||||
# the module and not find it, so it will not consider cv1 as a
|
||||
# ClassVar. This is a fairly obscure corner case, and the best
|
||||
# way to fix it would be to eval() the string "CV" with the
|
||||
# correct global and local namespaces. However that would involve
|
||||
# a eval() penalty for every single field of every dataclass
|
||||
# that's defined. It was judged not worth it.
|
||||
|
||||
match = _MODULE_IDENTIFIER_RE.match(annotation)
|
||||
if match:
|
||||
@ -616,8 +622,8 @@ def _get_field(cls, a_name, a_type):
|
||||
# and InitVars are also returned, but marked as such (see
|
||||
# f._field_type).
|
||||
|
||||
# If the default value isn't derived from Field, then it's
|
||||
# only a normal default value. Convert it to a Field().
|
||||
# If the default value isn't derived from Field, then it's only a
|
||||
# normal default value. Convert it to a Field().
|
||||
default = getattr(cls, a_name, MISSING)
|
||||
if isinstance(default, Field):
|
||||
f = default
|
||||
@ -640,9 +646,9 @@ def _get_field(cls, a_name, a_type):
|
||||
# string annotations. get_type_hints() won't always work for us
|
||||
# (see https://github.com/python/typing/issues/508 for example),
|
||||
# plus it's expensive and would require an eval for every stirng
|
||||
# annotation. So, make a best effort to see if this is a
|
||||
# ClassVar or InitVar using regex's and checking that the thing
|
||||
# referenced is actually of the correct type.
|
||||
# annotation. So, make a best effort to see if this is a ClassVar
|
||||
# or InitVar using regex's and checking that the thing referenced
|
||||
# is actually of the correct type.
|
||||
|
||||
# For the complete discussion, see https://bugs.python.org/issue33453
|
||||
|
||||
@ -652,8 +658,6 @@ def _get_field(cls, a_name, a_type):
|
||||
# module).
|
||||
typing = sys.modules.get('typing')
|
||||
if typing:
|
||||
# This test uses a typing internal class, but it's the best
|
||||
# way to test if this is a ClassVar.
|
||||
if (_is_classvar(a_type, typing)
|
||||
or (isinstance(f.type, str)
|
||||
and _is_type(f.type, cls, typing, typing.ClassVar,
|
||||
@ -682,8 +686,8 @@ def _get_field(cls, a_name, a_type):
|
||||
raise TypeError(f'field {f.name} cannot have a '
|
||||
'default factory')
|
||||
# Should I check for other field settings? default_factory
|
||||
# seems the most serious to check for. Maybe add others.
|
||||
# For example, how about init=False (or really,
|
||||
# seems the most serious to check for. Maybe add others. For
|
||||
# example, how about init=False (or really,
|
||||
# init=<not-the-default-init-value>)? It makes no sense for
|
||||
# ClassVar and InitVar to specify init=<anything>.
|
||||
|
||||
@ -763,8 +767,8 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||
|
||||
# Find our base classes in reverse MRO order, and exclude
|
||||
# ourselves. In reversed order so that more derived classes
|
||||
# override earlier field definitions in base classes.
|
||||
# As long as we're iterating over them, see if any are frozen.
|
||||
# override earlier field definitions in base classes. As long as
|
||||
# we're iterating over them, see if any are frozen.
|
||||
any_frozen_base = False
|
||||
has_dataclass_bases = False
|
||||
for b in cls.__mro__[-1:0:-1]:
|
||||
@ -780,29 +784,30 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||
|
||||
# Annotations that are defined in this class (not in base
|
||||
# classes). If __annotations__ isn't present, then this class
|
||||
# adds no new annotations. We use this to compute fields that
|
||||
# are added by this class.
|
||||
# adds no new annotations. We use this to compute fields that are
|
||||
# added by this class.
|
||||
#
|
||||
# Fields are found from cls_annotations, which is guaranteed to be
|
||||
# ordered. Default values are from class attributes, if a field
|
||||
# has a default. If the default value is a Field(), then it
|
||||
# contains additional info beyond (and possibly including) the
|
||||
# actual default value. Pseudo-fields ClassVars and InitVars are
|
||||
# included, despite the fact that they're not real fields.
|
||||
# That's dealt with later.
|
||||
# included, despite the fact that they're not real fields. That's
|
||||
# dealt with later.
|
||||
cls_annotations = cls.__dict__.get('__annotations__', {})
|
||||
|
||||
# Now find fields in our class. While doing so, validate some
|
||||
# things, and set the default values (as class attributes)
|
||||
# where we can.
|
||||
# things, and set the default values (as class attributes) where
|
||||
# we can.
|
||||
cls_fields = [_get_field(cls, name, type)
|
||||
for name, type in cls_annotations.items()]
|
||||
for f in cls_fields:
|
||||
fields[f.name] = f
|
||||
|
||||
# If the class attribute (which is the default value for
|
||||
# this field) exists and is of type 'Field', replace it
|
||||
# with the real default. This is so that normal class
|
||||
# introspection sees a real default value, not a Field.
|
||||
# If the class attribute (which is the default value for this
|
||||
# field) exists and is of type 'Field', replace it with the
|
||||
# real default. This is so that normal class introspection
|
||||
# sees a real default value, not a Field.
|
||||
if isinstance(getattr(cls, f.name, None), Field):
|
||||
if f.default is MISSING:
|
||||
# If there's no default, delete the class attribute.
|
||||
@ -832,8 +837,8 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||
raise TypeError('cannot inherit frozen dataclass from a '
|
||||
'non-frozen one')
|
||||
|
||||
# Remember all of the fields on our class (including bases). This also
|
||||
# marks this class as being a dataclass.
|
||||
# Remember all of the fields on our class (including bases). This
|
||||
# also marks this class as being a dataclass.
|
||||
setattr(cls, _FIELDS, fields)
|
||||
|
||||
# Was this class defined with an explicit __hash__? Note that if
|
||||
@ -845,8 +850,8 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||
has_explicit_hash = not (class_hash is MISSING or
|
||||
(class_hash is None and '__eq__' in cls.__dict__))
|
||||
|
||||
# If we're generating ordering methods, we must be generating
|
||||
# the eq methods.
|
||||
# If we're generating ordering methods, we must be generating the
|
||||
# eq methods.
|
||||
if order and not eq:
|
||||
raise ValueError('eq must be true if order is true')
|
||||
|
||||
@ -861,8 +866,9 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
|
||||
_init_fn(flds,
|
||||
frozen,
|
||||
has_post_init,
|
||||
# The name to use for the "self" param
|
||||
# in __init__. Use "self" if possible.
|
||||
# The name to use for the "self"
|
||||
# param in __init__. Use "self"
|
||||
# if possible.
|
||||
'__dataclass_self__' if 'self' in fields
|
||||
else 'self',
|
||||
))
|
||||
@ -1130,8 +1136,8 @@ def replace(obj, **changes):
|
||||
assert c1.x == 3 and c1.y == 2
|
||||
"""
|
||||
|
||||
# We're going to mutate 'changes', but that's okay because it's a new
|
||||
# dict, even if called with 'replace(obj, **my_changes)'.
|
||||
# We're going to mutate 'changes', but that's okay because it's a
|
||||
# new dict, even if called with 'replace(obj, **my_changes)'.
|
||||
|
||||
if not _is_dataclass_instance(obj):
|
||||
raise TypeError("replace() should be called on dataclass instances")
|
||||
@ -1152,8 +1158,8 @@ def replace(obj, **changes):
|
||||
changes[f.name] = getattr(obj, f.name)
|
||||
|
||||
# Create the new object, which calls __init__() and
|
||||
# __post_init__() (if defined), using all of the init fields
|
||||
# we've added and/or left in 'changes'. If there are values
|
||||
# supplied in changes that aren't fields, this will correctly
|
||||
# raise a TypeError.
|
||||
# __post_init__() (if defined), using all of the init fields we've
|
||||
# added and/or left in 'changes'. If there are values supplied in
|
||||
# changes that aren't fields, this will correctly raise a
|
||||
# TypeError.
|
||||
return obj.__class__(**changes)
|
||||
|
Loading…
x
Reference in New Issue
Block a user