params-proto 3.2.3__py3-none-any.whl → 3.2.4__py3-none-any.whl

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.
params_proto/proto.py CHANGED
@@ -694,59 +694,9 @@ class ptype(type):
694
694
 
695
695
  # Update the instance's class to the decorated class
696
696
  # This allows isinstance(instance, DecoratedClass) to work
697
+ # Since cls is a subclass of original_cls, methods are inherited naturally
697
698
  object.__setattr__(instance, "__class__", cls)
698
699
 
699
- # Copy methods from original class and wrap to return self
700
- for name in dir(original_cls):
701
- # Skip proto fields (fields are handled above)
702
- if name in annotations:
703
- continue
704
-
705
- # For dunder methods, only copy user-defined ones (not inherited from object/type)
706
- if name.startswith("__"):
707
- # Check if this dunder method is user-defined (not from object or type)
708
- is_user_defined = False
709
- for klass in original_cls.__mro__:
710
- if klass is object or klass is type:
711
- break
712
- if name in klass.__dict__:
713
- is_user_defined = True
714
- break
715
- if not is_user_defined:
716
- continue
717
-
718
- # Check raw descriptor in MRO to detect staticmethod/classmethod (handles inheritance)
719
- raw_attr = None
720
- for klass in original_cls.__mro__:
721
- if name in klass.__dict__:
722
- raw_attr = klass.__dict__[name]
723
- break
724
-
725
- attr = getattr(original_cls, name)
726
-
727
- # Only process actual methods (staticmethod, classmethod, or function)
728
- if isinstance(raw_attr, staticmethod):
729
- # For staticmethod, use directly (no binding needed)
730
- method = attr
731
- elif isinstance(raw_attr, classmethod) or inspect.isfunction(raw_attr) or inspect.ismethod(attr):
732
- # For instance methods and classmethods, bind to instance
733
- # Note: classmethods bound to instance is intentional for @proto
734
- # semantics where instances have all attributes accessible
735
- method = attr.__get__(instance, original_cls)
736
- else:
737
- # Not a method (e.g., _EnvVar, property, or other callable), skip
738
- continue
739
-
740
- # Wrap it to return self if it returns None
741
- def make_wrapper(m):
742
- def wrapper(*args, **kwargs):
743
- result = m(*args, **kwargs)
744
- return instance if result is None else result
745
-
746
- return wrapper
747
-
748
- setattr(instance, name, make_wrapper(method))
749
-
750
700
  return instance
751
701
 
752
702
 
