| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| |
| """Tests for decorators module with Python 3 syntax not supported by 2.7.""" |
| |
| from __future__ import absolute_import |
| |
| import unittest |
| |
| from apache_beam.typehints import Any |
| from apache_beam.typehints import Dict |
| from apache_beam.typehints import List |
| from apache_beam.typehints import Tuple |
| from apache_beam.typehints import TypeVariable |
| from apache_beam.typehints import decorators |
| |
| decorators._enable_from_callable = True |
| T = TypeVariable('T') |
| |
| |
| class IOTypeHintsTest(unittest.TestCase): |
| |
| def test_from_callable(self): |
| def fn(a: int, b: str = None, *args: Tuple[T], foo: List[int], |
| **kwargs: Dict[str, str]) -> Tuple: |
| return a, b, args, foo, kwargs |
| th = decorators.IOTypeHints.from_callable(fn) |
| self.assertEqual(th.input_types, ( |
| (int, str, Tuple[T]), {'foo': List[int], 'kwargs': Dict[str, str]})) |
| self.assertEqual(th.output_types, ((Tuple,), {})) |
| |
| def test_from_callable_partial_annotations(self): |
| def fn(a: int, b=None, *args, foo: List[int], **kwargs): |
| return a, b, args, foo, kwargs |
| th = decorators.IOTypeHints.from_callable(fn) |
| self.assertEqual(th.input_types, |
| ((int, Any, Tuple[Any, ...]), |
| {'foo': List[int], 'kwargs': Dict[Any, Any]})) |
| self.assertEqual(th.output_types, ((Any,), {})) |
| |
| def test_from_callable_class(self): |
| class Class(object): |
| def __init__(self, unused_arg: int): |
| pass |
| |
| th = decorators.IOTypeHints.from_callable(Class) |
| self.assertEqual(th.input_types, ((int,), {})) |
| self.assertEqual(th.output_types, ((Class,), {})) |
| |
| def test_from_callable_method(self): |
| class Class(object): |
| def method(self, arg: T = None) -> None: |
| pass |
| |
| th = decorators.IOTypeHints.from_callable(Class.method) |
| self.assertEqual(th.input_types, ((Any, T), {})) |
| self.assertEqual(th.output_types, ((None,), {})) |
| |
| th = decorators.IOTypeHints.from_callable(Class().method) |
| self.assertEqual(th.input_types, ((T,), {})) |
| self.assertEqual(th.output_types, ((None,), {})) |
| |
| def test_getcallargs_forhints(self): |
| def fn(a: int, b: str = None, *args: Tuple[T], foo: List[int], |
| **kwargs: Dict[str, str]) -> Tuple: |
| return a, b, args, foo, kwargs |
| callargs = decorators.getcallargs_forhints(fn, float, foo=List[str]) |
| self.assertDictEqual(callargs, |
| {'a': float, |
| 'b': str, |
| 'args': Tuple[T], |
| 'foo': List[str], |
| 'kwargs': Dict[str, str]}) |
| |
| def test_getcallargs_forhints_default_arg(self): |
| # Default args are not necessarily types, so they should be ignored. |
| def fn(a=List[int], b=None, *args, foo=(), **kwargs) -> Tuple: |
| return a, b, args, foo, kwargs |
| callargs = decorators.getcallargs_forhints(fn) |
| self.assertDictEqual(callargs, |
| {'a': Any, |
| 'b': Any, |
| 'args': Tuple[Any, ...], |
| 'foo': Any, |
| 'kwargs': Dict[Any, Any]}) |
| |
| def test_getcallargs_forhints_missing_arg(self): |
| def fn(a, b=None, *args, foo, **kwargs): |
| return a, b, args, foo, kwargs |
| |
| with self.assertRaisesRegexp(decorators.TypeCheckError, "missing.*'a'"): |
| decorators.getcallargs_forhints(fn, foo=List[int]) |
| with self.assertRaisesRegexp(decorators.TypeCheckError, "missing.*'foo'"): |
| decorators.getcallargs_forhints(fn, 5) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |