Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove unified repr #4

Merged
merged 2 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions sdks/python/apache_beam/runners/interactive/sql/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ def pformat_namedtuple(schema: NamedTuple) -> str:
return '{}({})'.format(
schema.__name__,
', '.join([
'{}: {}'.format(k, v.__name__ if hasattr(v, '__name__') else repr(v))
for k,
'{}: {}'.format(k, repr(v)) for k,
v in schema.__annotations__.items()
]))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ def convert_to_beam_type(typ):
# TODO(https://github.com/apache/beam/issues/19954): Currently unhandled.
_LOGGER.info('Converting string literal type hint to Any: "%s"', typ)
return typehints.Any
elif sys.version_info >= (3, 10) and isinstance(typ, typing.NewType): # pylint: disable=isinstance-second-argument-not-valid-type
# Special case for NewType, where, since Python 3.10, NewType is now a class
# rather than a function.
# TODO(https://github.com/apache/beam/issues/20076): Currently unhandled.
_LOGGER.info('Converting NewType type hint to Any: "%s"', typ)
return typehints.Any
elif getattr(typ, '__module__', None) != 'typing':
# Only translate types from the typing module.
return typ
Expand Down
3 changes: 1 addition & 2 deletions sdks/python/apache_beam/typehints/row_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@ def __hash__(self):

def __repr__(self):
return 'Row(%s)' % ', '.join(
'%s=%s' % (name, typehints._unified_repr(t)) for name,
t in self._fields)
'%s=%s' % (name, repr(t)) for name, t in self._fields)

def get_type_for(self, name):
return dict(self._fields)[name]
Expand Down
8 changes: 3 additions & 5 deletions sdks/python/apache_beam/typehints/sharded_key_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ def type_check(self, instance):
raise typehints.CompositeTypeHintError(
"%s type-constraint violated. The type of key in 'ShardedKey' "
"is incorrect. Expected an instance of type '%s', "
"instead received an instance of type '%s'." % (
repr(self),
typehints._unified_repr(self.key_type),
instance.key.__class__.__name__))
"instead received an instance of type '%s'." %
(repr(self), repr(self.key_type), instance.key.__class__.__name__))

def match_type_variables(self, concrete_type):
if isinstance(concrete_type, ShardedKeyTypeConstraint):
Expand All @@ -80,7 +78,7 @@ def __hash__(self):
return hash(self.key_type)

def __repr__(self):
return 'ShardedKey[%s]' % typehints._unified_repr(self.key_type)
return 'ShardedKey[%s]' % repr(self.key_type)


ShardedKeyType = ShardedKeyTypeConstraint
Expand Down
8 changes: 4 additions & 4 deletions sdks/python/apache_beam/typehints/sharded_key_type_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_compatibility(self):

def test_repr(self):
constraint = ShardedKeyType[int]
self.assertEqual('ShardedKey[int]', repr(constraint))
self.assertEqual('ShardedKey[<class \'int\'>]', repr(constraint))

def test_type_check_not_sharded_key(self):
constraint = ShardedKeyType[int]
Expand All @@ -55,9 +55,9 @@ def test_type_check_invalid_key_type(self):
with self.assertRaises((TypeError, TypeError)) as e:
constraint.type_check(obj)
self.assertEqual(
"ShardedKey[int] type-constraint violated. The type of key in "
"'ShardedKey' is incorrect. Expected an instance of type 'int', "
"instead received an instance of type 'str'.",
"ShardedKey[<class \'int\'>] type-constraint violated. The type of key "
"in 'ShardedKey' is incorrect. Expected an instance of type \'<class "
"\'int\'>\', instead received an instance of type 'str'.",
e.exception.args[0])

def test_type_check_valid_simple_type(self):
Expand Down
6 changes: 3 additions & 3 deletions sdks/python/apache_beam/typehints/typecheck_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,9 @@ def is_even_as_key(a):
e.exception.args[0],
"Runtime type violation detected within ParDo(IsEven): "
"Type-hint for return type violated: "
"Tuple[bool, int] hint type-constraint violated. "
"The type of element #0 in the passed tuple is incorrect. "
"Expected an instance of type bool, "
"Tuple[<class \'bool\'>, <class \'int\'>] hint type-constraint "
"violated. The type of element #0 in the passed tuple is incorrect. "
"Expected an instance of type <class \'bool\'>, "
"instead received an instance of type int. ")

def test_pipeline_runtime_checking_violation_composite_type_output(self):
Expand Down
20 changes: 12 additions & 8 deletions sdks/python/apache_beam/typehints/typed_pipeline_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,14 @@ def process(self, element: int) -> typehints.Tuple[str]:
result = [(1, 2)] | beam.ParDo(MyDoFn())
self.assertEqual([1], sorted(result))

