From 7e0a98bbcfa4817509bd7e0c11dcff12f304b035 Mon Sep 17 00:00:00 2001 From: Daiyi Peng Date: Mon, 25 Sep 2023 17:08:04 -0700 Subject: [PATCH] `pg.Formattable`: Uses `__str_format_kwargs__`/`__repr_format_kwargs__` to control the format of `__str__` and `__repr__`. PiperOrigin-RevId: 568364421 --- pyglove/core/geno/base.py | 24 +++++++++++----------- pyglove/core/object_utils/common_traits.py | 10 +++++++-- pyglove/core/symbolic/base.py | 10 +++------ pyglove/core/symbolic/dict.py | 2 +- pyglove/core/tuning/protocols.py | 4 ---- pyglove/core/typing/class_schema.py | 11 ---------- 6 files changed, 24 insertions(+), 37 deletions(-) diff --git a/pyglove/core/geno/base.py b/pyglove/core/geno/base.py index cc38665..806e4c9 100644 --- a/pyglove/core/geno/base.py +++ b/pyglove/core/geno/base.py @@ -72,6 +72,15 @@ class DNASpec(symbolic.Object): method, it's aimed to be used within the same process, thus not required to be serializable. """ + + # Override format kwargs for __str__. + __str_format_kwargs__ = dict( + compact=True, + verbose=False, + hide_default_values=True, + hide_missing_values=True + ) + # NOTE(daiyip): we disable the symbolic comparison to allow hashing DNASpec # by object ID, therefore we can use DNASpec objects as the keys for a dict. # This is helpful when we want to align decision points using DNASpec as @@ -332,14 +341,6 @@ def userdata(self) -> AttributeDict: """Gets user data.""" return self._userdata - def __str__(self): - """Operator str.""" - return self.format( - compact=True, - verbose=False, - hide_default_values=True, - hide_missing_values=True) - @classmethod def from_json(cls, json_value, *args, **kwargs) -> symbolic.Object: """Override from_json for backward compatibility with serialized data.""" @@ -468,6 +469,9 @@ class DNA(symbolic.Object): """ # pylint: enable=line-too-long + # Use compact format for __str__ output. + __str_format_kwargs__ = dict(compact=True) + # Allow assignment on symbolic attributes. allow_symbolic_assignment = True @@ -1686,10 +1690,6 @@ def from_parameters(cls, del use_literal_values return cls.from_dict(parameters, dna_spec) - def __str__(self) -> str: - """Use compact form as string representation.""" - return self.format(compact=True) - symbolic.members([ ( diff --git a/pyglove/core/object_utils/common_traits.py b/pyglove/core/object_utils/common_traits.py index b6bcbe9..8f896ac 100644 --- a/pyglove/core/object_utils/common_traits.py +++ b/pyglove/core/object_utils/common_traits.py @@ -31,6 +31,12 @@ class Formattable(metaclass=abc.ABCMeta): All symbolic types implement this interface. """ + # Additional format keyword arguments for `__str__`. + __str_format_kwargs__ = dict(compact=False, verbose=True) + + # Additional format keyword arguments for `__repr__`. + __repr_format_kwargs__ = dict(compact=True) + @abc.abstractmethod def format(self, compact: bool = False, @@ -53,11 +59,11 @@ def format(self, def __str__(self) -> str: """Returns the full (maybe multi-line) representation of this object.""" - return self.format(compact=False, verbose=True) + return self.format(**self.__str_format_kwargs__) def __repr__(self) -> str: """Returns a single-line representation of this object.""" - return self.format(compact=True) + return self.format(**self.__repr_format_kwargs__) class MaybePartial(metaclass=abc.ABCMeta): diff --git a/pyglove/core/symbolic/base.py b/pyglove/core/symbolic/base.py index ccc09d3..f4d5276 100644 --- a/pyglove/core/symbolic/base.py +++ b/pyglove/core/symbolic/base.py @@ -193,6 +193,9 @@ class Symbolic( :class:`pyglove.Dict`. """ + # Do not include comments in str output. + __str_format_kwargs__ = dict(compact=False, verbose=False) + # Symbolic sub-types that will be set when they are defined. # pylint: disable=invalid-name @@ -1056,13 +1059,6 @@ class A(pg.Object): v = query(self, path_regex, where, False, custom_selector) object_utils.print(v, file=file, **kwargs) - def __str__(self) -> str: - """Override Formattable.__str__ by setting verbose to False.""" - return self.format(compact=False, verbose=False) - - def __repr__(self) -> str: - return self.format(compact=True) - def __copy__(self) -> 'Symbolic': """Overridden shallow copy.""" return self.sym_clone(deep=False) diff --git a/pyglove/core/symbolic/dict.py b/pyglove/core/symbolic/dict.py index 3b200e5..60b63dd 100644 --- a/pyglove/core/symbolic/dict.py +++ b/pyglove/core/symbolic/dict.py @@ -967,7 +967,7 @@ def _should_include_key(key): def __repr__(self) -> str: """Operator repr().""" - return self.format(compact=True) + return base.Symbolic.__repr__(self) def __eq__(self, other: Any) -> bool: """Operator ==.""" diff --git a/pyglove/core/tuning/protocols.py b/pyglove/core/tuning/protocols.py index c82b8bc..f69f282 100644 --- a/pyglove/core/tuning/protocols.py +++ b/pyglove/core/tuning/protocols.py @@ -36,10 +36,6 @@ def __hash__(self): """Hash code.""" return hash(repr(self)) - def __str__(self): - """Overrides __str__ to use non-verbose format.""" - return self.format(compact=False, verbose=False) - @symbolic.members([ ('step', pg_typing.Int(), 'At which step the result is reported.'), diff --git a/pyglove/core/typing/class_schema.py b/pyglove/core/typing/class_schema.py index 21ed133..bf533bd 100644 --- a/pyglove/core/typing/class_schema.py +++ b/pyglove/core/typing/class_schema.py @@ -519,14 +519,6 @@ def __ne__(self, other: Any) -> bool: """Operator !=.""" return not self.__eq__(other) - def __repr__(self) -> str: - """Operator repr.""" - return self.format(compact=True) - - def __str__(self) -> str: - """Operator str.""" - return self.format(compact=False, verbose=True) - @classmethod def from_annotation( cls, @@ -1268,9 +1260,6 @@ def to_json(self, **kwargs) -> Dict[str, Any]: **kwargs, ) - def __str__(self) -> str: - return self.format(compact=False, verbose=True) - def __eq__(self, other: Any) -> bool: if self is other: return True