@@ -869,30 +819,32 @@ def proto(
869
819
  else:
870
820
  metaclass = ptype
871
821
 
872
- # Recreate the class with ptype as its metaclass
873
- # Collect class namespace (attributes and methods)
874
- namespace = {}
875
- for key in dir(obj):
876
- if not key.startswith("__") or key in ("__annotations__", "__module__", "__qualname__", "__doc__"):
877
- try:
878
- # Use __dict__ to preserve classmethod/staticmethod descriptors
879
- # getattr() would return bound methods instead of descriptors
880
- if key in obj.__dict__:
881
- namespace[key] = obj.__dict__[key]
882
- else:
883
- namespace[key] = getattr(obj, key)
884
- except AttributeError:
885
- pass
822
+ # Create new class with metaclass as subclass of original
823
+ # Since new class inherits from obj, methods are inherited naturally.
824
+ # We only need to provide:
825
+ # - Module/qualname metadata
826
+ # - Annotations (so annotated fields are visible on the class)
827
+ # - Resolved default values (with EnvVars resolved)
828
+ namespace = {
829
+ "__module__": obj.__module__,
830
+ "__qualname__": obj.__qualname__,
831
+ "__doc__": obj.__doc__,
832
+ "__annotations__": annotations,
833
+ }
886
834
 
887
- # Replace _EnvVar objects with resolved values from defaults
888
- # This ensures the descriptor doesn't interfere with class attribute access
889
- for key, value in defaults.items():
890
- namespace[key] = value
835
+ # Add resolved default values (EnvVars are already resolved in defaults dict)
836
+ # Also set None for annotated fields without defaults so they're accessible
837
+ for key in annotations.keys():
838
+ if key in defaults:
839
+ namespace[key] = defaults[key]
840
+ else:
841
+ namespace[key] = None
891
842
 
892
- # Create new class with metaclass
893
- # IMPORTANT: Use (obj,) as bases to make new class a SUBCLASS of original.
894
- # This ensures super() works correctly - the original class is in the MRO,
895
- # so Python's super() validation passes when checking isinstance(self, original_class).
843
+ # Create new class as SUBCLASS of original.
844
+ # This ensures:
845
+ # 1. super() works correctly (original class is in MRO)
846
+ # 2. Methods, staticmethods, classmethods are inherited naturally
847
+ # 3. isinstance(instance, DecoratedClass) works
896
848
  new_cls = metaclass(
897
849
  obj.__name__,
898
850
  (obj,),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: params-proto
3
- Version: 3.2.3
3
+ Version: 3.2.4
4
4
  Summary: Modern Hyper Parameter Management for Machine Learning
5
5
  Project-URL: Homepage, https://github.com/geyang/params-proto
6
6
  Project-URL: Documentation, https://params-proto.readthedocs.io
@@ -3,7 +3,7 @@ params_proto/app.py,sha256=UySpd1op3M44Szk6Ekyn0fJcnZsQvMTMPdaEybwWsLE,19
3
3
  params_proto/documentation.py,sha256=mIqmcwGWo8tM1BuNzLIwVTzdbQ3qyPus7yWTaOce4dM,8091
4
4
  params_proto/envvar.py,sha256=A87jxSAQ2tjbKLbrm96lblV90zNdtBGCSV6QRe2DrgA,8398
5
5
  params_proto/parse_env_template.py,sha256=mXTvKpNhT2jGr3HpwKw42shd18O0QACmSJn6yWMDdKA,1298
6
- params_proto/proto.py,sha256=CYLLEKT8mDcxi25q75wIjHuoS3U_7cMvWuqFRmeTYAQ,39996
6
+ params_proto/proto.py,sha256=9l_WFj3yfKbW74Jo-247rnJzNsinQHZ2wqW9K158Zeo,38081
7
7
  params_proto/type_utils.py,sha256=x68rL5m76ZFRKsCRgH_i_4vLpt6ldWEsEAalgacFIH8,7364
8
8
  params_proto/cli/__init__.py,sha256=sLpN3GmaBqd_d0J0nvUNOeGlV74_-jQGW0nDUU34tjA,493
9
9
  params_proto/cli/ansi_help.py,sha256=-1gzbvOpi9GjPlqgiINOYQAfIstzg0-ukv1se88TYCQ,10967
@@ -20,7 +20,7 @@ params_proto/v2/hyper.py,sha256=onBAkT8Ja8IkeHEOq1AwCdTuBzAnthIe766ZE0lAy-M,1146
20
20
  params_proto/v2/partial.py,sha256=_ovi4NY8goYgHurfYt1OV0E9DSMXGYucjMVIyG1Q_xc,983
21
21
  params_proto/v2/proto.py,sha256=-BTTwFOhJsaPnujwFIDh14QMB8r_ZdridK9I2Jkqd_U,19228
22
22
  params_proto/v2/utils.py,sha256=5EWvwboZDTsCYfzSED_J6RVFyNLIlf95nIu4p_ZSVxA,3540
23
- params_proto-3.2.3.dist-info/METADATA,sha256=bKvvnv82Bs4UkhnDvsNyWXoGPjhX7fDf0U9_IiCoXJA,8959
24
- params_proto-3.2.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
25
- params_proto-3.2.3.dist-info/licenses/LICENSE.md,sha256=c2qSYi9tUMZtzj9SEsMeKhub5LJUmHwBtDLiIMM5b6U,1526
26
- params_proto-3.2.3.dist-info/RECORD,,
23
+ params_proto-3.2.4.dist-info/METADATA,sha256=zHg8HnFEU7IQrSZLUZOOLi5WVfBUVkk__jKGgJDoh-s,8959
24
+ params_proto-3.2.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
25
+ params_proto-3.2.4.dist-info/licenses/LICENSE.md,sha256=c2qSYi9tUMZtzj9SEsMeKhub5LJUmHwBtDLiIMM5b6U,1526
26
+ params_proto-3.2.4.dist-info/RECORD,,