with self.assertRaisesRegex(typehints.TypeCheckError,
r'requires.*Tuple\[int, int\].*got.*str'):
with self.assertRaisesRegex(
typehints.TypeCheckError,
r'requires.*Tuple\[<class \'int\'>, <class \'int\'>\].*got.*str'):
_ = ['a', 'b', 'c'] | beam.ParDo(MyDoFn())

with self.assertRaisesRegex(typehints.TypeCheckError,
r'requires.*Tuple\[int, int\].*got.*int'):
with self.assertRaisesRegex(
typehints.TypeCheckError,
r'requires.*Tuple\[<class \'int\'>, <class \'int\'>\].*got.*int'):
_ = [1, 2, 3] | (beam.ParDo(MyDoFn()) | 'again' >> beam.ParDo(MyDoFn()))

def test_typed_callable_iterable_output(self):
Expand Down Expand Up @@ -745,7 +747,8 @@ def repeat(s, *times):

with self.assertRaisesRegex(
typehints.TypeCheckError,
r'requires Tuple\[int, ...\] but got Tuple\[str, ...\]'):
(r'requires Tuple\[<class \'int\'>, ...\] but got '
r'Tuple\[<class \'str\'>, ...\]')):
['a', 'bb', 'c'] | beam.Map(repeat, 'z')

def test_var_positional_only_side_input_hint(self):
Expand All @@ -762,8 +765,8 @@ def test_var_positional_only_side_input_hint(self):

with self.assertRaisesRegex(
typehints.TypeCheckError,
r'requires Tuple\[Union\[int, str\], ...\] but got '
r'Tuple\[Union\[float, int\], ...\]'):
r'requires Tuple\[Union\[<class \'int\'>, <class \'str\'>\], ...\] but '
r'got Tuple\[Union\[<class \'float\'>, <class \'int\'>\], ...\]'):
_ = [1.2] | beam.Map(lambda *_: 'a', 5).with_input_types(int, str)

def test_var_keyword_side_input_hint(self):
Expand All @@ -783,7 +786,8 @@ def test_var_keyword_side_input_hint(self):

with self.assertRaisesRegex(
typehints.TypeCheckError,
r'requires Dict\[str, str\] but got Dict\[str, int\]'):
r'requires Dict\[<class \'str\'>, <class \'str\'>\] but got '
r'Dict\[<class \'str\'>, <class \'int\'>\]'):
_ = (['a', 'b', 'c']
| beam.Map(lambda e, **_: 'a', kw=5).with_input_types(
str, ignored=str))
Expand Down
66 changes: 19 additions & 47 deletions sdks/python/apache_beam/typehints/typehints.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ def type_check(self, sequence_instance):
'instead received an instance of type %s.' % (
repr(self),
index,
_unified_repr(self._sequence_type),
_unified_repr(self.inner_type),
repr(self._sequence_type),
repr(self.inner_type),
elem.__class__.__name__))
except CompositeTypeHintError as e:
raise CompositeTypeHintError(
Expand Down Expand Up @@ -394,27 +394,6 @@ def validate_composite_type_param(type_param, error_msg_prefix):
(error_msg_prefix, type_param, type_param.__class__.__name__))


# TODO(https://github.com/apache/beam/issues/20982): Remove this function and
# use plain repr() instead.
def _unified_repr(o):
"""Given an object return a qualified name for the object.

This function closely mirrors '__qualname__' which was introduced in
Python 3.3. It is used primarily to format types or object instances for
error messages.

Args:
o: An instance of a TypeConstraint or a type.

Returns:
A qualified name for the passed Python object fit for string formatting.
"""
if isinstance(o, (TypeConstraint, type(None))) or not hasattr(o, '__name__'):
return repr(o)
else:
return o.__name__


