typedpy 2.2.1__tar.gz → 2.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@ from typedpy.structures import (
12
12
  NoneField,
13
13
  FinalStructure,
14
14
  ImmutableField,
15
- unique
15
+ unique,
16
16
  )
17
17
  from typedpy.fields import (
18
18
  Number,
@@ -4,14 +4,14 @@ def wrap_val(v):
4
4
 
5
5
  def _is_dunder(name):
6
6
  """Returns True if a __dunder__ name, False otherwise."""
7
- return (len(name) > 4 and
8
- name[:2] == name[-2:] == '__' and
9
- name[2] != '_' and
10
- name[-3] != '_')
7
+ return (
8
+ len(name) > 4
9
+ and name[:2] == name[-2:] == "__"
10
+ and name[2] != "_"
11
+ and name[-3] != "_"
12
+ )
11
13
 
12
14
 
13
15
  def _is_sunder(name):
14
16
  """Returns True if a _sunder name, False otherwise."""
15
- return (len(name) > 2 and
16
- name[0] == '_' and
17
- name[1:2] != '_' )
17
+ return len(name) > 2 and name[0] == "_" and name[1:2] != "_"
@@ -282,11 +282,16 @@ class Function(Field):
282
282
  """
283
283
  A function or method. Note that this can't be any callable (it can't be a class, for example), but a real function
284
284
  """
285
+
285
286
  _bound_method_type = type(Field().__init__)
286
287
 
287
288
  def __set__(self, instance, value):
288
289
  def is_function(f):
289
- return type(f) in {type(lambda x: x), type(open), Function._bound_method_type}
290
+ return type(f) in {
291
+ type(lambda x: x),
292
+ type(open),
293
+ Function._bound_method_type,
294
+ }
290
295
 
291
296
  def err_prefix():
292
297
  return (
@@ -20,6 +20,7 @@ ADDITIONAL_PROPERTIES = "_additionalProperties"
20
20
  IS_IMMUTABLE = "_immutable"
21
21
  OPTIONAL_FIELDS = "_optional"
22
22
  MUST_BE_UNIQUE = "_must_be_unique"
23
+ IGNORE_NONE_VALUES = "_ignore_none"
23
24
  MAX_NUMBER_OF_INSTANCES_TO_VERIFY_UNIQUENESS = 100000
24
25
 
25
26
  py_version = sys.version_info[0:2]
@@ -108,9 +109,15 @@ def get_base_info(bases):
108
109
  """
109
110
  bases_params = OrderedDict()
110
111
  bases_required = []
111
- base_structures = [
112
- base for base in bases if issubclass(base, Structure) and base is not Structure
113
- ] if 'Structure' in globals() else []
112
+ base_structures = (
113
+ [
114
+ base
115
+ for base in bases
116
+ if issubclass(base, Structure) and base is not Structure
117
+ ]
118
+ if "Structure" in globals()
119
+ else []
120
+ )
114
121
  for base in base_structures:
115
122
  for k, param in getattr(base, "__signature__").parameters.items():
116
123
  if k not in bases_params:
@@ -138,7 +145,7 @@ def _check_for_final_violations(classes):
138
145
  )
139
146
  )
140
147
  if "ImmutableStructure" in globals() and is_sub_class(
141
- c, ImmutableStructure
148
+ c, ImmutableStructure
142
149
  ):
143
150
  raise TypeError(
144
151
  "Tried to extend {}, which is an ImmutableStructure. This is forbidden".format(
@@ -202,13 +209,19 @@ class UniqueMixin:
202
209
 
203
210
  def __manage_uniqueness__(self):
204
211
  myclass = self.__class__
205
- if getattr(myclass, MUST_BE_UNIQUE, False) and \
206
- len(getattr(myclass, "_ALL_INSTANCES", set())) < MAX_NUMBER_OF_INSTANCES_TO_VERIFY_UNIQUENESS:
212
+ if (
213
+ getattr(myclass, MUST_BE_UNIQUE, False)
214
+ and len(getattr(myclass, "_ALL_INSTANCES", set()))
215
+ < MAX_NUMBER_OF_INSTANCES_TO_VERIFY_UNIQUENESS
216
+ ):
207
217
  hash_of_instance = self.__hash__()
208
218
  if hash_of_instance in getattr(myclass, "_ALL_INSTANCES", set()):
209
219
  classname = self.__class__.__name__
210
- raise ValueError("Instance copy in {}, which is defined as unique. Instance is {}".format(
211
- classname, self))
220
+ raise ValueError(
221
+ "Instance copy in {}, which is defined as unique. Instance is {}".format(
222
+ classname, self
223
+ )
224
+ )
212
225
  getattr(myclass, "_ALL_INSTANCES", set()).add(hash_of_instance)
213
226
 
214
227
  def __manage_uniqueness_for_field__(self, instance, value):
@@ -216,14 +229,27 @@ class UniqueMixin:
216
229
  return
217
230
  field_name = getattr(self, "_name")
218
231
  structure_class_name = instance.__class__.__name__
219
- all_instances_by_struct_name = getattr(self, "_ALL_INSTANCES", defaultdict(dict))
220
- instance_by_value_for_current_struct = all_instances_by_struct_name[structure_class_name]
221
- if getattr(self, MUST_BE_UNIQUE, False) and \
222
- len(instance_by_value_for_current_struct) < MAX_NUMBER_OF_INSTANCES_TO_VERIFY_UNIQUENESS:
232
+ all_instances_by_struct_name = getattr(
233
+ self, "_ALL_INSTANCES", defaultdict(dict)
234
+ )
235
+ instance_by_value_for_current_struct = all_instances_by_struct_name[
236
+ structure_class_name
237
+ ]
238
+ if (
239
+ getattr(self, MUST_BE_UNIQUE, False)
240
+ and len(instance_by_value_for_current_struct)
241
+ < MAX_NUMBER_OF_INSTANCES_TO_VERIFY_UNIQUENESS
242
+ ):
223
243
  hash_of_field_val = value.__hash__()
224
- if instance_by_value_for_current_struct.get(hash_of_field_val, instance) != instance:
225
- raise ValueError("Instance copy of field {} in {}, which is defined as unique. Instance is {}".format(
226
- field_name, structure_class_name, wrap_val(value)))
244
+ if (
245
+ instance_by_value_for_current_struct.get(hash_of_field_val, instance)
246
+ != instance
247
+ ):
248
+ raise ValueError(
249
+ "Instance copy of field {} in {}, which is defined as unique. Instance is {}".format(
250
+ field_name, structure_class_name, wrap_val(value)
251
+ )
252
+ )
227
253
  if hash_of_field_val not in instance_by_value_for_current_struct:
228
254
  instance_by_value_for_current_struct[hash_of_field_val] = instance
229
255
 
@@ -261,12 +287,9 @@ class Field(UniqueMixin, metaclass=_FieldMeta):
261
287
  the field implicitly optional.
262
288
  Default values are validated based on the field definition like any other value
263
289
  assignment.
264
-
265
- ignore_none: optional
266
- ignore assignment to None. Default is True
267
290
  """
268
291
 
269
- def __init__(self, name=None, immutable=None, is_unique=None, default=None, ignore_none=True):
292
+ def __init__(self, name=None, immutable=None, is_unique=None, default=None):
270
293
  self._name = name
271
294
  self._default = default
272
295
  if is_unique in [True, False]:
@@ -277,7 +300,6 @@ class Field(UniqueMixin, metaclass=_FieldMeta):
277
300
  self._immutable = immutable
278
301
  if default:
279
302
  self._try_default_value(default)
280
- self._ignore_none = ignore_none
281
303
 
282
304
  def _try_default_value(self, default):
283
305
  try:
@@ -298,13 +320,13 @@ class Field(UniqueMixin, metaclass=_FieldMeta):
298
320
  else owner.__dict__[self._name]
299
321
  )
300
322
  is_immutable = (
301
- instance is not None
302
- and getattr(instance, IS_IMMUTABLE, False)
303
- or getattr(self, IS_IMMUTABLE, False)
323
+ instance is not None
324
+ and getattr(instance, IS_IMMUTABLE, False)
325
+ or getattr(self, IS_IMMUTABLE, False)
304
326
  )
305
327
  needs_defensive_copy = (
306
- not isinstance(res, (ImmutableMixin, int, float, str, bool, enum.Enum))
307
- or res is None
328
+ not isinstance(res, (ImmutableMixin, int, float, str, bool, enum.Enum))
329
+ or res is None
308
330
  )
309
331
  return deepcopy(res) if (is_immutable and needs_defensive_copy) else res
310
332
 
@@ -312,7 +334,7 @@ class Field(UniqueMixin, metaclass=_FieldMeta):
312
334
  if getattr(self, IS_IMMUTABLE, False) and self._name in instance.__dict__:
313
335
  raise ValueError("{}: Field is immutable".format(self._name))
314
336
  if getattr(self, IS_IMMUTABLE, False) and not getattr(
315
- self, "_custom_deep_copy_implementation", False
337
+ self, "_custom_deep_copy_implementation", False
316
338
  ):
317
339
  try:
318
340
  instance.__dict__[self._name] = deepcopy(value)
@@ -327,7 +349,7 @@ class Field(UniqueMixin, metaclass=_FieldMeta):
327
349
  instance.__dict__[self._name] = value
328
350
  instance.__manage__uniqueness_of_all_fields__()
329
351
  if getattr(instance, "_instantiated", False) and not getattr(
330
- instance, "_skip_validation", False
352
+ instance, "_skip_validation", False
331
353
  ):
332
354
  instance.__validate__()
333
355
 
@@ -391,33 +413,34 @@ def _get_all_fields_by_name(cls):
391
413
  def _instantiate_fields_if_needed(cls_dict: dict, defaults: dict):
392
414
  for key, val in cls_dict.items():
393
415
  if (
394
- key
395
- not in {
396
- REQUIRED_FIELDS,
397
- ADDITIONAL_PROPERTIES,
398
- IS_IMMUTABLE,
399
- DEFAULTS,
400
- OPTIONAL_FIELDS,
401
- }
402
- and not isinstance(val, Field)
403
- and not key.startswith("__")
404
- and (
416
+ key
417
+ not in {
418
+ REQUIRED_FIELDS,
419
+ ADDITIONAL_PROPERTIES,
420
+ IS_IMMUTABLE,
421
+ DEFAULTS,
422
+ OPTIONAL_FIELDS,
423
+ IGNORE_NONE_VALUES,
424
+ }
425
+ and not isinstance(val, Field)
426
+ and not key.startswith("__")
427
+ and (
405
428
  Field in getattr(val, "__mro__", []) or is_function_returning_field(val)
406
- )
429
+ )
407
430
  ):
408
431
  new_val = val(default=defaults[key]) if key in defaults else val()
409
432
  cls_dict[key] = new_val
410
433
 
411
434
 
412
435
  def _apply_default_and_update_required_not_to_include_fields_with_defaults(
413
- cls_dict: dict, defaults: dict, fields: list
436
+ cls_dict: dict, defaults: dict, fields: list
414
437
  ):
415
438
  required_fields = set(cls_dict.get(REQUIRED_FIELDS, []))
416
439
  optional_fields = set(cls_dict.get(OPTIONAL_FIELDS, []))
417
440
  required_fields_predefined = REQUIRED_FIELDS in cls_dict
418
441
  for field_name in fields:
419
442
  if field_name in defaults and not getattr(
420
- cls_dict[field_name], "_default", None
443
+ cls_dict[field_name], "_default", None
421
444
  ):
422
445
  cls_dict[field_name]._try_default_value(defaults[field_name])
423
446
  cls_dict[field_name]._default = defaults[field_name]
@@ -524,15 +547,15 @@ def _type_is_generic(v):
524
547
  generic_alias = getattr(typing, "_GenericAlias", Foo)
525
548
  special_generic_alias = getattr(typing, "_SpecialGenericAlias", Foo)
526
549
  return (
527
- (python_ver_36 and isinstance(v, typing_base))
528
- or (
529
- python_ver_atleast_than_37
530
- and isinstance(v, (generic_alias, special_generic_alias))
531
- )
532
- or (
533
- python_ver_atleast_39
534
- and origin in {list, dict, tuple, set, frozenset, deque, typing.Union}
535
- )
550
+ (python_ver_36 and isinstance(v, typing_base))
551
+ or (
552
+ python_ver_atleast_than_37
553
+ and isinstance(v, (generic_alias, special_generic_alias))
554
+ )
555
+ or (
556
+ python_ver_atleast_39
557
+ and origin in {list, dict, tuple, set, frozenset, deque, typing.Union}
558
+ )
536
559
  )
537
560
 
538
561
 
@@ -591,7 +614,7 @@ def add_annotations_to_class_dict(cls_dict):
591
614
  from .fields import AnyOf
592
615
 
593
616
  if isinstance(the_type, AnyOf) and getattr(
594
- the_type, "_is_optional", False
617
+ the_type, "_is_optional", False
595
618
  ):
596
619
  optional_fields.add(k)
597
620
  if k in cls_dict:
@@ -665,6 +688,10 @@ class Structure(UniqueMixin, metaclass=StructMeta):
665
688
  # this raises an exception:
666
689
  Foo(id = 1, a = 2)
667
690
 
691
+ _ignore_none(bool): optional
692
+ Ignore assignment to None for any field value.
693
+ Default is False.
694
+
668
695
  Decorating it with @unique ensures that no all instances of this structure will be unique. It
669
696
  will raise an exception otherwise (see "Uniqueness" section).
670
697
  """
@@ -696,10 +723,15 @@ class Structure(UniqueMixin, metaclass=StructMeta):
696
723
  if key in self.__dict__:
697
724
  raise ValueError("Structure is immutable")
698
725
  value = deepcopy(value)
726
+ if getattr(self, IGNORE_NONE_VALUES, False) and value is None:
727
+ return
699
728
  super().__setattr__(key, value)
700
729
 
701
- if getattr(self, "_instantiated", False) \
702
- and not _is_dunder(key) and not _is_sunder(key):
730
+ if (
731
+ getattr(self, "_instantiated", False)
732
+ and not _is_dunder(key)
733
+ and not _is_sunder(key)
734
+ ):
703
735
  self.__manage_uniqueness__()
704
736
 
705
737
  def __getstate__(self):
@@ -734,7 +766,7 @@ class Structure(UniqueMixin, metaclass=StructMeta):
734
766
 
735
767
  name = self.__class__.__name__
736
768
  if name.startswith("StructureReference_") and self.__class__.__bases__ == (
737
- Structure,
769
+ Structure,
738
770
  ):
739
771
  name = "Structure"
740
772
  props = []
@@ -765,7 +797,7 @@ class Structure(UniqueMixin, metaclass=StructMeta):
765
797
 
766
798
  def __delitem__(self, key):
767
799
  if isinstance(getattr(self, REQUIRED_FIELDS), list) and key in getattr(
768
- self, REQUIRED_FIELDS
800
+ self, REQUIRED_FIELDS
769
801
  ):
770
802
  raise ValueError("{} is mandatory".format(key))
771
803
  del self.__dict__[key]
@@ -810,9 +842,9 @@ class Structure(UniqueMixin, metaclass=StructMeta):
810
842
  required = props.get(REQUIRED_FIELDS, field_names)
811
843
  additional_props = props.get(ADDITIONAL_PROPERTIES, True)
812
844
  if (
813
- len(field_names) == 1
814
- and required == field_names
815
- and additional_props is False
845
+ len(field_names) == 1
846
+ and required == field_names
847
+ and additional_props is False
816
848
  ):
817
849
  return item in getattr(self, field_names[0], {})
818
850
 
@@ -882,8 +914,6 @@ class TypedField(Field):
882
914
  )
883
915
 
884
916
  def __set__(self, instance, value):
885
- if getattr(instance, "_ignore_none", False) and value is None:
886
- return
887
917
  if not getattr(instance, "_skip_validation", False):
888
918
  self._validate(value)
889
919
  super().__set__(instance, value)
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: typedpy
3
- Version: 2.2.1
3
+ Version: 2.2.2
4
4
  Summary: Type-safe Python
5
5
  Home-page: http://github.com/loyada/typedpy
6
6
  Author: Danny Loya
7
7
  Author-email: dan.loya@gmail.com
8
8
  License: MIT
9
- Download-URL: https://github.com/loyada/typedpy/archive/v2.2.1.tar.gz
9
+ Download-URL: https://github.com/loyada/typedpy/archive/v2.2.2.tar.gz
10
10
  Description: [![][travis img]][travis]
11
11
  [![][docs img]][docs]
12
12