From 8c5f509610896d4e70c9d42f762ae7e3231a91d1 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 10:11:51 +0000 Subject: [PATCH 01/24] Added a test to check for type information. --- tools/ci_build/verify/check_typing_info.py | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tools/ci_build/verify/check_typing_info.py diff --git a/tools/ci_build/verify/check_typing_info.py b/tools/ci_build/verify/check_typing_info.py new file mode 100644 index 0000000000..ee0a2465ea --- /dev/null +++ b/tools/ci_build/verify/check_typing_info.py @@ -0,0 +1,70 @@ +# Copyright 2019 The TensorFlow Authors. All Rights Reserved. +# +# Licensed 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. +# ============================================================================== +# +from types import ModuleType +import inspect + +import tensorflow_addons + +EXAMPLE_URL = 'https://github.com/tensorflow/addons/blob/fa8e966d987fd9b0d20551a666e44e2790fdf9c7/tensorflow_addons/layers/normalizations.py#L73' +TUTORIAL_URL = 'https://docs.python.org/3/library/typing.html' + + +def check_public_api_has_typing_information(): + for attribute in get_attributes(tensorflow_addons): + if isinstance(attribute, ModuleType): + check_module_is_typed(attribute) + + +def check_module_is_typed(module): + for attribute in get_attributes(module): + if inspect.isclass(attribute): + check_function_is_typed(attribute.__init__, class_=attribute) + if inspect.isfunction(attribute): + check_function_is_typed(attribute) + + +def check_function_is_typed(func, class_=None): + """ If class_ is not None, func is the __init__ of the class.""" + list_args = inspect.getfullargspec(func).args + if class_ is not None: + list_args.pop(0) # we remove 'self' + if len(list_args) != len(func.__annotations__): + if class_ is None: + function_name = func.__name__ + else: + function_name = class_.__name__ + '.__init__' + raise NotImplementedError( + "The function {} has not complete type annotations " + "in its signature. We would like all the functions and " + "class constructors in the public API to be typed and have " + "the typechecked decorator. \n" + "If you are not familiar with adding type hints in " + "functions, you can look at functions already typed in" + "the codebase. For example: {}. \n" + "You can also look at this tutorial: {}.".format(function_name, + EXAMPLE_URL, + TUTORIAL_URL) + ) + + +def get_attributes(module): + for attr_name in dir(module): + attr = getattr(module, attr_name) + yield attr + + +if __name__ == '__main__': + check_public_api_has_typing_information() \ No newline at end of file From f144705cb6a7481e8a12a0e72dcecfdac702b54c Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 11:07:06 +0000 Subject: [PATCH 02/24] It works, it just needs an exception list. --- tensorflow_addons/activations/gelu.py | 6 +++- tensorflow_addons/utils/types.py | 7 ++++- tools/ci_build/verify/check_typing_info.py | 35 +++++++++++++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/tensorflow_addons/activations/gelu.py b/tensorflow_addons/activations/gelu.py index eb2fb3f10f..7882a77189 100644 --- a/tensorflow_addons/activations/gelu.py +++ b/tensorflow_addons/activations/gelu.py @@ -14,13 +14,17 @@ # ============================================================================== import tensorflow as tf +from typeguard import typechecked + +from tensorflow_addons.utils import types from tensorflow_addons.utils.resource_loader import LazySO _activation_so = LazySO("custom_ops/activations/_activation_ops.so") @tf.keras.utils.register_keras_serializable(package='Addons') -def gelu(x, approximate=True): +@typechecked +def gelu(x: types.TensorLike, approximate: bool = True): """Gaussian Error Linear Unit. Computes gaussian error linear: diff --git a/tensorflow_addons/utils/types.py b/tensorflow_addons/utils/types.py index 8b0ffbe1c0..ecd2495aa3 100644 --- a/tensorflow_addons/utils/types.py +++ b/tensorflow_addons/utils/types.py @@ -14,8 +14,13 @@ # ============================================================================== """Types for typing functions signatures.""" -from typing import Union, Callable +from typing import Union, Callable, List + +import numpy as np +import tensorflow as tf Initializer = Union[None, dict, str, Callable] Regularizer = Union[None, dict, str, Callable] Constraint = Union[None, dict, str, Callable] + +TensorLike = Union[List[Union[float, int]], np.ndarray, tf.Tensor] diff --git a/tools/ci_build/verify/check_typing_info.py b/tools/ci_build/verify/check_typing_info.py index ee0a2465ea..f44db12364 100644 --- a/tools/ci_build/verify/check_typing_info.py +++ b/tools/ci_build/verify/check_typing_info.py @@ -38,19 +38,20 @@ def check_module_is_typed(module): def check_function_is_typed(func, class_=None): """ If class_ is not None, func is the __init__ of the class.""" + func = inspect.unwrap(func) # if the real function is hidden behind a decorator. list_args = inspect.getfullargspec(func).args if class_ is not None: list_args.pop(0) # we remove 'self' - if len(list_args) != len(func.__annotations__): + if len(list_args) != len(get_list_of_annotated_args(func)): if class_ is None: function_name = func.__name__ else: function_name = class_.__name__ + '.__init__' - raise NotImplementedError( - "The function {} has not complete type annotations " + raise NotTypedError( + "The function '{}' has not complete type annotations " "in its signature. We would like all the functions and " "class constructors in the public API to be typed and have " - "the typechecked decorator. \n" + "the @typechecked decorator. \n" "If you are not familiar with adding type hints in " "functions, you can look at functions already typed in" "the codebase. For example: {}. \n" @@ -59,6 +60,28 @@ def check_function_is_typed(func, class_=None): TUTORIAL_URL) ) + if class_ is None: + check_return_type(func) + + +def check_return_type(func): + if 'return' not in func.__annotations__: + raise NotTypedError( + 'The function {} has no return type. Please add one. ' + 'You can take a look at the gelu activation function ' + 'in tensorflow_addons/activations/gelu.py ' + 'if you want an example.'.format(func.__name__) + ) + + +def get_list_of_annotated_args(func): + args_with_annotations = list(func.__annotations__.keys()) + try: + args_with_annotations.remove('return') + except ValueError: + pass + return args_with_annotations + def get_attributes(module): for attr_name in dir(module): @@ -66,5 +89,9 @@ def get_attributes(module): yield attr +class NotTypedError(Exception): + pass + + if __name__ == '__main__': check_public_api_has_typing_information() \ No newline at end of file From 6a42b45f181437e933ad4bc1bf0613a52fdb991b Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 11:07:38 +0000 Subject: [PATCH 03/24] Added return type. --- tensorflow_addons/activations/gelu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow_addons/activations/gelu.py b/tensorflow_addons/activations/gelu.py index 7882a77189..426f9d76e3 100644 --- a/tensorflow_addons/activations/gelu.py +++ b/tensorflow_addons/activations/gelu.py @@ -24,7 +24,7 @@ @tf.keras.utils.register_keras_serializable(package='Addons') @typechecked -def gelu(x: types.TensorLike, approximate: bool = True): +def gelu(x: types.TensorLike, approximate: bool = True) -> tf.Tensor: """Gaussian Error Linear Unit. Computes gaussian error linear: From 038c1a539a44175b2f9012dddd3f432f6522d641 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 11:30:57 +0000 Subject: [PATCH 04/24] Added the exception list. --- tools/ci_build/verify/check_typing_info.py | 119 +++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/tools/ci_build/verify/check_typing_info.py b/tools/ci_build/verify/check_typing_info.py index f44db12364..5dcccfbd05 100644 --- a/tools/ci_build/verify/check_typing_info.py +++ b/tools/ci_build/verify/check_typing_info.py @@ -22,6 +22,123 @@ TUTORIAL_URL = 'https://docs.python.org/3/library/typing.html' +# TODO: add types and remove all elements from +# the exception list. +EXCEPTION_LIST = [ + tensorflow_addons.activations.hardshrink, + tensorflow_addons.activations.lisht, + tensorflow_addons.activations.mish, + tensorflow_addons.activations.tanhshrink, + tensorflow_addons.activations.sparsemax, + tensorflow_addons.activations.softshrink, + tensorflow_addons.activations.rrelu, + tensorflow_addons.callbacks.TQDMProgressBar, + tensorflow_addons.callbacks.TimeStopping, + tensorflow_addons.image.connected_components, + tensorflow_addons.image.dense_image_warp, + tensorflow_addons.image.interpolate_bilinear, + tensorflow_addons.image.euclidean_dist_transform, + tensorflow_addons.image.adjust_hsv_in_yiq, + tensorflow_addons.image.random_hsv_in_yiq, + tensorflow_addons.image.mean_filter2d, + tensorflow_addons.image.median_filter2d, + tensorflow_addons.image.interpolate_spline, + tensorflow_addons.image.resampler, + tensorflow_addons.image.sparse_image_warp, + tensorflow_addons.image.rotate, + tensorflow_addons.image.transform, + tensorflow_addons.image.translate, + tensorflow_addons.layers.GELU, + tensorflow_addons.layers.Maxout, + tensorflow_addons.layers.GroupNormalization, + tensorflow_addons.layers.InstanceNormalization, + tensorflow_addons.layers.CorrelationCost, + tensorflow_addons.layers.PoincareNormalize, + tensorflow_addons.layers.Sparsemax, + tensorflow_addons.layers.TLU, + tensorflow_addons.layers.WeightNormalization, + tensorflow_addons.losses.contrastive_loss, + tensorflow_addons.losses.sigmoid_focal_crossentropy, + tensorflow_addons.losses.giou_loss, + tensorflow_addons.losses.lifted_struct_loss, + tensorflow_addons.losses.sparsemax_loss, + tensorflow_addons.losses.triplet_semihard_loss, + tensorflow_addons.losses.pinball_loss, + tensorflow_addons.losses.PinballLoss, + tensorflow_addons.losses.ContrastiveLoss, + tensorflow_addons.losses.SigmoidFocalCrossEntropy, + tensorflow_addons.losses.GIoULoss, + tensorflow_addons.losses.LiftedStructLoss, + tensorflow_addons.losses.SparsemaxLoss, + tensorflow_addons.losses.TripletSemiHardLoss, + tensorflow_addons.losses.npairs_loss, + tensorflow_addons.losses.NpairsLoss, + tensorflow_addons.losses.npairs_multilabel_loss, + tensorflow_addons.losses.NpairsMultilabelLoss, + tensorflow_addons.metrics.CohenKappa, + tensorflow_addons.metrics.F1Score, + tensorflow_addons.metrics.FBetaScore, + tensorflow_addons.metrics.HammingLoss, + tensorflow_addons.metrics.hamming_distance, + tensorflow_addons.metrics.MeanMetricWrapper, + tensorflow_addons.metrics.MatthewsCorrelationCoefficient, + tensorflow_addons.metrics.MultiLabelConfusionMatrix, + tensorflow_addons.metrics.RSquare, + tensorflow_addons.optimizers.AveragedOptimizerWrapper, + tensorflow_addons.optimizers.ConditionalGradient, + tensorflow_addons.optimizers.CyclicalLearningRate, + tensorflow_addons.optimizers.TriangularCyclicalLearningRate, + tensorflow_addons.optimizers.Triangular2CyclicalLearningRate, + tensorflow_addons.optimizers.ExponentialCyclicalLearningRate, + tensorflow_addons.optimizers.LAMB, + tensorflow_addons.optimizers.LazyAdam, + tensorflow_addons.optimizers.Lookahead, + tensorflow_addons.optimizers.MovingAverage, + tensorflow_addons.optimizers.NovoGrad, + tensorflow_addons.optimizers.RectifiedAdam, + tensorflow_addons.optimizers.SWA, + tensorflow_addons.optimizers.AdamW, + tensorflow_addons.optimizers.SGDW, + tensorflow_addons.optimizers.extend_with_decoupled_weight_decay, + tensorflow_addons.optimizers.Yogi, + tensorflow_addons.rnn.LayerNormLSTMCell, + tensorflow_addons.rnn.NASCell, + tensorflow_addons.seq2seq.AttentionMechanism, + tensorflow_addons.seq2seq.AttentionWrapper, + tensorflow_addons.seq2seq.AttentionWrapperState, + tensorflow_addons.seq2seq.BahdanauAttention, + tensorflow_addons.seq2seq.BahdanauMonotonicAttention, + tensorflow_addons.seq2seq.LuongAttention, + tensorflow_addons.seq2seq.LuongMonotonicAttention, + tensorflow_addons.seq2seq.hardmax, + tensorflow_addons.seq2seq.monotonic_attention, + tensorflow_addons.seq2seq.safe_cumprod, + tensorflow_addons.seq2seq.BasicDecoder, + tensorflow_addons.seq2seq.BasicDecoderOutput, + tensorflow_addons.seq2seq.BeamSearchDecoder, + tensorflow_addons.seq2seq.BeamSearchDecoderOutput, + tensorflow_addons.seq2seq.BeamSearchDecoderState, + tensorflow_addons.seq2seq.FinalBeamSearchDecoderOutput, + tensorflow_addons.seq2seq.gather_tree, + tensorflow_addons.seq2seq.gather_tree_from_array, + tensorflow_addons.seq2seq.tile_batch, + tensorflow_addons.seq2seq.BaseDecoder, + tensorflow_addons.seq2seq.Decoder, + tensorflow_addons.seq2seq.dynamic_decode, + tensorflow_addons.seq2seq.SequenceLoss, + tensorflow_addons.seq2seq.sequence_loss, + tensorflow_addons.seq2seq.CustomSampler, + tensorflow_addons.seq2seq.GreedyEmbeddingSampler, + tensorflow_addons.seq2seq.InferenceSampler, + tensorflow_addons.seq2seq.SampleEmbeddingSampler, + tensorflow_addons.seq2seq.Sampler, + tensorflow_addons.seq2seq.ScheduledEmbeddingTrainingSampler, + tensorflow_addons.seq2seq.ScheduledOutputTrainingSampler, + #tensorflow_addons.seq2seq.TrainingSampler, + tensorflow_addons.text.parse_time, +] + + def check_public_api_has_typing_information(): for attribute in get_attributes(tensorflow_addons): if isinstance(attribute, ModuleType): @@ -30,6 +147,8 @@ def check_public_api_has_typing_information(): def check_module_is_typed(module): for attribute in get_attributes(module): + if attribute in EXCEPTION_LIST: + continue if inspect.isclass(attribute): check_function_is_typed(attribute.__init__, class_=attribute) if inspect.isfunction(attribute): From 912de0bf230d0fb0435040ff17031f4110554708 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 12:16:44 +0000 Subject: [PATCH 05/24] Using the signature is cleaner. --- tools/ci_build/verify/check_typing_info.py | 41 ++++++++++++++-------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/tools/ci_build/verify/check_typing_info.py b/tools/ci_build/verify/check_typing_info.py index 5dcccfbd05..966005e939 100644 --- a/tools/ci_build/verify/check_typing_info.py +++ b/tools/ci_build/verify/check_typing_info.py @@ -134,7 +134,20 @@ tensorflow_addons.seq2seq.Sampler, tensorflow_addons.seq2seq.ScheduledEmbeddingTrainingSampler, tensorflow_addons.seq2seq.ScheduledOutputTrainingSampler, - #tensorflow_addons.seq2seq.TrainingSampler, + tensorflow_addons.seq2seq.TrainingSampler, + tensorflow_addons.text.crf_binary_score, + tensorflow_addons.text.crf_decode, + tensorflow_addons.text.crf_decode_backward, + tensorflow_addons.text.crf_decode_forward, + tensorflow_addons.text.crf_forward, + tensorflow_addons.text.crf_log_likelihood, + tensorflow_addons.text.crf_log_norm, + tensorflow_addons.text.crf_multitag_sequence_score, + tensorflow_addons.text.crf_sequence_score, + tensorflow_addons.text.crf_unary_score, + tensorflow_addons.text.viterbi_decode, + tensorflow_addons.text.skip_gram_sample, + #tensorflow_addons.text.skip_gram_sample_with_text_vocab, tensorflow_addons.text.parse_time, ] @@ -157,34 +170,32 @@ def check_module_is_typed(module): def check_function_is_typed(func, class_=None): """ If class_ is not None, func is the __init__ of the class.""" - func = inspect.unwrap(func) # if the real function is hidden behind a decorator. - list_args = inspect.getfullargspec(func).args - if class_ is not None: - list_args.pop(0) # we remove 'self' - if len(list_args) != len(get_list_of_annotated_args(func)): + signature = inspect.signature(func) + for parameter_name, parameter in signature.parameters.items(): + if parameter.annotation != inspect.Signature.empty: + continue + if parameter_name in ('args', 'kwargs', 'self'): + continue if class_ is None: function_name = func.__name__ else: function_name = class_.__name__ + '.__init__' raise NotTypedError( "The function '{}' has not complete type annotations " - "in its signature. We would like all the functions and " + "in its signature (it's missing type hind for '{}'). " + "We would like all the functions and " "class constructors in the public API to be typed and have " "the @typechecked decorator. \n" "If you are not familiar with adding type hints in " "functions, you can look at functions already typed in" "the codebase. For example: {}. \n" - "You can also look at this tutorial: {}.".format(function_name, - EXAMPLE_URL, - TUTORIAL_URL) + "You can also look at this tutorial: " + "{}.".format(function_name, parameter_name, EXAMPLE_URL, TUTORIAL_URL) ) if class_ is None: - check_return_type(func) - - -def check_return_type(func): - if 'return' not in func.__annotations__: + if signature.return_annotation != inspect.Signature.empty: + return raise NotTypedError( 'The function {} has no return type. Please add one. ' 'You can take a look at the gelu activation function ' From 0092ca948ef70a456bd14e55bb31e2ea95a843fa Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 12:25:58 +0000 Subject: [PATCH 06/24] Typechecked is not compatible with autograph. --- tensorflow_addons/activations/gelu.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow_addons/activations/gelu.py b/tensorflow_addons/activations/gelu.py index 426f9d76e3..4c4d84432a 100644 --- a/tensorflow_addons/activations/gelu.py +++ b/tensorflow_addons/activations/gelu.py @@ -23,6 +23,7 @@ @tf.keras.utils.register_keras_serializable(package='Addons') +@tf.autograph.experimental.do_not_convert @typechecked def gelu(x: types.TensorLike, approximate: bool = True) -> tf.Tensor: """Gaussian Error Linear Unit. From 4a45358198e3a940099f0da4695aae951a200b1d Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 12:33:54 +0000 Subject: [PATCH 07/24] Added the github actions step. --- .github/workflows/ci_test.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 2262a40486..3fd60f2ca8 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -66,3 +66,13 @@ jobs: run: | set -x -e bash tools/run_docker.sh -c 'make sanity-check' + public-api-typed: + name: Check that the public API is typed + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-python@v1 + - name: install tensorflow + run: pip install tensorflow-cpu + - name: Run type check + run: python tools/ci_bulds/verify/check_typing_info.py From 0fc8cd64944702fd2eb4cd1a5aa2e3eb3246ef52 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 12:36:36 +0000 Subject: [PATCH 08/24] Added the python version. --- .github/workflows/ci_test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 3fd60f2ca8..33178b6f41 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -72,6 +72,8 @@ jobs: steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 + with: + python-version: '3.7' - name: install tensorflow run: pip install tensorflow-cpu - name: Run type check From e6ce2a14b3a7abef40bc7c77dc4e7a7d81402842 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 12:38:30 +0000 Subject: [PATCH 09/24] Typo --- .github/workflows/ci_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 33178b6f41..2e9becd8df 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -77,4 +77,4 @@ jobs: - name: install tensorflow run: pip install tensorflow-cpu - name: Run type check - run: python tools/ci_bulds/verify/check_typing_info.py + run: python tools/ci_buld/verify/check_typing_info.py From e82a203a1f0cac86d40264994e9eba6332714ddd Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 12:44:48 +0000 Subject: [PATCH 10/24] Typo. --- .github/workflows/ci_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 2e9becd8df..c7bdad95a8 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -77,4 +77,4 @@ jobs: - name: install tensorflow run: pip install tensorflow-cpu - name: Run type check - run: python tools/ci_buld/verify/check_typing_info.py + run: python tools/ci_build/verify/check_typing_info.py From 406090f9a407fe0a111903de4da57485bb347eeb Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 12:49:43 +0000 Subject: [PATCH 11/24] Install tf addons. --- .github/workflows/ci_test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index c7bdad95a8..1859fb40a3 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -76,5 +76,7 @@ jobs: python-version: '3.7' - name: install tensorflow run: pip install tensorflow-cpu + - name: install tf addons + run: pip install -e --no-deps . - name: Run type check run: python tools/ci_build/verify/check_typing_info.py From dced016af58931e3e7cb9f1f99e2aeac4663e770 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 12:57:00 +0000 Subject: [PATCH 12/24] Typo. --- .github/workflows/ci_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 1859fb40a3..e11c3506d8 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -77,6 +77,6 @@ jobs: - name: install tensorflow run: pip install tensorflow-cpu - name: install tf addons - run: pip install -e --no-deps . + run: pip install -e --no-deps . - name: Run type check run: python tools/ci_build/verify/check_typing_info.py From dfc46bc2c7b21c48d0fc4e3c64cb5f7455124c68 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 12:58:48 +0000 Subject: [PATCH 13/24] Arguments order. --- .github/workflows/ci_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index e11c3506d8..26e8862fa8 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -77,6 +77,6 @@ jobs: - name: install tensorflow run: pip install tensorflow-cpu - name: install tf addons - run: pip install -e --no-deps . + run: pip install --no-deps -e . - name: Run type check run: python tools/ci_build/verify/check_typing_info.py From 8958ebcd2eb7beddf4de4cb096007e1c485dfb5c Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 13:10:17 +0000 Subject: [PATCH 14/24] Added option to install tf-addons without building. --- .github/workflows/ci_test.yml | 2 +- setup.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 26e8862fa8..dce64bf428 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -77,6 +77,6 @@ jobs: - name: install tensorflow run: pip install tensorflow-cpu - name: install tf addons - run: pip install --no-deps -e . + run: TF_ADDONS_NO_BUILD=1 pip install --no-deps -e . - name: Run type check run: python tools/ci_build/verify/check_typing_info.py diff --git a/setup.py b/setup.py index 21eb3c9dff..b30e3bb85b 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,8 @@ else: project_name = TFA_RELEASE +build = () + # Version version = {} base_dir = os.path.dirname(os.path.abspath(__file__)) @@ -60,7 +62,7 @@ required_pkgs = f.read().splitlines() # Manylinux2010 requires a patch for platlib -if sys.platform.startswith('linux'): +if sys.platform.startswith('linux') and os.environ.get('TF_ADDONS_NO_BUILD', '0') =='0': ext_modules = [Extension('_foo', ['stub.cc'])] else: ext_modules = [] From aeba883c5dc22b4e1566b7fbf270f32c2e0ca097 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 13:12:20 +0000 Subject: [PATCH 15/24] typeguard. --- .github/workflows/ci_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index dce64bf428..aa91d5a68b 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -74,8 +74,8 @@ jobs: - uses: actions/setup-python@v1 with: python-version: '3.7' - - name: install tensorflow - run: pip install tensorflow-cpu + - name: install tensorflow and typeguard + run: pip install tensorflow-cpu typeguard - name: install tf addons run: TF_ADDONS_NO_BUILD=1 pip install --no-deps -e . - name: Run type check From 54dff521a50a853c0ab4096e055f43adba1b0513 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 13:17:20 +0000 Subject: [PATCH 16/24] Everything should work now. --- tools/ci_build/verify/check_typing_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci_build/verify/check_typing_info.py b/tools/ci_build/verify/check_typing_info.py index 966005e939..c292c0035e 100644 --- a/tools/ci_build/verify/check_typing_info.py +++ b/tools/ci_build/verify/check_typing_info.py @@ -147,7 +147,7 @@ tensorflow_addons.text.crf_unary_score, tensorflow_addons.text.viterbi_decode, tensorflow_addons.text.skip_gram_sample, - #tensorflow_addons.text.skip_gram_sample_with_text_vocab, + tensorflow_addons.text.skip_gram_sample_with_text_vocab, tensorflow_addons.text.parse_time, ] @@ -182,7 +182,7 @@ def check_function_is_typed(func, class_=None): function_name = class_.__name__ + '.__init__' raise NotTypedError( "The function '{}' has not complete type annotations " - "in its signature (it's missing type hind for '{}'). " + "in its signature (it's missing the type hint for '{}'). " "We would like all the functions and " "class constructors in the public API to be typed and have " "the @typechecked decorator. \n" From 6000d1f9a124b6fa22b5b079c1083cbc945500ff Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 13:19:38 +0000 Subject: [PATCH 17/24] Forgot to remove variable. --- setup.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/setup.py b/setup.py index b30e3bb85b..cdc02ee05f 100644 --- a/setup.py +++ b/setup.py @@ -45,8 +45,6 @@ else: project_name = TFA_RELEASE -build = () - # Version version = {} base_dir = os.path.dirname(os.path.abspath(__file__)) From d1009fa99162f624855ade929f2a944df4fbd1fa Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 13:30:18 +0000 Subject: [PATCH 18/24] More extensive about types. --- tensorflow_addons/utils/types.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tensorflow_addons/utils/types.py b/tensorflow_addons/utils/types.py index ecd2495aa3..5e5f516979 100644 --- a/tensorflow_addons/utils/types.py +++ b/tensorflow_addons/utils/types.py @@ -19,8 +19,23 @@ import numpy as np import tensorflow as tf + +Number = Union[float, + int, + np.float16, + np.float32, + np.float64, + np.int8, + np.int16, + np.int32, + np.int64, + np.uint8, + np.uint16, + np.uint32, + np.uint64] + Initializer = Union[None, dict, str, Callable] Regularizer = Union[None, dict, str, Callable] Constraint = Union[None, dict, str, Callable] -TensorLike = Union[List[Union[float, int]], np.ndarray, tf.Tensor] +TensorLike = Union[List[Union[Number, list]], Number, np.ndarray, tf.Tensor] From aebc685d04a8199ac496f984ee0578a0c8059f41 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 13:43:50 +0000 Subject: [PATCH 19/24] Unused function. --- tools/ci_build/verify/check_typing_info.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tools/ci_build/verify/check_typing_info.py b/tools/ci_build/verify/check_typing_info.py index c292c0035e..cc2dc8438e 100644 --- a/tools/ci_build/verify/check_typing_info.py +++ b/tools/ci_build/verify/check_typing_info.py @@ -204,15 +204,6 @@ def check_function_is_typed(func, class_=None): ) -def get_list_of_annotated_args(func): - args_with_annotations = list(func.__annotations__.keys()) - try: - args_with_annotations.remove('return') - except ValueError: - pass - return args_with_annotations - - def get_attributes(module): for attr_name in dir(module): attr = getattr(module, attr_name) From 0ef5d0ae381a979cd2a8ea8b9f2cd9af3d9c64a9 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Fri, 24 Jan 2020 17:30:09 +0000 Subject: [PATCH 20/24] Typing gelu. --- .github/workflows/ci_test.yml | 14 -- setup.py | 2 +- tools/ci_build/verify/check_typing_info.py | 218 --------------------- 3 files changed, 1 insertion(+), 233 deletions(-) delete mode 100644 tools/ci_build/verify/check_typing_info.py diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index aa91d5a68b..2262a40486 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -66,17 +66,3 @@ jobs: run: | set -x -e bash tools/run_docker.sh -c 'make sanity-check' - public-api-typed: - name: Check that the public API is typed - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-python@v1 - with: - python-version: '3.7' - - name: install tensorflow and typeguard - run: pip install tensorflow-cpu typeguard - - name: install tf addons - run: TF_ADDONS_NO_BUILD=1 pip install --no-deps -e . - - name: Run type check - run: python tools/ci_build/verify/check_typing_info.py diff --git a/setup.py b/setup.py index cdc02ee05f..21eb3c9dff 100644 --- a/setup.py +++ b/setup.py @@ -60,7 +60,7 @@ required_pkgs = f.read().splitlines() # Manylinux2010 requires a patch for platlib -if sys.platform.startswith('linux') and os.environ.get('TF_ADDONS_NO_BUILD', '0') =='0': +if sys.platform.startswith('linux'): ext_modules = [Extension('_foo', ['stub.cc'])] else: ext_modules = [] diff --git a/tools/ci_build/verify/check_typing_info.py b/tools/ci_build/verify/check_typing_info.py deleted file mode 100644 index cc2dc8438e..0000000000 --- a/tools/ci_build/verify/check_typing_info.py +++ /dev/null @@ -1,218 +0,0 @@ -# Copyright 2019 The TensorFlow Authors. All Rights Reserved. -# -# Licensed 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. -# ============================================================================== -# -from types import ModuleType -import inspect - -import tensorflow_addons - -EXAMPLE_URL = 'https://github.com/tensorflow/addons/blob/fa8e966d987fd9b0d20551a666e44e2790fdf9c7/tensorflow_addons/layers/normalizations.py#L73' -TUTORIAL_URL = 'https://docs.python.org/3/library/typing.html' - - -# TODO: add types and remove all elements from -# the exception list. -EXCEPTION_LIST = [ - tensorflow_addons.activations.hardshrink, - tensorflow_addons.activations.lisht, - tensorflow_addons.activations.mish, - tensorflow_addons.activations.tanhshrink, - tensorflow_addons.activations.sparsemax, - tensorflow_addons.activations.softshrink, - tensorflow_addons.activations.rrelu, - tensorflow_addons.callbacks.TQDMProgressBar, - tensorflow_addons.callbacks.TimeStopping, - tensorflow_addons.image.connected_components, - tensorflow_addons.image.dense_image_warp, - tensorflow_addons.image.interpolate_bilinear, - tensorflow_addons.image.euclidean_dist_transform, - tensorflow_addons.image.adjust_hsv_in_yiq, - tensorflow_addons.image.random_hsv_in_yiq, - tensorflow_addons.image.mean_filter2d, - tensorflow_addons.image.median_filter2d, - tensorflow_addons.image.interpolate_spline, - tensorflow_addons.image.resampler, - tensorflow_addons.image.sparse_image_warp, - tensorflow_addons.image.rotate, - tensorflow_addons.image.transform, - tensorflow_addons.image.translate, - tensorflow_addons.layers.GELU, - tensorflow_addons.layers.Maxout, - tensorflow_addons.layers.GroupNormalization, - tensorflow_addons.layers.InstanceNormalization, - tensorflow_addons.layers.CorrelationCost, - tensorflow_addons.layers.PoincareNormalize, - tensorflow_addons.layers.Sparsemax, - tensorflow_addons.layers.TLU, - tensorflow_addons.layers.WeightNormalization, - tensorflow_addons.losses.contrastive_loss, - tensorflow_addons.losses.sigmoid_focal_crossentropy, - tensorflow_addons.losses.giou_loss, - tensorflow_addons.losses.lifted_struct_loss, - tensorflow_addons.losses.sparsemax_loss, - tensorflow_addons.losses.triplet_semihard_loss, - tensorflow_addons.losses.pinball_loss, - tensorflow_addons.losses.PinballLoss, - tensorflow_addons.losses.ContrastiveLoss, - tensorflow_addons.losses.SigmoidFocalCrossEntropy, - tensorflow_addons.losses.GIoULoss, - tensorflow_addons.losses.LiftedStructLoss, - tensorflow_addons.losses.SparsemaxLoss, - tensorflow_addons.losses.TripletSemiHardLoss, - tensorflow_addons.losses.npairs_loss, - tensorflow_addons.losses.NpairsLoss, - tensorflow_addons.losses.npairs_multilabel_loss, - tensorflow_addons.losses.NpairsMultilabelLoss, - tensorflow_addons.metrics.CohenKappa, - tensorflow_addons.metrics.F1Score, - tensorflow_addons.metrics.FBetaScore, - tensorflow_addons.metrics.HammingLoss, - tensorflow_addons.metrics.hamming_distance, - tensorflow_addons.metrics.MeanMetricWrapper, - tensorflow_addons.metrics.MatthewsCorrelationCoefficient, - tensorflow_addons.metrics.MultiLabelConfusionMatrix, - tensorflow_addons.metrics.RSquare, - tensorflow_addons.optimizers.AveragedOptimizerWrapper, - tensorflow_addons.optimizers.ConditionalGradient, - tensorflow_addons.optimizers.CyclicalLearningRate, - tensorflow_addons.optimizers.TriangularCyclicalLearningRate, - tensorflow_addons.optimizers.Triangular2CyclicalLearningRate, - tensorflow_addons.optimizers.ExponentialCyclicalLearningRate, - tensorflow_addons.optimizers.LAMB, - tensorflow_addons.optimizers.LazyAdam, - tensorflow_addons.optimizers.Lookahead, - tensorflow_addons.optimizers.MovingAverage, - tensorflow_addons.optimizers.NovoGrad, - tensorflow_addons.optimizers.RectifiedAdam, - tensorflow_addons.optimizers.SWA, - tensorflow_addons.optimizers.AdamW, - tensorflow_addons.optimizers.SGDW, - tensorflow_addons.optimizers.extend_with_decoupled_weight_decay, - tensorflow_addons.optimizers.Yogi, - tensorflow_addons.rnn.LayerNormLSTMCell, - tensorflow_addons.rnn.NASCell, - tensorflow_addons.seq2seq.AttentionMechanism, - tensorflow_addons.seq2seq.AttentionWrapper, - tensorflow_addons.seq2seq.AttentionWrapperState, - tensorflow_addons.seq2seq.BahdanauAttention, - tensorflow_addons.seq2seq.BahdanauMonotonicAttention, - tensorflow_addons.seq2seq.LuongAttention, - tensorflow_addons.seq2seq.LuongMonotonicAttention, - tensorflow_addons.seq2seq.hardmax, - tensorflow_addons.seq2seq.monotonic_attention, - tensorflow_addons.seq2seq.safe_cumprod, - tensorflow_addons.seq2seq.BasicDecoder, - tensorflow_addons.seq2seq.BasicDecoderOutput, - tensorflow_addons.seq2seq.BeamSearchDecoder, - tensorflow_addons.seq2seq.BeamSearchDecoderOutput, - tensorflow_addons.seq2seq.BeamSearchDecoderState, - tensorflow_addons.seq2seq.FinalBeamSearchDecoderOutput, - tensorflow_addons.seq2seq.gather_tree, - tensorflow_addons.seq2seq.gather_tree_from_array, - tensorflow_addons.seq2seq.tile_batch, - tensorflow_addons.seq2seq.BaseDecoder, - tensorflow_addons.seq2seq.Decoder, - tensorflow_addons.seq2seq.dynamic_decode, - tensorflow_addons.seq2seq.SequenceLoss, - tensorflow_addons.seq2seq.sequence_loss, - tensorflow_addons.seq2seq.CustomSampler, - tensorflow_addons.seq2seq.GreedyEmbeddingSampler, - tensorflow_addons.seq2seq.InferenceSampler, - tensorflow_addons.seq2seq.SampleEmbeddingSampler, - tensorflow_addons.seq2seq.Sampler, - tensorflow_addons.seq2seq.ScheduledEmbeddingTrainingSampler, - tensorflow_addons.seq2seq.ScheduledOutputTrainingSampler, - tensorflow_addons.seq2seq.TrainingSampler, - tensorflow_addons.text.crf_binary_score, - tensorflow_addons.text.crf_decode, - tensorflow_addons.text.crf_decode_backward, - tensorflow_addons.text.crf_decode_forward, - tensorflow_addons.text.crf_forward, - tensorflow_addons.text.crf_log_likelihood, - tensorflow_addons.text.crf_log_norm, - tensorflow_addons.text.crf_multitag_sequence_score, - tensorflow_addons.text.crf_sequence_score, - tensorflow_addons.text.crf_unary_score, - tensorflow_addons.text.viterbi_decode, - tensorflow_addons.text.skip_gram_sample, - tensorflow_addons.text.skip_gram_sample_with_text_vocab, - tensorflow_addons.text.parse_time, -] - - -def check_public_api_has_typing_information(): - for attribute in get_attributes(tensorflow_addons): - if isinstance(attribute, ModuleType): - check_module_is_typed(attribute) - - -def check_module_is_typed(module): - for attribute in get_attributes(module): - if attribute in EXCEPTION_LIST: - continue - if inspect.isclass(attribute): - check_function_is_typed(attribute.__init__, class_=attribute) - if inspect.isfunction(attribute): - check_function_is_typed(attribute) - - -def check_function_is_typed(func, class_=None): - """ If class_ is not None, func is the __init__ of the class.""" - signature = inspect.signature(func) - for parameter_name, parameter in signature.parameters.items(): - if parameter.annotation != inspect.Signature.empty: - continue - if parameter_name in ('args', 'kwargs', 'self'): - continue - if class_ is None: - function_name = func.__name__ - else: - function_name = class_.__name__ + '.__init__' - raise NotTypedError( - "The function '{}' has not complete type annotations " - "in its signature (it's missing the type hint for '{}'). " - "We would like all the functions and " - "class constructors in the public API to be typed and have " - "the @typechecked decorator. \n" - "If you are not familiar with adding type hints in " - "functions, you can look at functions already typed in" - "the codebase. For example: {}. \n" - "You can also look at this tutorial: " - "{}.".format(function_name, parameter_name, EXAMPLE_URL, TUTORIAL_URL) - ) - - if class_ is None: - if signature.return_annotation != inspect.Signature.empty: - return - raise NotTypedError( - 'The function {} has no return type. Please add one. ' - 'You can take a look at the gelu activation function ' - 'in tensorflow_addons/activations/gelu.py ' - 'if you want an example.'.format(func.__name__) - ) - - -def get_attributes(module): - for attr_name in dir(module): - attr = getattr(module, attr_name) - yield attr - - -class NotTypedError(Exception): - pass - - -if __name__ == '__main__': - check_public_api_has_typing_information() \ No newline at end of file From 9117054cf495270cba59ccdc20ea582d2204f770 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Mon, 27 Jan 2020 15:36:51 +0100 Subject: [PATCH 21/24] Removed the do_not_convert. --- tensorflow_addons/activations/gelu.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tensorflow_addons/activations/gelu.py b/tensorflow_addons/activations/gelu.py index 4c4d84432a..aa7f98d6fa 100644 --- a/tensorflow_addons/activations/gelu.py +++ b/tensorflow_addons/activations/gelu.py @@ -23,8 +23,6 @@ @tf.keras.utils.register_keras_serializable(package='Addons') -@tf.autograph.experimental.do_not_convert -@typechecked def gelu(x: types.TensorLike, approximate: bool = True) -> tf.Tensor: """Gaussian Error Linear Unit. From 960fc4740533fc19b30403de662a535bfaea9e97 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Mon, 27 Jan 2020 15:39:57 +0100 Subject: [PATCH 22/24] Used black. --- tensorflow_addons/utils/types.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/tensorflow_addons/utils/types.py b/tensorflow_addons/utils/types.py index 5e5f516979..464d79755e 100644 --- a/tensorflow_addons/utils/types.py +++ b/tensorflow_addons/utils/types.py @@ -20,19 +20,21 @@ import tensorflow as tf -Number = Union[float, - int, - np.float16, - np.float32, - np.float64, - np.int8, - np.int16, - np.int32, - np.int64, - np.uint8, - np.uint16, - np.uint32, - np.uint64] +Number = Union[ + float, + int, + np.float16, + np.float32, + np.float64, + np.int8, + np.int16, + np.int32, + np.int64, + np.uint8, + np.uint16, + np.uint32, + np.uint64, +] Initializer = Union[None, dict, str, Callable] Regularizer = Union[None, dict, str, Callable] From ba688ca5801dbfef6eb9fbbbb4198c2a495cccaa Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Mon, 27 Jan 2020 19:50:19 +0000 Subject: [PATCH 23/24] Removed unused import. --- tensorflow_addons/activations/gelu.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tensorflow_addons/activations/gelu.py b/tensorflow_addons/activations/gelu.py index aa7f98d6fa..6cb6ad4c35 100644 --- a/tensorflow_addons/activations/gelu.py +++ b/tensorflow_addons/activations/gelu.py @@ -14,7 +14,6 @@ # ============================================================================== import tensorflow as tf -from typeguard import typechecked from tensorflow_addons.utils import types from tensorflow_addons.utils.resource_loader import LazySO From 7a4822f3a974a9a1744e914b298b95e2ef53c96a Mon Sep 17 00:00:00 2001 From: Sean Morgan Date: Mon, 27 Jan 2020 19:26:58 -0500 Subject: [PATCH 24/24] Update types.py --- tensorflow_addons/utils/types.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tensorflow_addons/utils/types.py b/tensorflow_addons/utils/types.py index 4bf2d7728f..03c749cf36 100644 --- a/tensorflow_addons/utils/types.py +++ b/tensorflow_addons/utils/types.py @@ -36,9 +36,6 @@ np.uint64, ] -import numpy as np -import tensorflow as tf - Initializer = Union[None, dict, str, Callable] Regularizer = Union[None, dict, str, Callable] Constraint = Union[None, dict, str, Callable]