| |
| |
| <!DOCTYPE html> |
| <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]--> |
| <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]--> |
| <head> |
| <meta charset="utf-8"> |
| |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| |
| <title>apache_beam.typehints.decorators — Apache Beam 2.47.0 documentation</title> |
| |
| |
| |
| |
| |
| |
| |
| |
| <script type="text/javascript" src="../../../_static/js/modernizr.min.js"></script> |
| |
| |
| <script type="text/javascript" id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script> |
| <script type="text/javascript" src="../../../_static/jquery.js"></script> |
| <script type="text/javascript" src="../../../_static/underscore.js"></script> |
| <script type="text/javascript" src="../../../_static/doctools.js"></script> |
| <script type="text/javascript" src="../../../_static/language_data.js"></script> |
| <script async="async" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-AMS-MML_HTMLorMML"></script> |
| |
| <script type="text/javascript" src="../../../_static/js/theme.js"></script> |
| |
| |
| |
| |
| <link rel="stylesheet" href="../../../_static/css/theme.css" type="text/css" /> |
| <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" /> |
| <link rel="index" title="Index" href="../../../genindex.html" /> |
| <link rel="search" title="Search" href="../../../search.html" /> |
| </head> |
| |
| <body class="wy-body-for-nav"> |
| |
| |
| <div class="wy-grid-for-nav"> |
| |
| <nav data-toggle="wy-nav-shift" class="wy-nav-side"> |
| <div class="wy-side-scroll"> |
| <div class="wy-side-nav-search" > |
| |
| |
| |
| <a href="../../../index.html" class="icon icon-home"> Apache Beam |
| |
| |
| |
| </a> |
| |
| |
| |
| |
| <div class="version"> |
| 2.47.0 |
| </div> |
| |
| |
| |
| |
| <div role="search"> |
| <form id="rtd-search-form" class="wy-form" action="../../../search.html" method="get"> |
| <input type="text" name="q" placeholder="Search docs" /> |
| <input type="hidden" name="check_keywords" value="yes" /> |
| <input type="hidden" name="area" value="default" /> |
| </form> |
| </div> |
| |
| |
| </div> |
| |
| <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation"> |
| |
| |
| |
| |
| |
| |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.coders.html">apache_beam.coders package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.dataframe.html">apache_beam.dataframe package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.io.html">apache_beam.io package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.metrics.html">apache_beam.metrics package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.ml.html">apache_beam.ml package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.options.html">apache_beam.options package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.portability.html">apache_beam.portability package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.runners.html">apache_beam.runners package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.testing.html">apache_beam.testing package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.transforms.html">apache_beam.transforms package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.typehints.html">apache_beam.typehints package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.utils.html">apache_beam.utils package</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.yaml.html">apache_beam.yaml package</a></li> |
| </ul> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.error.html">apache_beam.error module</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.pipeline.html">apache_beam.pipeline module</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../../../apache_beam.pvalue.html">apache_beam.pvalue module</a></li> |
| </ul> |
| |
| |
| |
| </div> |
| </div> |
| </nav> |
| |
| <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"> |
| |
| |
| <nav class="wy-nav-top" aria-label="top navigation"> |
| |
| <i data-toggle="wy-nav-top" class="fa fa-bars"></i> |
| <a href="../../../index.html">Apache Beam</a> |
| |
| </nav> |
| |
| |
| <div class="wy-nav-content"> |
| |
| <div class="rst-content"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <div role="navigation" aria-label="breadcrumbs navigation"> |
| |
| <ul class="wy-breadcrumbs"> |
| |
| <li><a href="../../../index.html">Docs</a> »</li> |
| |
| <li><a href="../../index.html">Module code</a> »</li> |
| |
| <li>apache_beam.typehints.decorators</li> |
| |
| |
| <li class="wy-breadcrumbs-aside"> |
| |
| </li> |
| |
| </ul> |
| |
| |
| <hr/> |
| </div> |
| <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> |
| <div itemprop="articleBody"> |
| |
| <h1>Source code for apache_beam.typehints.decorators</h1><div class="highlight"><pre> |
| <span></span><span class="c1">#</span> |
| <span class="c1"># Licensed to the Apache Software Foundation (ASF) under one or more</span> |
| <span class="c1"># contributor license agreements. See the NOTICE file distributed with</span> |
| <span class="c1"># this work for additional information regarding copyright ownership.</span> |
| <span class="c1"># The ASF licenses this file to You under the Apache License, Version 2.0</span> |
| <span class="c1"># (the "License"); you may not use this file except in compliance with</span> |
| <span class="c1"># the License. You may obtain a copy of the License at</span> |
| <span class="c1">#</span> |
| <span class="c1"># http://www.apache.org/licenses/LICENSE-2.0</span> |
| <span class="c1">#</span> |
| <span class="c1"># Unless required by applicable law or agreed to in writing, software</span> |
| <span class="c1"># distributed under the License is distributed on an "AS IS" BASIS,</span> |
| <span class="c1"># WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span> |
| <span class="c1"># See the License for the specific language governing permissions and</span> |
| <span class="c1"># limitations under the License.</span> |
| <span class="c1">#</span> |
| |
| <span class="sd">"""Type hinting decorators allowing static or runtime type-checking for the SDK.</span> |
| |
| <span class="sd">This module defines decorators which utilize the type-hints defined in</span> |
| <span class="sd">'type_hints.py' to allow annotation of the types of function arguments and</span> |
| <span class="sd">return values.</span> |
| |
| <span class="sd">Type-hints for functions are annotated using two separate decorators. One is for</span> |
| <span class="sd">type-hinting the types of function arguments, the other for type-hinting the</span> |
| <span class="sd">function return value. Type-hints can either be specified in the form of</span> |
| <span class="sd">positional arguments::</span> |
| |
| <span class="sd"> @with_input_types(int, int)</span> |
| <span class="sd"> def add(a, b):</span> |
| <span class="sd"> return a + b</span> |
| |
| <span class="sd">Keyword arguments::</span> |
| |
| <span class="sd"> @with_input_types(a=int, b=int)</span> |
| <span class="sd"> def add(a, b):</span> |
| <span class="sd"> return a + b</span> |
| |
| <span class="sd">Or even a mix of both::</span> |
| |
| <span class="sd"> @with_input_types(int, b=int)</span> |
| <span class="sd"> def add(a, b):</span> |
| <span class="sd"> return a + b</span> |
| |
| <span class="sd">Example usage for type-hinting arguments only::</span> |
| |
| <span class="sd"> @with_input_types(s=str)</span> |
| <span class="sd"> def to_lower(a):</span> |
| <span class="sd"> return a.lower()</span> |
| |
| <span class="sd">Example usage for type-hinting return values only::</span> |
| |
| <span class="sd"> @with_output_types(Tuple[int, bool])</span> |
| <span class="sd"> def compress_point(ec_point):</span> |
| <span class="sd"> return ec_point.x, ec_point.y < 0</span> |
| |
| <span class="sd">Example usage for type-hinting both arguments and return values::</span> |
| |
| <span class="sd"> @with_input_types(a=int)</span> |
| <span class="sd"> @with_output_types(str)</span> |
| <span class="sd"> def int_to_str(a):</span> |
| <span class="sd"> return str(a)</span> |
| |
| <span class="sd">The valid type-hint for such as function looks like the following::</span> |
| |
| <span class="sd"> @with_input_types(a=int, b=int)</span> |
| <span class="sd"> def foo((a, b)):</span> |
| <span class="sd"> ...</span> |
| |
| <span class="sd">Notice that we hint the type of each unpacked argument independently, rather</span> |
| <span class="sd">than hinting the type of the tuple as a whole (Tuple[int, int]).</span> |
| |
| <span class="sd">Optionally, type-hints can be type-checked at runtime. To toggle this behavior</span> |
| <span class="sd">this module defines two functions: 'enable_run_time_type_checking' and</span> |
| <span class="sd">'disable_run_time_type_checking'. NOTE: for this toggle behavior to work</span> |
| <span class="sd">properly it must appear at the top of the module where all functions are</span> |
| <span class="sd">defined, or before importing a module containing type-hinted functions.</span> |
| <span class="sd">"""</span> |
| |
| <span class="c1"># pytype: skip-file</span> |
| |
| <span class="kn">import</span> <span class="nn">inspect</span> |
| <span class="kn">import</span> <span class="nn">itertools</span> |
| <span class="kn">import</span> <span class="nn">logging</span> |
| <span class="kn">import</span> <span class="nn">sys</span> |
| <span class="kn">import</span> <span class="nn">traceback</span> |
| <span class="kn">import</span> <span class="nn">types</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Callable</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Dict</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Iterable</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">NamedTuple</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Tuple</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">TypeVar</span> |
| <span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Union</span> |
| |
| <span class="kn">from</span> <span class="nn">apache_beam.typehints</span> <span class="kn">import</span> <span class="n">native_type_compatibility</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.typehints</span> <span class="kn">import</span> <span class="n">typehints</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.typehints.native_type_compatibility</span> <span class="kn">import</span> <span class="n">convert_to_beam_type</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.typehints.typehints</span> <span class="kn">import</span> <span class="n">CompositeTypeHintError</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.typehints.typehints</span> <span class="kn">import</span> <span class="n">SimpleTypeHintError</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.typehints.typehints</span> <span class="kn">import</span> <span class="n">check_constraint</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.typehints.typehints</span> <span class="kn">import</span> <span class="n">validate_composite_type_param</span> |
| |
| <span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span> |
| <span class="s1">'disable_type_annotations'</span><span class="p">,</span> |
| <span class="s1">'no_annotations'</span><span class="p">,</span> |
| <span class="s1">'with_input_types'</span><span class="p">,</span> |
| <span class="s1">'with_output_types'</span><span class="p">,</span> |
| <span class="s1">'WithTypeHints'</span><span class="p">,</span> |
| <span class="s1">'TypeCheckError'</span><span class="p">,</span> |
| <span class="p">]</span> |
| |
| <span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'T'</span><span class="p">)</span> |
| <span class="n">WithTypeHintsT</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s1">'WithTypeHintsT'</span><span class="p">,</span> <span class="n">bound</span><span class="o">=</span><span class="s1">'WithTypeHints'</span><span class="p">)</span> <span class="c1"># pylint: disable=invalid-name</span> |
| |
| <span class="c1"># This is missing in the builtin types module. str.upper is arbitrary, any</span> |
| <span class="c1"># method on a C-implemented type will do.</span> |
| <span class="c1"># pylint: disable=invalid-name</span> |
| <span class="n">_MethodDescriptorType</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="nb">str</span><span class="o">.</span><span class="n">upper</span><span class="p">)</span> |
| <span class="c1"># pylint: enable=invalid-name</span> |
| |
| <span class="n">_ANY_VAR_POSITIONAL</span> <span class="o">=</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Tuple</span><span class="p">[</span><span class="n">typehints</span><span class="o">.</span><span class="n">Any</span><span class="p">,</span> <span class="o">...</span><span class="p">]</span> |
| <span class="n">_ANY_VAR_KEYWORD</span> <span class="o">=</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Dict</span><span class="p">[</span><span class="n">typehints</span><span class="o">.</span><span class="n">Any</span><span class="p">,</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Any</span><span class="p">]</span> |
| <span class="n">_disable_from_callable</span> <span class="o">=</span> <span class="kc">False</span> |
| |
| |
| <span class="k">def</span> <span class="nf">get_signature</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Like inspect.signature(), but supports Py2 as well.</span> |
| |
| <span class="sd"> This module uses inspect.signature instead of getfullargspec since in the</span> |
| <span class="sd"> latter: 'the "self" parameter is always reported, even for bound methods'</span> |
| <span class="sd"> https://github.com/python/cpython/blob/44f91c388a6f4da9ed3300df32ca290b8aa104ea/Lib/inspect.py#L1103</span> |
| <span class="sd"> """</span> |
| <span class="k">try</span><span class="p">:</span> |
| <span class="n">signature</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">signature</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> |
| <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> |
| <span class="c1"># Fall back on a catch-all signature.</span> |
| <span class="n">params</span> <span class="o">=</span> <span class="p">[</span> |
| <span class="n">inspect</span><span class="o">.</span><span class="n">Parameter</span><span class="p">(</span><span class="s1">'_'</span><span class="p">,</span> <span class="n">inspect</span><span class="o">.</span><span class="n">Parameter</span><span class="o">.</span><span class="n">POSITIONAL_OR_KEYWORD</span><span class="p">),</span> |
| <span class="n">inspect</span><span class="o">.</span><span class="n">Parameter</span><span class="p">(</span> |
| <span class="s1">'__unknown__varargs'</span><span class="p">,</span> <span class="n">inspect</span><span class="o">.</span><span class="n">Parameter</span><span class="o">.</span><span class="n">VAR_POSITIONAL</span><span class="p">),</span> |
| <span class="n">inspect</span><span class="o">.</span><span class="n">Parameter</span><span class="p">(</span><span class="s1">'__unknown__keywords'</span><span class="p">,</span> <span class="n">inspect</span><span class="o">.</span><span class="n">Parameter</span><span class="o">.</span><span class="n">VAR_KEYWORD</span><span class="p">)</span> |
| <span class="p">]</span> |
| |
| <span class="n">signature</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">Signature</span><span class="p">(</span><span class="n">params</span><span class="p">)</span> |
| |
| <span class="c1"># This is a specialization to hint the first argument of certain builtins,</span> |
| <span class="c1"># such as str.strip.</span> |
| <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">_MethodDescriptorType</span><span class="p">):</span> |
| <span class="n">params</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">signature</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">values</span><span class="p">())</span> |
| <span class="k">if</span> <span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">annotation</span> <span class="o">==</span> <span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span> |
| <span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">annotation</span><span class="o">=</span><span class="n">func</span><span class="o">.</span><span class="vm">__objclass__</span><span class="p">)</span> |
| <span class="n">signature</span> <span class="o">=</span> <span class="n">signature</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">parameters</span><span class="o">=</span><span class="n">params</span><span class="p">)</span> |
| |
| <span class="c1"># This is a specialization to hint the return value of type callables.</span> |
| <span class="k">if</span> <span class="p">(</span><span class="n">signature</span><span class="o">.</span><span class="n">return_annotation</span> <span class="o">==</span> <span class="n">signature</span><span class="o">.</span><span class="n">empty</span> <span class="ow">and</span> |
| <span class="nb">isinstance</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="nb">type</span><span class="p">)):</span> |
| <span class="n">signature</span> <span class="o">=</span> <span class="n">signature</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">return_annotation</span><span class="o">=</span><span class="n">typehints</span><span class="o">.</span><span class="n">normalize</span><span class="p">(</span><span class="n">func</span><span class="p">))</span> |
| |
| <span class="k">return</span> <span class="n">signature</span> |
| |
| |
| <div class="viewcode-block" id="no_annotations"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.no_annotations">[docs]</a><span class="k">def</span> <span class="nf">no_annotations</span><span class="p">(</span><span class="n">fn</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Decorator that prevents Beam from using type hint annotations on a</span> |
| <span class="sd"> callable."""</span> |
| <span class="nb">setattr</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span> <span class="s1">'_beam_no_annotations'</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span> |
| <span class="k">return</span> <span class="n">fn</span></div> |
| |
| |
| <div class="viewcode-block" id="disable_type_annotations"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.disable_type_annotations">[docs]</a><span class="k">def</span> <span class="nf">disable_type_annotations</span><span class="p">():</span> |
| <span class="w"> </span><span class="sd">"""Prevent Beam from using type hint annotations to determine input and output</span> |
| <span class="sd"> types of transforms.</span> |
| |
| <span class="sd"> This setting applies globally.</span> |
| <span class="sd"> """</span> |
| <span class="k">global</span> <span class="n">_disable_from_callable</span> |
| <span class="n">_disable_from_callable</span> <span class="o">=</span> <span class="kc">True</span></div> |
| |
| |
| <span class="n">TRACEBACK_LIMIT</span> <span class="o">=</span> <span class="mi">5</span> |
| |
| |
| <span class="k">class</span> <span class="nc">IOTypeHints</span><span class="p">(</span><span class="n">NamedTuple</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Encapsulates all type hint information about a Beam construct.</span> |
| |
| <span class="sd"> This should primarily be used via the WithTypeHints mixin class, though</span> |
| <span class="sd"> may also be attached to other objects (such as Python functions).</span> |
| |
| <span class="sd"> Attributes:</span> |
| <span class="sd"> input_types: (tuple, dict) List of typing types, and an optional dictionary.</span> |
| <span class="sd"> May be None. The list and dict correspond to args and kwargs.</span> |
| <span class="sd"> output_types: (tuple, dict) List of typing types, and an optional dictionary</span> |
| <span class="sd"> (unused). Only the first element of the list is used. May be None.</span> |
| <span class="sd"> origin: (List[str]) Stack of tracebacks of method calls used to create this</span> |
| <span class="sd"> instance.</span> |
| <span class="sd"> """</span> |
| <span class="n">input_types</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="o">...</span><span class="p">],</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]]]</span> |
| <span class="n">output_types</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">Tuple</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="o">...</span><span class="p">],</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]]]</span> |
| <span class="n">origin</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> |
| |
| <span class="nd">@classmethod</span> |
| <span class="k">def</span> <span class="nf">_make_origin</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">tb</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">msg</span><span class="o">=</span><span class="p">()):</span> |
| <span class="c1"># type: (List[IOTypeHints], bool, Iterable[str]) -> List[str]</span> |
| <span class="k">if</span> <span class="n">msg</span><span class="p">:</span> |
| <span class="n">res</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="n">res</span> <span class="o">=</span> <span class="p">[]</span> |
| <span class="k">if</span> <span class="n">tb</span><span class="p">:</span> |
| <span class="c1"># Omit this method and the IOTypeHints method that called it.</span> |
| <span class="n">num_frames_skip</span> <span class="o">=</span> <span class="mi">2</span> |
| <span class="n">tbs</span> <span class="o">=</span> <span class="n">traceback</span><span class="o">.</span><span class="n">format_stack</span><span class="p">(</span><span class="n">limit</span><span class="o">=</span><span class="n">TRACEBACK_LIMIT</span> <span class="o">+</span> |
| <span class="n">num_frames_skip</span><span class="p">)[:</span><span class="o">-</span><span class="n">num_frames_skip</span><span class="p">]</span> |
| <span class="c1"># tb is a list of strings in the form of 'File ...\n[code]\n'. Split into</span> |
| <span class="c1"># single lines and flatten.</span> |
| <span class="n">res</span> <span class="o">+=</span> <span class="nb">list</span><span class="p">(</span> |
| <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="o">.</span><span class="n">from_iterable</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">tbs</span><span class="p">))</span> |
| |
| <span class="n">bases</span> <span class="o">=</span> <span class="p">[</span><span class="n">base</span> <span class="k">for</span> <span class="n">base</span> <span class="ow">in</span> <span class="n">bases</span> <span class="k">if</span> <span class="n">base</span><span class="o">.</span><span class="n">origin</span><span class="p">]</span> |
| <span class="k">if</span> <span class="n">bases</span><span class="p">:</span> |
| <span class="n">res</span> <span class="o">+=</span> <span class="p">[</span><span class="s1">''</span><span class="p">,</span> <span class="s1">'based on:'</span><span class="p">]</span> |
| <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">base</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">bases</span><span class="p">):</span> |
| <span class="k">if</span> <span class="n">i</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span> |
| <span class="n">res</span> <span class="o">+=</span> <span class="p">[</span><span class="s1">''</span><span class="p">,</span> <span class="s1">'and:'</span><span class="p">]</span> |
| <span class="n">res</span> <span class="o">+=</span> <span class="p">[</span><span class="s1">' '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">base</span><span class="p">)]</span> |
| <span class="n">res</span> <span class="o">+=</span> <span class="p">[</span><span class="s1">' '</span> <span class="o">+</span> <span class="n">s</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">base</span><span class="o">.</span><span class="n">origin</span><span class="p">]</span> |
| <span class="k">return</span> <span class="n">res</span> |
| |
| <span class="nd">@classmethod</span> |
| <span class="k">def</span> <span class="nf">empty</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span> |
| <span class="c1"># type: () -> IOTypeHints</span> |
| |
| <span class="w"> </span><span class="sd">"""Construct a base IOTypeHints object with no hints."""</span> |
| <span class="k">return</span> <span class="n">IOTypeHints</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="p">[])</span> |
| |
| <span class="nd">@classmethod</span> |
| <span class="k">def</span> <span class="nf">from_callable</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">fn</span><span class="p">):</span> |
| <span class="c1"># type: (Callable) -> Optional[IOTypeHints]</span> |
| |
| <span class="w"> </span><span class="sd">"""Construct an IOTypeHints object from a callable's signature.</span> |
| |
| <span class="sd"> Supports Python 3 annotations. For partial annotations, sets unknown types</span> |
| <span class="sd"> to Any, _ANY_VAR_POSITIONAL, or _ANY_VAR_KEYWORD.</span> |
| |
| <span class="sd"> Returns:</span> |
| <span class="sd"> A new IOTypeHints or None if no annotations found.</span> |
| <span class="sd"> """</span> |
| <span class="k">if</span> <span class="n">_disable_from_callable</span> <span class="ow">or</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span> <span class="s1">'_beam_no_annotations'</span><span class="p">,</span> <span class="kc">False</span><span class="p">):</span> |
| <span class="k">return</span> <span class="kc">None</span> |
| <span class="n">signature</span> <span class="o">=</span> <span class="n">get_signature</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span> |
| <span class="k">if</span> <span class="p">(</span><span class="nb">all</span><span class="p">(</span><span class="n">param</span><span class="o">.</span><span class="n">annotation</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">empty</span> |
| <span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">signature</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">values</span><span class="p">())</span> <span class="ow">and</span> |
| <span class="n">signature</span><span class="o">.</span><span class="n">return_annotation</span> <span class="o">==</span> <span class="n">signature</span><span class="o">.</span><span class="n">empty</span><span class="p">):</span> |
| <span class="k">return</span> <span class="kc">None</span> |
| <span class="n">input_args</span> <span class="o">=</span> <span class="p">[]</span> |
| <span class="n">input_kwargs</span> <span class="o">=</span> <span class="p">{}</span> |
| <span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">signature</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> |
| <span class="k">if</span> <span class="n">param</span><span class="o">.</span><span class="n">annotation</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span> |
| <span class="k">if</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">VAR_POSITIONAL</span><span class="p">:</span> |
| <span class="n">input_args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_ANY_VAR_POSITIONAL</span><span class="p">)</span> |
| <span class="k">elif</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">VAR_KEYWORD</span><span class="p">:</span> |
| <span class="n">input_kwargs</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">_ANY_VAR_KEYWORD</span> |
| <span class="k">elif</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">KEYWORD_ONLY</span><span class="p">:</span> |
| <span class="n">input_kwargs</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Any</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="n">input_args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">typehints</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="k">if</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="ow">in</span> <span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">KEYWORD_ONLY</span><span class="p">,</span> <span class="n">param</span><span class="o">.</span><span class="n">VAR_KEYWORD</span><span class="p">]:</span> |
| <span class="n">input_kwargs</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">convert_to_beam_type</span><span class="p">(</span><span class="n">param</span><span class="o">.</span><span class="n">annotation</span><span class="p">)</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="k">assert</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="ow">in</span> <span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">POSITIONAL_ONLY</span><span class="p">,</span> |
| <span class="n">param</span><span class="o">.</span><span class="n">POSITIONAL_OR_KEYWORD</span><span class="p">,</span> |
| <span class="n">param</span><span class="o">.</span><span class="n">VAR_POSITIONAL</span><span class="p">],</span> \ |
| <span class="s1">'Unsupported Parameter kind: </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> |
| <span class="n">input_args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">convert_to_beam_type</span><span class="p">(</span><span class="n">param</span><span class="o">.</span><span class="n">annotation</span><span class="p">))</span> |
| <span class="n">output_args</span> <span class="o">=</span> <span class="p">[]</span> |
| <span class="k">if</span> <span class="n">signature</span><span class="o">.</span><span class="n">return_annotation</span> <span class="o">!=</span> <span class="n">signature</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span> |
| <span class="n">output_args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">convert_to_beam_type</span><span class="p">(</span><span class="n">signature</span><span class="o">.</span><span class="n">return_annotation</span><span class="p">))</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="n">output_args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">typehints</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span> |
| |
| <span class="n">name</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span> <span class="s1">'__name__'</span><span class="p">,</span> <span class="s1">'<unknown>'</span><span class="p">)</span> |
| <span class="n">msg</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'from_callable(</span><span class="si">%s</span><span class="s1">)'</span> <span class="o">%</span> <span class="n">name</span><span class="p">,</span> <span class="s1">' signature: </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">signature</span><span class="p">]</span> |
| <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span> <span class="s1">'__code__'</span><span class="p">):</span> |
| <span class="n">msg</span><span class="o">.</span><span class="n">append</span><span class="p">(</span> |
| <span class="s1">' File "</span><span class="si">%s</span><span class="s1">", line </span><span class="si">%d</span><span class="s1">'</span> <span class="o">%</span> |
| <span class="p">(</span><span class="n">fn</span><span class="o">.</span><span class="vm">__code__</span><span class="o">.</span><span class="n">co_filename</span><span class="p">,</span> <span class="n">fn</span><span class="o">.</span><span class="vm">__code__</span><span class="o">.</span><span class="n">co_firstlineno</span><span class="p">))</span> |
| <span class="k">return</span> <span class="n">IOTypeHints</span><span class="p">(</span> |
| <span class="n">input_types</span><span class="o">=</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="n">input_args</span><span class="p">),</span> <span class="n">input_kwargs</span><span class="p">),</span> |
| <span class="n">output_types</span><span class="o">=</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="n">output_args</span><span class="p">),</span> <span class="p">{}),</span> |
| <span class="n">origin</span><span class="o">=</span><span class="bp">cls</span><span class="o">.</span><span class="n">_make_origin</span><span class="p">([],</span> <span class="n">tb</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">msg</span><span class="o">=</span><span class="n">msg</span><span class="p">))</span> |
| |
| <span class="k">def</span> <span class="nf">with_input_types</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> |
| <span class="c1"># type: (...) -> IOTypeHints</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_replace</span><span class="p">(</span> |
| <span class="n">input_types</span><span class="o">=</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">),</span> <span class="n">origin</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_make_origin</span><span class="p">([</span><span class="bp">self</span><span class="p">]))</span> |
| |
| <span class="k">def</span> <span class="nf">with_output_types</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> |
| <span class="c1"># type: (...) -> IOTypeHints</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_replace</span><span class="p">(</span> |
| <span class="n">output_types</span><span class="o">=</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">),</span> <span class="n">origin</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_make_origin</span><span class="p">([</span><span class="bp">self</span><span class="p">]))</span> |
| |
| <span class="k">def</span> <span class="nf">with_input_types_from</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span> |
| <span class="c1"># type: (IOTypeHints) -> IOTypeHints</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_replace</span><span class="p">(</span> |
| <span class="n">input_types</span><span class="o">=</span><span class="n">other</span><span class="o">.</span><span class="n">input_types</span><span class="p">,</span> <span class="n">origin</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_make_origin</span><span class="p">([</span><span class="bp">self</span><span class="p">]))</span> |
| |
| <span class="k">def</span> <span class="nf">with_output_types_from</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span> |
| <span class="c1"># type: (IOTypeHints) -> IOTypeHints</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_replace</span><span class="p">(</span> |
| <span class="n">output_types</span><span class="o">=</span><span class="n">other</span><span class="o">.</span><span class="n">output_types</span><span class="p">,</span> <span class="n">origin</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_make_origin</span><span class="p">([</span><span class="bp">self</span><span class="p">]))</span> |
| |
| <span class="k">def</span> <span class="nf">simple_output_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span> |
| <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_has_output_types</span><span class="p">():</span> |
| <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span> |
| <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">kwargs</span><span class="p">:</span> |
| <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span> |
| <span class="s1">'Expected single output type hint for </span><span class="si">%s</span><span class="s1"> but got: </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> |
| <span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span><span class="p">))</span> |
| <span class="k">return</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> |
| |
| <span class="k">def</span> <span class="nf">has_simple_output_type</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Whether there's a single positional output type."""</span> |
| <span class="k">return</span> <span class="p">(</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">output_types</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> |
| <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> |
| |
| <span class="k">def</span> <span class="nf">strip_pcoll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.pipeline</span> <span class="kn">import</span> <span class="n">Pipeline</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.pvalue</span> <span class="kn">import</span> <span class="n">PBegin</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.pvalue</span> <span class="kn">import</span> <span class="n">PDone</span> |
| |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">strip_pcoll_helper</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">input_types</span><span class="p">,</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">_has_input_types</span><span class="p">,</span> |
| <span class="s1">'input_types'</span><span class="p">,</span> |
| <span class="p">[</span><span class="n">Pipeline</span><span class="p">,</span> <span class="n">PBegin</span><span class="p">],</span> |
| <span class="s1">'This input type hint will be ignored '</span> |
| <span class="s1">'and not used for type-checking purposes. '</span> |
| <span class="s1">'Typically, input type hints for a '</span> |
| <span class="s1">'PTransform are single (or nested) types '</span> |
| <span class="s1">'wrapped by a PCollection, or PBegin.'</span><span class="p">,</span> |
| <span class="s1">'strip_pcoll_input()'</span><span class="p">)</span><span class="o">.</span>\ |
| <span class="n">strip_pcoll_helper</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">output_types</span><span class="p">,</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">has_simple_output_type</span><span class="p">,</span> |
| <span class="s1">'output_types'</span><span class="p">,</span> |
| <span class="p">[</span><span class="n">PDone</span><span class="p">,</span> <span class="kc">None</span><span class="p">],</span> |
| <span class="s1">'This output type hint will be ignored '</span> |
| <span class="s1">'and not used for type-checking purposes. '</span> |
| <span class="s1">'Typically, output type hints for a '</span> |
| <span class="s1">'PTransform are single (or nested) types '</span> |
| <span class="s1">'wrapped by a PCollection, PDone, or None.'</span><span class="p">,</span> |
| <span class="s1">'strip_pcoll_output()'</span><span class="p">)</span> |
| |
| <span class="k">def</span> <span class="nf">strip_pcoll_helper</span><span class="p">(</span> |
| <span class="bp">self</span><span class="p">,</span> |
| <span class="n">my_type</span><span class="p">,</span> <span class="c1"># type: any</span> |
| <span class="n">has_my_type</span><span class="p">,</span> <span class="c1"># type: Callable[[], bool]</span> |
| <span class="n">my_key</span><span class="p">,</span> <span class="c1"># type: str</span> |
| <span class="n">special_containers</span><span class="p">,</span> <span class="c1"># type: List[Union[PBegin, PDone, PCollection]] # noqa: F821</span> |
| <span class="n">error_str</span><span class="p">,</span> <span class="c1"># type: str</span> |
| <span class="n">source_str</span> <span class="c1"># type: str</span> |
| <span class="p">):</span> |
| <span class="c1"># type: (...) -> IOTypeHints</span> |
| <span class="kn">from</span> <span class="nn">apache_beam.pvalue</span> <span class="kn">import</span> <span class="n">PCollection</span> |
| |
| <span class="k">if</span> <span class="ow">not</span> <span class="n">has_my_type</span><span class="p">()</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">my_type</span> <span class="ow">or</span> <span class="nb">len</span><span class="p">(</span><span class="n">my_type</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span> |
| <span class="k">return</span> <span class="bp">self</span> |
| |
| <span class="n">my_type</span> <span class="o">=</span> <span class="n">my_type</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> |
| |
| <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">my_type</span><span class="p">,</span> <span class="n">typehints</span><span class="o">.</span><span class="n">AnyTypeConstraint</span><span class="p">):</span> |
| <span class="k">return</span> <span class="bp">self</span> |
| |
| <span class="n">special_containers</span> <span class="o">+=</span> <span class="p">[</span><span class="n">PCollection</span><span class="p">]</span> |
| <span class="n">kwarg_dict</span> <span class="o">=</span> <span class="p">{}</span> |
| |
| <span class="k">if</span> <span class="p">(</span><span class="n">my_type</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">special_containers</span> <span class="ow">and</span> |
| <span class="nb">getattr</span><span class="p">(</span><span class="n">my_type</span><span class="p">,</span> <span class="s1">'__origin__'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="o">!=</span> <span class="n">PCollection</span><span class="p">):</span> |
| <span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="n">error_str</span> <span class="o">+</span> <span class="s1">' Got: </span><span class="si">%s</span><span class="s1"> instead.'</span> <span class="o">%</span> <span class="n">my_type</span><span class="p">)</span> |
| <span class="n">kwarg_dict</span><span class="p">[</span><span class="n">my_key</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_replace</span><span class="p">(</span> |
| <span class="n">origin</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_make_origin</span><span class="p">([</span><span class="bp">self</span><span class="p">],</span> <span class="n">tb</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">msg</span><span class="o">=</span><span class="p">[</span><span class="n">source_str</span><span class="p">]),</span> |
| <span class="o">**</span><span class="n">kwarg_dict</span><span class="p">)</span> |
| |
| <span class="k">if</span> <span class="p">(</span><span class="nb">getattr</span><span class="p">(</span><span class="n">my_type</span><span class="p">,</span> <span class="s1">'__args__'</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="ow">in</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="kc">None</span><span class="p">]</span> <span class="ow">or</span> |
| <span class="nb">len</span><span class="p">(</span><span class="n">my_type</span><span class="o">.</span><span class="n">__args__</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">):</span> |
| <span class="c1"># e.g. PCollection (or PBegin/PDone)</span> |
| <span class="n">kwarg_dict</span><span class="p">[</span><span class="n">my_key</span><span class="p">]</span> <span class="o">=</span> <span class="p">((</span><span class="n">typehints</span><span class="o">.</span><span class="n">Any</span><span class="p">,</span> <span class="p">),</span> <span class="p">{})</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="c1"># e.g. PCollection[type]</span> |
| <span class="n">kwarg_dict</span><span class="p">[</span><span class="n">my_key</span><span class="p">]</span> <span class="o">=</span> <span class="p">((</span><span class="n">convert_to_beam_type</span><span class="p">(</span><span class="n">my_type</span><span class="o">.</span><span class="n">__args__</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="p">),</span> <span class="p">{})</span> |
| |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_replace</span><span class="p">(</span> |
| <span class="n">origin</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_make_origin</span><span class="p">([</span><span class="bp">self</span><span class="p">],</span> <span class="n">tb</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">msg</span><span class="o">=</span><span class="p">[</span><span class="n">source_str</span><span class="p">]),</span> |
| <span class="o">**</span><span class="n">kwarg_dict</span><span class="p">)</span> |
| |
| <span class="k">def</span> <span class="nf">strip_iterable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="c1"># type: () -> IOTypeHints</span> |
| |
| <span class="w"> </span><span class="sd">"""Removes outer Iterable (or equivalent) from output type.</span> |
| |
| <span class="sd"> Only affects instances with simple output types, otherwise is a no-op.</span> |
| <span class="sd"> Does not modify self.</span> |
| |
| <span class="sd"> Designed to be used with type hints from callables of ParDo, FlatMap, DoFn.</span> |
| <span class="sd"> Output type may be Optional[T], in which case the result of stripping T is</span> |
| <span class="sd"> used as the output type.</span> |
| <span class="sd"> Output type may be None/NoneType, in which case nothing is done.</span> |
| |
| <span class="sd"> Example: Generator[Tuple(int, int)] becomes Tuple(int, int)</span> |
| |
| <span class="sd"> Returns:</span> |
| <span class="sd"> A copy of this instance with a possibly different output type.</span> |
| |
| <span class="sd"> Raises:</span> |
| <span class="sd"> ValueError if output type is simple and not iterable.</span> |
| <span class="sd"> """</span> |
| <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">has_simple_output_type</span><span class="p">():</span> |
| <span class="k">return</span> <span class="bp">self</span> |
| <span class="n">output_type</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> |
| <span class="k">if</span> <span class="n">output_type</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">output_type</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="kc">None</span><span class="p">)):</span> |
| <span class="k">return</span> <span class="bp">self</span> |
| <span class="c1"># If output_type == Optional[T]: output_type = T.</span> |
| <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">output_type</span><span class="p">,</span> <span class="n">typehints</span><span class="o">.</span><span class="n">UnionConstraint</span><span class="p">):</span> |
| <span class="n">types</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">output_type</span><span class="o">.</span><span class="n">union_types</span><span class="p">)</span> |
| <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">types</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span> |
| <span class="k">try</span><span class="p">:</span> |
| <span class="n">types</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="kc">None</span><span class="p">))</span> |
| <span class="n">output_type</span> <span class="o">=</span> <span class="n">types</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> |
| <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> |
| <span class="k">pass</span> |
| |
| <span class="n">yielded_type</span> <span class="o">=</span> <span class="n">typehints</span><span class="o">.</span><span class="n">get_yielded_type</span><span class="p">(</span><span class="n">output_type</span><span class="p">)</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_replace</span><span class="p">(</span> |
| <span class="n">output_types</span><span class="o">=</span><span class="p">((</span><span class="n">yielded_type</span><span class="p">,</span> <span class="p">),</span> <span class="p">{}),</span> |
| <span class="n">origin</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_make_origin</span><span class="p">([</span><span class="bp">self</span><span class="p">],</span> <span class="n">tb</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">msg</span><span class="o">=</span><span class="p">[</span><span class="s1">'strip_iterable()'</span><span class="p">]))</span> |
| |
| <span class="k">def</span> <span class="nf">with_defaults</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">hints</span><span class="p">):</span> |
| <span class="c1"># type: (Optional[IOTypeHints]) -> IOTypeHints</span> |
| <span class="k">if</span> <span class="ow">not</span> <span class="n">hints</span><span class="p">:</span> |
| <span class="k">return</span> <span class="bp">self</span> |
| <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="p">:</span> |
| <span class="k">return</span> <span class="n">hints</span> |
| <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_has_input_types</span><span class="p">():</span> |
| <span class="n">input_types</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">input_types</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="n">input_types</span> <span class="o">=</span> <span class="n">hints</span><span class="o">.</span><span class="n">input_types</span> |
| <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_has_output_types</span><span class="p">():</span> |
| <span class="n">output_types</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="n">output_types</span> <span class="o">=</span> <span class="n">hints</span><span class="o">.</span><span class="n">output_types</span> |
| <span class="n">res</span> <span class="o">=</span> <span class="n">IOTypeHints</span><span class="p">(</span> |
| <span class="n">input_types</span><span class="p">,</span> |
| <span class="n">output_types</span><span class="p">,</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">_make_origin</span><span class="p">([</span><span class="bp">self</span><span class="p">,</span> <span class="n">hints</span><span class="p">],</span> <span class="n">tb</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">msg</span><span class="o">=</span><span class="p">[</span><span class="s1">'with_defaults()'</span><span class="p">]))</span> |
| <span class="k">if</span> <span class="n">res</span> <span class="o">==</span> <span class="bp">self</span><span class="p">:</span> |
| <span class="k">return</span> <span class="bp">self</span> <span class="c1"># Don't needlessly increase origin traceback length.</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="k">return</span> <span class="n">res</span> |
| |
| <span class="k">def</span> <span class="nf">_has_input_types</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">input_types</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="nb">any</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">input_types</span><span class="p">)</span> |
| |
| <span class="k">def</span> <span class="nf">_has_output_types</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="nb">any</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">output_types</span><span class="p">)</span> |
| |
| <span class="k">def</span> <span class="fm">__bool__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_has_input_types</span><span class="p">()</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">_has_output_types</span><span class="p">()</span> |
| |
| <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="k">return</span> <span class="s1">'IOTypeHints[inputs=</span><span class="si">%s</span><span class="s1">, outputs=</span><span class="si">%s</span><span class="s1">]'</span> <span class="o">%</span> <span class="p">(</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">input_types</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span><span class="p">)</span> |
| |
| <span class="k">def</span> <span class="nf">debug_str</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="k">return</span> <span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="bp">self</span><span class="o">.</span><span class="fm">__repr__</span><span class="p">()]</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">origin</span><span class="p">)</span> |
| |
| <span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span> |
| <span class="k">def</span> <span class="nf">same</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span> |
| <span class="k">if</span> <span class="n">a</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">any</span><span class="p">(</span><span class="n">a</span><span class="p">):</span> |
| <span class="k">return</span> <span class="n">b</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">any</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="k">return</span> <span class="n">a</span> <span class="o">==</span> <span class="n">b</span> |
| |
| <span class="k">return</span> <span class="p">(</span> |
| <span class="n">same</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">input_types</span><span class="p">,</span> <span class="n">other</span><span class="o">.</span><span class="n">input_types</span><span class="p">)</span> <span class="ow">and</span> |
| <span class="n">same</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">output_types</span><span class="p">,</span> <span class="n">other</span><span class="o">.</span><span class="n">output_types</span><span class="p">))</span> |
| |
| <span class="k">def</span> <span class="fm">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="k">return</span> <span class="nb">hash</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span> |
| |
| <span class="k">def</span> <span class="nf">__reduce__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="c1"># Don't include "origin" debug information in pickled form.</span> |
| <span class="k">return</span> <span class="p">(</span><span class="n">IOTypeHints</span><span class="p">,</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">input_types</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">output_types</span><span class="p">,</span> <span class="p">[]))</span> |
| |
| |
| <div class="viewcode-block" id="WithTypeHints"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.WithTypeHints">[docs]</a><span class="k">class</span> <span class="nc">WithTypeHints</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""A mixin class that provides the ability to set and retrieve type hints.</span> |
| <span class="sd"> """</span> |
| <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">unused_args</span><span class="p">,</span> <span class="o">**</span><span class="n">unused_kwargs</span><span class="p">):</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">_type_hints</span> <span class="o">=</span> <span class="n">IOTypeHints</span><span class="o">.</span><span class="n">empty</span><span class="p">()</span> |
| |
| <span class="k">def</span> <span class="nf">_get_or_create_type_hints</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="c1"># type: () -> IOTypeHints</span> |
| <span class="c1"># __init__ may have not been called</span> |
| <span class="k">try</span><span class="p">:</span> |
| <span class="c1"># Only return an instance bound to self (see BEAM-8629).</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">[</span><span class="s1">'_type_hints'</span><span class="p">]</span> |
| <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">_type_hints</span> <span class="o">=</span> <span class="n">IOTypeHints</span><span class="o">.</span><span class="n">empty</span><span class="p">()</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_type_hints</span> |
| |
| <div class="viewcode-block" id="WithTypeHints.get_type_hints"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.WithTypeHints.get_type_hints">[docs]</a> <span class="k">def</span> <span class="nf">get_type_hints</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Gets and/or initializes type hints for this object.</span> |
| |
| <span class="sd"> If type hints have not been set, attempts to initialize type hints in this</span> |
| <span class="sd"> order:</span> |
| <span class="sd"> - Using self.default_type_hints().</span> |
| <span class="sd"> - Using self.__class__ type hints.</span> |
| <span class="sd"> """</span> |
| <span class="k">return</span> <span class="p">(</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">_get_or_create_type_hints</span><span class="p">()</span><span class="o">.</span><span class="n">with_defaults</span><span class="p">(</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">default_type_hints</span><span class="p">())</span><span class="o">.</span><span class="n">with_defaults</span><span class="p">(</span> |
| <span class="n">get_type_hints</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">)))</span></div> |
| |
| <span class="k">def</span> <span class="nf">_set_type_hints</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">type_hints</span><span class="p">):</span> |
| <span class="c1"># type: (IOTypeHints) -> None</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">_type_hints</span> <span class="o">=</span> <span class="n">type_hints</span> |
| |
| <div class="viewcode-block" id="WithTypeHints.default_type_hints"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.WithTypeHints.default_type_hints">[docs]</a> <span class="k">def</span> <span class="nf">default_type_hints</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="k">return</span> <span class="kc">None</span></div> |
| |
| <div class="viewcode-block" id="WithTypeHints.with_input_types"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.WithTypeHints.with_input_types">[docs]</a> <span class="k">def</span> <span class="nf">with_input_types</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">arg_hints</span><span class="p">,</span> <span class="o">**</span><span class="n">kwarg_hints</span><span class="p">):</span> |
| <span class="c1"># type: (WithTypeHintsT, *Any, **Any) -> WithTypeHintsT</span> |
| <span class="n">arg_hints</span> <span class="o">=</span> <span class="n">native_type_compatibility</span><span class="o">.</span><span class="n">convert_to_beam_types</span><span class="p">(</span><span class="n">arg_hints</span><span class="p">)</span> |
| <span class="n">kwarg_hints</span> <span class="o">=</span> <span class="n">native_type_compatibility</span><span class="o">.</span><span class="n">convert_to_beam_types</span><span class="p">(</span><span class="n">kwarg_hints</span><span class="p">)</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">_type_hints</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_or_create_type_hints</span><span class="p">()</span><span class="o">.</span><span class="n">with_input_types</span><span class="p">(</span> |
| <span class="o">*</span><span class="n">arg_hints</span><span class="p">,</span> <span class="o">**</span><span class="n">kwarg_hints</span><span class="p">)</span> |
| <span class="k">return</span> <span class="bp">self</span></div> |
| |
| <div class="viewcode-block" id="WithTypeHints.with_output_types"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.WithTypeHints.with_output_types">[docs]</a> <span class="k">def</span> <span class="nf">with_output_types</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">arg_hints</span><span class="p">,</span> <span class="o">**</span><span class="n">kwarg_hints</span><span class="p">):</span> |
| <span class="c1"># type: (WithTypeHintsT, *Any, **Any) -> WithTypeHintsT</span> |
| <span class="n">arg_hints</span> <span class="o">=</span> <span class="n">native_type_compatibility</span><span class="o">.</span><span class="n">convert_to_beam_types</span><span class="p">(</span><span class="n">arg_hints</span><span class="p">)</span> |
| <span class="n">kwarg_hints</span> <span class="o">=</span> <span class="n">native_type_compatibility</span><span class="o">.</span><span class="n">convert_to_beam_types</span><span class="p">(</span><span class="n">kwarg_hints</span><span class="p">)</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">_type_hints</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_or_create_type_hints</span><span class="p">()</span><span class="o">.</span><span class="n">with_output_types</span><span class="p">(</span> |
| <span class="o">*</span><span class="n">arg_hints</span><span class="p">,</span> <span class="o">**</span><span class="n">kwarg_hints</span><span class="p">)</span> |
| <span class="k">return</span> <span class="bp">self</span></div></div> |
| |
| |
| <div class="viewcode-block" id="TypeCheckError"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.TypeCheckError">[docs]</a><span class="k">class</span> <span class="nc">TypeCheckError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> |
| <span class="k">pass</span></div> |
| |
| |
| <span class="k">def</span> <span class="nf">_positional_arg_hints</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">hints</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Returns the type of a (possibly tuple-packed) positional argument.</span> |
| |
| <span class="sd"> E.g. for lambda ((a, b), c): None the single positional argument is (as</span> |
| <span class="sd"> returned by inspect) [[a, b], c] which should have type</span> |
| <span class="sd"> Tuple[Tuple[Int, Any], float] when applied to the type hints</span> |
| <span class="sd"> {a: int, b: Any, c: float}.</span> |
| <span class="sd"> """</span> |
| <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span> |
| <span class="k">return</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Tuple</span><span class="p">[[</span><span class="n">_positional_arg_hints</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">hints</span><span class="p">)</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">arg</span><span class="p">]]</span> |
| <span class="k">return</span> <span class="n">hints</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Any</span><span class="p">)</span> |
| |
| |
| <span class="k">def</span> <span class="nf">_unpack_positional_arg_hints</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">hint</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Unpacks the given hint according to the nested structure of arg.</span> |
| |
| <span class="sd"> For example, if arg is [[a, b], c] and hint is Tuple[Any, int], then</span> |
| <span class="sd"> this function would return ((Any, Any), int) so it can be used in conjunction</span> |
| <span class="sd"> with inspect.getcallargs.</span> |
| <span class="sd"> """</span> |
| <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span> |
| <span class="n">tuple_constraint</span> <span class="o">=</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Tuple</span><span class="p">[[</span><span class="n">typehints</span><span class="o">.</span><span class="n">Any</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">arg</span><span class="p">)]</span> |
| <span class="k">if</span> <span class="ow">not</span> <span class="n">typehints</span><span class="o">.</span><span class="n">is_consistent_with</span><span class="p">(</span><span class="n">hint</span><span class="p">,</span> <span class="n">tuple_constraint</span><span class="p">):</span> |
| <span class="k">raise</span> <span class="n">TypeCheckError</span><span class="p">(</span> |
| <span class="s1">'Bad tuple arguments for </span><span class="si">%s</span><span class="s1">: expected </span><span class="si">%s</span><span class="s1">, got </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> |
| <span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">tuple_constraint</span><span class="p">,</span> <span class="n">hint</span><span class="p">))</span> |
| <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">hint</span><span class="p">,</span> <span class="n">typehints</span><span class="o">.</span><span class="n">TupleConstraint</span><span class="p">):</span> |
| <span class="k">return</span> <span class="nb">tuple</span><span class="p">(</span> |
| <span class="n">_unpack_positional_arg_hints</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span> <span class="k">for</span> <span class="n">a</span><span class="p">,</span> |
| <span class="n">t</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">hint</span><span class="o">.</span><span class="n">tuple_types</span><span class="p">))</span> |
| <span class="k">return</span> <span class="p">(</span><span class="n">typehints</span><span class="o">.</span><span class="n">Any</span><span class="p">,</span> <span class="p">)</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> |
| <span class="k">return</span> <span class="n">hint</span> |
| |
| |
| <span class="k">def</span> <span class="nf">_normalize_var_positional_hint</span><span class="p">(</span><span class="n">hint</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Converts a var_positional hint into Tuple[Union[<types>], ...] form.</span> |
| |
| <span class="sd"> Args:</span> |
| <span class="sd"> hint: (tuple) Should be either a tuple of one or more types, or a single</span> |
| <span class="sd"> Tuple[<type>, ...].</span> |
| |
| <span class="sd"> Raises:</span> |
| <span class="sd"> TypeCheckError if hint does not have the right form.</span> |
| <span class="sd"> """</span> |
| <span class="k">if</span> <span class="ow">not</span> <span class="n">hint</span> <span class="ow">or</span> <span class="nb">type</span><span class="p">(</span><span class="n">hint</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">tuple</span><span class="p">:</span> |
| <span class="k">raise</span> <span class="n">TypeCheckError</span><span class="p">(</span><span class="s1">'Unexpected VAR_POSITIONAL value: </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">hint</span><span class="p">)</span> |
| |
| <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">hint</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">hint</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">typehints</span><span class="o">.</span><span class="n">TupleSequenceConstraint</span><span class="p">):</span> |
| <span class="c1"># Example: tuple(Tuple[Any, ...]) -> Tuple[Any, ...]</span> |
| <span class="k">return</span> <span class="n">hint</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="c1"># Example: tuple(int, str) -> Tuple[Union[int, str], ...]</span> |
| <span class="k">return</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Tuple</span><span class="p">[</span><span class="n">typehints</span><span class="o">.</span><span class="n">Union</span><span class="p">[</span><span class="n">hint</span><span class="p">],</span> <span class="o">...</span><span class="p">]</span> |
| |
| |
| <span class="k">def</span> <span class="nf">_normalize_var_keyword_hint</span><span class="p">(</span><span class="n">hint</span><span class="p">,</span> <span class="n">arg_name</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Converts a var_keyword hint into Dict[<key type>, <value type>] form.</span> |
| |
| <span class="sd"> Args:</span> |
| <span class="sd"> hint: (dict) Should either contain a pair (arg_name,</span> |
| <span class="sd"> Dict[<key type>, <value type>]), or one or more possible types for the</span> |
| <span class="sd"> value.</span> |
| <span class="sd"> arg_name: (str) The keyword receiving this hint.</span> |
| |
| <span class="sd"> Raises:</span> |
| <span class="sd"> TypeCheckError if hint does not have the right form.</span> |
| <span class="sd"> """</span> |
| <span class="k">if</span> <span class="ow">not</span> <span class="n">hint</span> <span class="ow">or</span> <span class="nb">type</span><span class="p">(</span><span class="n">hint</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">dict</span><span class="p">:</span> |
| <span class="k">raise</span> <span class="n">TypeCheckError</span><span class="p">(</span><span class="s1">'Unexpected VAR_KEYWORD value: </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">hint</span><span class="p">)</span> |
| <span class="n">keys</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">hint</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span> |
| <span class="n">values</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">hint</span><span class="o">.</span><span class="n">values</span><span class="p">())</span> |
| <span class="k">if</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">keys</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">arg_name</span> <span class="ow">and</span> |
| <span class="nb">isinstance</span><span class="p">(</span><span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">typehints</span><span class="o">.</span><span class="n">DictConstraint</span><span class="p">)):</span> |
| <span class="c1"># Example: dict(kwargs=Dict[str, Any]) -> Dict[str, Any]</span> |
| <span class="k">return</span> <span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="c1"># Example: dict(k1=str, k2=int) -> Dict[str, Union[str,int]]</span> |
| <span class="k">return</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Union</span><span class="p">[</span><span class="n">values</span><span class="p">]]</span> |
| |
| |
| <span class="k">def</span> <span class="nf">getcallargs_forhints</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="o">*</span><span class="n">type_args</span><span class="p">,</span> <span class="o">**</span><span class="n">type_kwargs</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Bind type_args and type_kwargs to func.</span> |
| |
| <span class="sd"> Works like inspect.getcallargs, with some modifications to support type hint</span> |
| <span class="sd"> checks.</span> |
| <span class="sd"> For unbound args, will use annotations and fall back to Any (or variants of</span> |
| <span class="sd"> Any).</span> |
| |
| <span class="sd"> Returns:</span> |
| <span class="sd"> A mapping from parameter name to argument.</span> |
| <span class="sd"> """</span> |
| <span class="k">try</span><span class="p">:</span> |
| <span class="n">signature</span> <span class="o">=</span> <span class="n">get_signature</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> |
| <span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> |
| <span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">'Could not get signature for function: </span><span class="si">%s</span><span class="s1">: </span><span class="si">%s</span><span class="s1">'</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> |
| <span class="k">return</span> <span class="p">{}</span> |
| <span class="k">try</span><span class="p">:</span> |
| <span class="n">bindings</span> <span class="o">=</span> <span class="n">signature</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="o">*</span><span class="n">type_args</span><span class="p">,</span> <span class="o">**</span><span class="n">type_kwargs</span><span class="p">)</span> |
| <span class="k">except</span> <span class="ne">TypeError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> |
| <span class="c1"># Might be raised due to too few or too many arguments.</span> |
| <span class="k">raise</span> <span class="n">TypeCheckError</span><span class="p">(</span><span class="n">e</span><span class="p">)</span> |
| <span class="n">bound_args</span> <span class="o">=</span> <span class="n">bindings</span><span class="o">.</span><span class="n">arguments</span> |
| <span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">signature</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> |
| <span class="k">if</span> <span class="n">param</span><span class="o">.</span><span class="n">name</span> <span class="ow">in</span> <span class="n">bound_args</span><span class="p">:</span> |
| <span class="c1"># Bound: unpack/convert variadic arguments.</span> |
| <span class="k">if</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">VAR_POSITIONAL</span><span class="p">:</span> |
| <span class="n">bound_args</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">_normalize_var_positional_hint</span><span class="p">(</span> |
| <span class="n">bound_args</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">])</span> |
| <span class="k">elif</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">VAR_KEYWORD</span><span class="p">:</span> |
| <span class="n">bound_args</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">_normalize_var_keyword_hint</span><span class="p">(</span> |
| <span class="n">bound_args</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">],</span> <span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="c1"># Unbound: must have a default or be variadic.</span> |
| <span class="k">if</span> <span class="n">param</span><span class="o">.</span><span class="n">annotation</span> <span class="o">!=</span> <span class="n">param</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span> |
| <span class="n">bound_args</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="n">annotation</span> |
| <span class="k">elif</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">VAR_POSITIONAL</span><span class="p">:</span> |
| <span class="n">bound_args</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">_ANY_VAR_POSITIONAL</span> |
| <span class="k">elif</span> <span class="n">param</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="n">param</span><span class="o">.</span><span class="n">VAR_KEYWORD</span><span class="p">:</span> |
| <span class="n">bound_args</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">_ANY_VAR_KEYWORD</span> |
| <span class="k">elif</span> <span class="n">param</span><span class="o">.</span><span class="n">default</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">param</span><span class="o">.</span><span class="n">empty</span><span class="p">:</span> |
| <span class="c1"># Declare unbound parameters with defaults to be Any.</span> |
| <span class="n">bound_args</span><span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">typehints</span><span class="o">.</span><span class="n">Any</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="c1"># This case should be caught by signature.bind() above.</span> |
| <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">'Unexpected unbound parameter: </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">param</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> |
| |
| <span class="k">return</span> <span class="nb">dict</span><span class="p">(</span><span class="n">bound_args</span><span class="p">)</span> |
| |
| |
| <span class="k">def</span> <span class="nf">get_type_hints</span><span class="p">(</span><span class="n">fn</span><span class="p">):</span> |
| <span class="c1"># type: (Any) -> IOTypeHints</span> |
| |
| <span class="w"> </span><span class="sd">"""Gets the type hint associated with an arbitrary object fn.</span> |
| |
| <span class="sd"> Always returns a valid IOTypeHints object, creating one if necessary.</span> |
| <span class="sd"> """</span> |
| <span class="c1"># pylint: disable=protected-access</span> |
| <span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span> <span class="s1">'_type_hints'</span><span class="p">):</span> |
| <span class="k">try</span><span class="p">:</span> |
| <span class="n">fn</span><span class="o">.</span><span class="n">_type_hints</span> <span class="o">=</span> <span class="n">IOTypeHints</span><span class="o">.</span><span class="n">empty</span><span class="p">()</span> |
| <span class="k">except</span> <span class="p">(</span><span class="ne">AttributeError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">):</span> |
| <span class="c1"># Can't add arbitrary attributes to this object,</span> |
| <span class="c1"># but might have some restrictions anyways...</span> |
| <span class="n">hints</span> <span class="o">=</span> <span class="n">IOTypeHints</span><span class="o">.</span><span class="n">empty</span><span class="p">()</span> |
| <span class="c1"># Python 3.7 introduces annotations for _MethodDescriptorTypes.</span> |
| <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span> <span class="n">_MethodDescriptorType</span><span class="p">)</span> <span class="ow">and</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span> <span class="o"><</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">):</span> |
| <span class="n">hints</span> <span class="o">=</span> <span class="n">hints</span><span class="o">.</span><span class="n">with_input_types</span><span class="p">(</span><span class="n">fn</span><span class="o">.</span><span class="vm">__objclass__</span><span class="p">)</span> <span class="c1"># type: ignore</span> |
| <span class="k">return</span> <span class="n">hints</span> |
| <span class="k">return</span> <span class="n">fn</span><span class="o">.</span><span class="n">_type_hints</span> |
| <span class="c1"># pylint: enable=protected-access</span> |
| |
| |
| <div class="viewcode-block" id="with_input_types"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.with_input_types">[docs]</a><span class="k">def</span> <span class="nf">with_input_types</span><span class="p">(</span><span class="o">*</span><span class="n">positional_hints</span><span class="p">,</span> <span class="o">**</span><span class="n">keyword_hints</span><span class="p">):</span> |
| <span class="c1"># type: (*Any, **Any) -> Callable[[T], T]</span> |
| |
| <span class="w"> </span><span class="sd">"""A decorator that type-checks defined type-hints with passed func arguments.</span> |
| |
| <span class="sd"> All type-hinted arguments can be specified using positional arguments,</span> |
| <span class="sd"> keyword arguments, or a mix of both. Additionaly, all function arguments must</span> |
| <span class="sd"> be type-hinted in totality if even one parameter is type-hinted.</span> |
| |
| <span class="sd"> Once fully decorated, if the arguments passed to the resulting function</span> |
| <span class="sd"> violate the type-hint constraints defined, a :class:`TypeCheckError`</span> |
| <span class="sd"> detailing the error will be raised.</span> |
| |
| <span class="sd"> To be used as:</span> |
| |
| <span class="sd"> .. testcode::</span> |
| |
| <span class="sd"> from apache_beam.typehints import with_input_types</span> |
| |
| <span class="sd"> @with_input_types(str)</span> |
| <span class="sd"> def upper(s):</span> |
| <span class="sd"> return s.upper()</span> |
| |
| <span class="sd"> Or:</span> |
| |
| <span class="sd"> .. testcode::</span> |
| |
| <span class="sd"> from apache_beam.typehints import with_input_types</span> |
| <span class="sd"> from apache_beam.typehints import List</span> |
| <span class="sd"> from apache_beam.typehints import Tuple</span> |
| |
| <span class="sd"> @with_input_types(ls=List[Tuple[int, int]])</span> |
| <span class="sd"> def increment(ls):</span> |
| <span class="sd"> [(i + 1, j + 1) for (i,j) in ls]</span> |
| |
| <span class="sd"> Args:</span> |
| <span class="sd"> *positional_hints: Positional type-hints having identical order as the</span> |
| <span class="sd"> function's formal arguments. Values for this argument must either be a</span> |
| <span class="sd"> built-in Python type or an instance of a</span> |
| <span class="sd"> :class:`~apache_beam.typehints.typehints.TypeConstraint` created by</span> |
| <span class="sd"> 'indexing' a</span> |
| <span class="sd"> :class:`~apache_beam.typehints.typehints.CompositeTypeHint` instance</span> |
| <span class="sd"> with a type parameter.</span> |
| <span class="sd"> **keyword_hints: Keyword arguments mirroring the names of the parameters to</span> |
| <span class="sd"> the decorated functions. The value of each keyword argument must either</span> |
| <span class="sd"> be one of the allowed built-in Python types, a custom class, or an</span> |
| <span class="sd"> instance of a :class:`~apache_beam.typehints.typehints.TypeConstraint`</span> |
| <span class="sd"> created by 'indexing' a</span> |
| <span class="sd"> :class:`~apache_beam.typehints.typehints.CompositeTypeHint` instance</span> |
| <span class="sd"> with a type parameter.</span> |
| |
| <span class="sd"> Raises:</span> |
| <span class="sd"> :class:`ValueError`: If not all function arguments have</span> |
| <span class="sd"> corresponding type-hints specified. Or if the inner wrapper function isn't</span> |
| <span class="sd"> passed a function object.</span> |
| <span class="sd"> :class:`TypeCheckError`: If the any of the passed type-hint</span> |
| <span class="sd"> constraints are not a type or</span> |
| <span class="sd"> :class:`~apache_beam.typehints.typehints.TypeConstraint` instance.</span> |
| |
| <span class="sd"> Returns:</span> |
| <span class="sd"> The original function decorated such that it enforces type-hint constraints</span> |
| <span class="sd"> for all received function arguments.</span> |
| <span class="sd"> """</span> |
| |
| <span class="n">converted_positional_hints</span> <span class="o">=</span> <span class="p">(</span> |
| <span class="n">native_type_compatibility</span><span class="o">.</span><span class="n">convert_to_beam_types</span><span class="p">(</span><span class="n">positional_hints</span><span class="p">))</span> |
| <span class="n">converted_keyword_hints</span> <span class="o">=</span> <span class="p">(</span> |
| <span class="n">native_type_compatibility</span><span class="o">.</span><span class="n">convert_to_beam_types</span><span class="p">(</span><span class="n">keyword_hints</span><span class="p">))</span> |
| <span class="k">del</span> <span class="n">positional_hints</span> |
| <span class="k">del</span> <span class="n">keyword_hints</span> |
| |
| <span class="k">def</span> <span class="nf">annotate_input_types</span><span class="p">(</span><span class="n">f</span><span class="p">):</span> |
| <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">types</span><span class="o">.</span><span class="n">FunctionType</span><span class="p">):</span> |
| <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">converted_positional_hints</span><span class="p">)</span> <span class="o">+</span> |
| <span class="nb">list</span><span class="p">(</span><span class="n">converted_keyword_hints</span><span class="o">.</span><span class="n">values</span><span class="p">())):</span> |
| <span class="n">validate_composite_type_param</span><span class="p">(</span> |
| <span class="n">t</span><span class="p">,</span> <span class="n">error_msg_prefix</span><span class="o">=</span><span class="s1">'All type hint arguments'</span><span class="p">)</span> |
| |
| <span class="n">th</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="s1">'_type_hints'</span><span class="p">,</span> <span class="n">IOTypeHints</span><span class="o">.</span><span class="n">empty</span><span class="p">())</span><span class="o">.</span><span class="n">with_input_types</span><span class="p">(</span> |
| <span class="o">*</span><span class="n">converted_positional_hints</span><span class="p">,</span> <span class="o">**</span><span class="n">converted_keyword_hints</span><span class="p">)</span> |
| <span class="n">f</span><span class="o">.</span><span class="n">_type_hints</span> <span class="o">=</span> <span class="n">th</span> <span class="c1"># pylint: disable=protected-access</span> |
| <span class="k">return</span> <span class="n">f</span> |
| |
| <span class="k">return</span> <span class="n">annotate_input_types</span></div> |
| |
| |
| <div class="viewcode-block" id="with_output_types"><a class="viewcode-back" href="../../../apache_beam.typehints.decorators.html#apache_beam.typehints.decorators.with_output_types">[docs]</a><span class="k">def</span> <span class="nf">with_output_types</span><span class="p">(</span><span class="o">*</span><span class="n">return_type_hint</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> |
| <span class="c1"># type: (*Any, **Any) -> Callable[[T], T]</span> |
| |
| <span class="w"> </span><span class="sd">"""A decorator that type-checks defined type-hints for return values(s).</span> |
| |
| <span class="sd"> This decorator will type-check the return value(s) of the decorated function.</span> |
| |
| <span class="sd"> Only a single type-hint is accepted to specify the return type of the return</span> |
| <span class="sd"> value. If the function to be decorated has multiple return values, then one</span> |
| <span class="sd"> should use: ``Tuple[type_1, type_2]`` to annotate the types of the return</span> |
| <span class="sd"> values.</span> |
| |
| <span class="sd"> If the ultimate return value for the function violates the specified type-hint</span> |
| <span class="sd"> a :class:`TypeCheckError` will be raised detailing the type-constraint</span> |
| <span class="sd"> violation.</span> |
| |
| <span class="sd"> This decorator is intended to be used like:</span> |
| |
| <span class="sd"> .. testcode::</span> |
| |
| <span class="sd"> from apache_beam.typehints import with_output_types</span> |
| <span class="sd"> from apache_beam.typehints import Set</span> |
| |
| <span class="sd"> class Coordinate(object):</span> |
| <span class="sd"> def __init__(self, x, y):</span> |
| <span class="sd"> self.x = x</span> |
| <span class="sd"> self.y = y</span> |
| |
| <span class="sd"> @with_output_types(Set[Coordinate])</span> |
| <span class="sd"> def parse_ints(ints):</span> |
| <span class="sd"> return {Coordinate(i, i) for i in ints}</span> |
| |
| <span class="sd"> Or with a simple type-hint:</span> |
| |
| <span class="sd"> .. testcode::</span> |
| |
| <span class="sd"> from apache_beam.typehints import with_output_types</span> |
| |
| <span class="sd"> @with_output_types(bool)</span> |
| <span class="sd"> def negate(p):</span> |
| <span class="sd"> return not p if p else p</span> |
| |
| <span class="sd"> Args:</span> |
| <span class="sd"> *return_type_hint: A type-hint specifying the proper return type of the</span> |
| <span class="sd"> function. This argument should either be a built-in Python type or an</span> |
| <span class="sd"> instance of a :class:`~apache_beam.typehints.typehints.TypeConstraint`</span> |
| <span class="sd"> created by 'indexing' a</span> |
| <span class="sd"> :class:`~apache_beam.typehints.typehints.CompositeTypeHint`.</span> |
| <span class="sd"> **kwargs: Not used.</span> |
| |
| <span class="sd"> Raises:</span> |
| <span class="sd"> :class:`ValueError`: If any kwarg parameters are passed in,</span> |
| <span class="sd"> or the length of **return_type_hint** is greater than ``1``. Or if the</span> |
| <span class="sd"> inner wrapper function isn't passed a function object.</span> |
| <span class="sd"> :class:`TypeCheckError`: If the **return_type_hint** object is</span> |
| <span class="sd"> in invalid type-hint.</span> |
| |
| <span class="sd"> Returns:</span> |
| <span class="sd"> The original function decorated such that it enforces type-hint constraints</span> |
| <span class="sd"> for all return values.</span> |
| <span class="sd"> """</span> |
| <span class="k">if</span> <span class="n">kwargs</span><span class="p">:</span> |
| <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span> |
| <span class="s2">"All arguments for the 'returns' decorator must be "</span> |
| <span class="s2">"positional arguments."</span><span class="p">)</span> |
| |
| <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">return_type_hint</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span> |
| <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span> |
| <span class="s2">"'returns' accepts only a single positional argument. In "</span> |
| <span class="s2">"order to specify multiple return types, use the 'Tuple' "</span> |
| <span class="s2">"type-hint."</span><span class="p">)</span> |
| |
| <span class="n">return_type_hint</span> <span class="o">=</span> <span class="n">native_type_compatibility</span><span class="o">.</span><span class="n">convert_to_beam_type</span><span class="p">(</span> |
| <span class="n">return_type_hint</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> |
| |
| <span class="n">validate_composite_type_param</span><span class="p">(</span> |
| <span class="n">return_type_hint</span><span class="p">,</span> <span class="n">error_msg_prefix</span><span class="o">=</span><span class="s1">'All type hint arguments'</span><span class="p">)</span> |
| |
| <span class="k">def</span> <span class="nf">annotate_output_types</span><span class="p">(</span><span class="n">f</span><span class="p">):</span> |
| <span class="n">th</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="s1">'_type_hints'</span><span class="p">,</span> <span class="n">IOTypeHints</span><span class="o">.</span><span class="n">empty</span><span class="p">())</span> |
| <span class="n">f</span><span class="o">.</span><span class="n">_type_hints</span> <span class="o">=</span> <span class="n">th</span><span class="o">.</span><span class="n">with_output_types</span><span class="p">(</span><span class="n">return_type_hint</span><span class="p">)</span> <span class="c1"># pylint: disable=protected-access</span> |
| <span class="k">return</span> <span class="n">f</span> |
| |
| <span class="k">return</span> <span class="n">annotate_output_types</span></div> |
| |
| |
| <span class="k">def</span> <span class="nf">_check_instance_type</span><span class="p">(</span> |
| <span class="n">type_constraint</span><span class="p">,</span> <span class="n">instance</span><span class="p">,</span> <span class="n">var_name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">verbose</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""A helper function to report type-hint constraint violations.</span> |
| |
| <span class="sd"> Args:</span> |
| <span class="sd"> type_constraint: An instance of a 'TypeConstraint' or a built-in Python</span> |
| <span class="sd"> type.</span> |
| <span class="sd"> instance: The candidate object which will be checked by to satisfy</span> |
| <span class="sd"> 'type_constraint'.</span> |
| <span class="sd"> var_name: If 'instance' is an argument, then the actual name for the</span> |
| <span class="sd"> parameter in the original function definition.</span> |
| |
| <span class="sd"> Raises:</span> |
| <span class="sd"> TypeCheckError: If 'instance' fails to meet the type-constraint of</span> |
| <span class="sd"> 'type_constraint'.</span> |
| <span class="sd"> """</span> |
| <span class="n">hint_type</span> <span class="o">=</span> <span class="p">(</span> |
| <span class="s2">"argument: '</span><span class="si">%s</span><span class="s2">'"</span> <span class="o">%</span> <span class="n">var_name</span> <span class="k">if</span> <span class="n">var_name</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="s1">'return type'</span><span class="p">)</span> |
| |
| <span class="k">try</span><span class="p">:</span> |
| <span class="n">check_constraint</span><span class="p">(</span><span class="n">type_constraint</span><span class="p">,</span> <span class="n">instance</span><span class="p">)</span> |
| <span class="k">except</span> <span class="n">SimpleTypeHintError</span><span class="p">:</span> |
| <span class="k">if</span> <span class="n">verbose</span><span class="p">:</span> |
| <span class="n">verbose_instance</span> <span class="o">=</span> <span class="s1">'</span><span class="si">%s</span><span class="s1">, '</span> <span class="o">%</span> <span class="n">instance</span> |
| <span class="k">else</span><span class="p">:</span> |
| <span class="n">verbose_instance</span> <span class="o">=</span> <span class="s1">''</span> |
| <span class="k">raise</span> <span class="n">TypeCheckError</span><span class="p">(</span> |
| <span class="s1">'Type-hint for </span><span class="si">%s</span><span class="s1"> violated. Expected an '</span> |
| <span class="s1">'instance of </span><span class="si">%s</span><span class="s1">, instead found </span><span class="si">%s</span><span class="s1">an instance of </span><span class="si">%s</span><span class="s1">.'</span> <span class="o">%</span> |
| <span class="p">(</span><span class="n">hint_type</span><span class="p">,</span> <span class="n">type_constraint</span><span class="p">,</span> <span class="n">verbose_instance</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="n">instance</span><span class="p">)))</span> |
| <span class="k">except</span> <span class="n">CompositeTypeHintError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> |
| <span class="k">raise</span> <span class="n">TypeCheckError</span><span class="p">(</span><span class="s1">'Type-hint for </span><span class="si">%s</span><span class="s1"> violated: </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">hint_type</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span> |
| |
| |
| <span class="k">def</span> <span class="nf">_interleave_type_check</span><span class="p">(</span><span class="n">type_constraint</span><span class="p">,</span> <span class="n">var_name</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""Lazily type-check the type-hint for a lazily generated sequence type.</span> |
| |
| <span class="sd"> This function can be applied as a decorator or called manually in a curried</span> |
| <span class="sd"> manner:</span> |
| <span class="sd"> * @_interleave_type_check(List[int])</span> |
| <span class="sd"> def gen():</span> |
| <span class="sd"> yield 5</span> |
| |
| <span class="sd"> or</span> |
| |
| <span class="sd"> * gen = _interleave_type_check(Tuple[int, int], 'coord_gen')(gen)</span> |
| |
| <span class="sd"> As a result, all type-checking for the passed generator will occur at 'yield'</span> |
| <span class="sd"> time. This way, we avoid having to depleat the generator in order to</span> |
| <span class="sd"> type-check it.</span> |
| |
| <span class="sd"> Args:</span> |
| <span class="sd"> type_constraint: An instance of a TypeConstraint. The output yielded of</span> |
| <span class="sd"> 'gen' will be type-checked according to this type constraint.</span> |
| <span class="sd"> var_name: The variable name binded to 'gen' if type-checking a function</span> |
| <span class="sd"> argument. Used solely for templating in error message generation.</span> |
| |
| <span class="sd"> Returns:</span> |
| <span class="sd"> A function which takes a generator as an argument and returns a wrapped</span> |
| <span class="sd"> version of the generator that interleaves type-checking at 'yield'</span> |
| <span class="sd"> iteration. If the generator received is already wrapped, then it is simply</span> |
| <span class="sd"> returned to avoid nested wrapping.</span> |
| <span class="sd"> """</span> |
| <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="n">gen</span><span class="p">):</span> |
| <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">gen</span><span class="p">,</span> <span class="n">GeneratorWrapper</span><span class="p">):</span> |
| <span class="k">return</span> <span class="n">gen</span> |
| <span class="k">return</span> <span class="n">GeneratorWrapper</span><span class="p">(</span> |
| <span class="n">gen</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">_check_instance_type</span><span class="p">(</span><span class="n">type_constraint</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">var_name</span><span class="p">))</span> |
| |
| <span class="k">return</span> <span class="n">wrapper</span> |
| |
| |
| <span class="k">class</span> <span class="nc">GeneratorWrapper</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> |
| <span class="w"> </span><span class="sd">"""A wrapper around a generator, allows execution of a callback per yield.</span> |
| |
| <span class="sd"> Additionally, wrapping a generator with this class allows one to assign</span> |
| <span class="sd"> arbitary attributes to a generator object just as with a function object.</span> |
| |
| <span class="sd"> Attributes:</span> |
| <span class="sd"> internal_gen: A instance of a generator object. As part of 'step' of the</span> |
| <span class="sd"> generator, the yielded object will be passed to 'interleave_func'.</span> |
| <span class="sd"> interleave_func: A callback accepting a single argument. This function will</span> |
| <span class="sd"> be called with the result of each yielded 'step' in the internal</span> |
| <span class="sd"> generator.</span> |
| <span class="sd"> """</span> |
| <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">gen</span><span class="p">,</span> <span class="n">interleave_func</span><span class="p">):</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">internal_gen</span> <span class="o">=</span> <span class="n">gen</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">interleave_func</span> <span class="o">=</span> <span class="n">interleave_func</span> |
| |
| <span class="k">def</span> <span class="fm">__getattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">):</span> |
| <span class="c1"># TODO(laolu): May also want to intercept 'send' in the future if we move to</span> |
| <span class="c1"># a GeneratorHint with 3 type-params:</span> |
| <span class="c1"># * Generator[send_type, return_type, yield_type]</span> |
| <span class="k">if</span> <span class="n">attr</span> <span class="o">==</span> <span class="s1">'__next__'</span><span class="p">:</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__next__</span><span class="p">()</span> |
| <span class="k">elif</span> <span class="n">attr</span> <span class="o">==</span> <span class="s1">'__iter__'</span><span class="p">:</span> |
| <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__iter__</span><span class="p">()</span> |
| <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">internal_gen</span><span class="p">,</span> <span class="n">attr</span><span class="p">)</span> |
| |
| <span class="k">def</span> <span class="fm">__next__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="n">next_val</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">internal_gen</span><span class="p">)</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">interleave_func</span><span class="p">(</span><span class="n">next_val</span><span class="p">)</span> |
| <span class="k">return</span> <span class="n">next_val</span> |
| |
| <span class="nb">next</span> <span class="o">=</span> <span class="fm">__next__</span> |
| |
| <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> |
| <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">internal_gen</span><span class="p">:</span> |
| <span class="bp">self</span><span class="o">.</span><span class="n">interleave_func</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> |
| <span class="k">yield</span> <span class="n">x</span> |
| </pre></div> |
| |
| </div> |
| |
| </div> |
| <footer> |
| |
| |
| <hr/> |
| |
| <div role="contentinfo"> |
| <p> |
| © Copyright |
| |
| </p> |
| </div> |
| Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. |
| |
| </footer> |
| |
| </div> |
| </div> |
| |
| </section> |
| |
| </div> |
| |
| |
| |
| <script type="text/javascript"> |
| jQuery(function () { |
| SphinxRtdTheme.Navigation.enable(true); |
| }); |
| </script> |
| |
| |
| |
| |
| |
| |
| </body> |
| </html> |