def check_constraint(type_constraint, object_instance):
"""Determine if the passed type instance satisfies the TypeConstraint.

Expand Down Expand Up @@ -533,7 +512,7 @@ def __hash__(self):
def __repr__(self):
# Sorting the type name strings simplifies unit tests.
return 'Union[%s]' % (
', '.join(sorted(_unified_repr(t) for t in self.union_types)))
', '.join(sorted(repr(t) for t in self.union_types)))

def inner_types(self):
for t in self.union_types:
Expand Down Expand Up @@ -565,7 +544,7 @@ def type_check(self, instance):
'%s type-constraint violated. Expected an instance of one of: %s, '
'received %s instead.%s' % (
repr(self),
tuple(sorted(_unified_repr(t) for t in self.union_types)),
tuple(sorted(repr(t) for t in self.union_types)),
instance.__class__.__name__,
error_msg))

Expand Down Expand Up @@ -673,7 +652,7 @@ def __init__(self, type_param):
super().__init__(type_param, tuple)

def __repr__(self):
return 'Tuple[%s, ...]' % _unified_repr(self.inner_type)
return 'Tuple[%s, ...]' % repr(self.inner_type)

def _consistent_with_check_(self, sub):
if isinstance(sub, TupleConstraint):
Expand All @@ -696,8 +675,7 @@ def __hash__(self):
return hash(self.tuple_types)

def __repr__(self):
return 'Tuple[%s]' % (
', '.join(_unified_repr(t) for t in self.tuple_types))
return 'Tuple[%s]' % (', '.join(repr(t) for t in self.tuple_types))

def _inner_types(self):
for t in self.tuple_types:
Expand Down Expand Up @@ -737,11 +715,8 @@ def type_check(self, tuple_instance):
raise CompositeTypeHintError(
'%s hint type-constraint violated. The type of element #%s in '
'the passed tuple is incorrect. Expected an instance of '
'type %s, instead received an instance of type %s.' % (
repr(self),
type_pos,
_unified_repr(expected),
actual.__class__.__name__))
'type %s, instead received an instance of type %s.' %
(repr(self), type_pos, repr(expected), actual.__class__.__name__))
except CompositeTypeHintError as e:
raise CompositeTypeHintError(
'%s hint type-constraint violated. The type of element #%s in '
Expand Down Expand Up @@ -805,7 +780,7 @@ def __init__(self, list_type):
super().__init__(list_type, list)

def __repr__(self):
return 'List[%s]' % _unified_repr(self.inner_type)
return 'List[%s]' % repr(self.inner_type)

def __getitem__(self, t):
validate_composite_type_param(t, error_msg_prefix='Parameter to List hint')
Expand Down Expand Up @@ -864,8 +839,7 @@ def __init__(self, key_type, value_type):
self.value_type = normalize(value_type)

def __repr__(self):
return 'Dict[%s, %s]' % (
_unified_repr(self.key_type), _unified_repr(self.value_type))
return 'Dict[%s, %s]' % (repr(self.key_type), repr(self.value_type))

def __eq__(self, other):
return (
Expand Down Expand Up @@ -896,7 +870,7 @@ def _raise_hint_exception_or_inner_exception(
repr(self),
incorrect_type[:-1],
incorrect_type,
_unified_repr(hinted_type),
repr(hinted_type),
inner_error_message))
else:
raise CompositeTypeHintError(
Expand All @@ -905,7 +879,7 @@ def _raise_hint_exception_or_inner_exception(
repr(self),
incorrect_type[:-1],
incorrect_type,
_unified_repr(hinted_type),
repr(hinted_type),
incorrect_instance,
incorrect_instance.__class__.__name__))

Expand Down Expand Up @@ -986,7 +960,7 @@ def __init__(self, type_param):
super().__init__(type_param, set)

def __repr__(self):
return 'Set[%s]' % _unified_repr(self.inner_type)
return 'Set[%s]' % repr(self.inner_type)

def __getitem__(self, type_param):
validate_composite_type_param(
Expand All @@ -1012,7 +986,7 @@ def __init__(self, type_param):
self).__init__(type_param, frozenset)

def __repr__(self):
return 'FrozenSet[%s]' % _unified_repr(self.inner_type)
return 'FrozenSet[%s]' % repr(self.inner_type)

def __getitem__(self, type_param):
validate_composite_type_param(
Expand All @@ -1036,7 +1010,7 @@ def __init__(self, iter_type):
self).__init__(iter_type, abc.Iterable)

def __repr__(self):
return 'Iterable[%s]' % _unified_repr(self.inner_type)
return 'Iterable[%s]' % repr(self.inner_type)

def _consistent_with_check_(self, sub):
if isinstance(sub, SequenceTypeConstraint):
Expand Down Expand Up @@ -1077,7 +1051,7 @@ def __init__(self, t):
self.yielded_type = normalize(t)

def __repr__(self):
return 'Iterator[%s]' % _unified_repr(self.yielded_type)
return 'Iterator[%s]' % repr(self.yielded_type)

def __eq__(self, other):
return (
Expand Down Expand Up @@ -1106,10 +1080,8 @@ def type_check(self, instance):
except SimpleTypeHintError:
raise CompositeTypeHintError(
'%s hint type-constraint violated. Expected a iterator of type %s. '
'Instead received a iterator of type %s.' % (
repr(self),
_unified_repr(self.yielded_type),
instance.__class__.__name__))
'Instead received a iterator of type %s.' %
(repr(self), repr(self.yielded_type), instance.__class__.__name__))

def __getitem__(self, type_param):
validate_composite_type_param(
Expand Down Expand Up @@ -1164,7 +1136,7 @@ def type_check(self, instance):
'is incorrect. Expected an instance of type %s, '
'instead received an instance of type %s.' % (
repr(self),
_unified_repr(self.inner_type),
repr(self.inner_type),
instance.value.__class__.__name__))


Expand Down
Loading