| # Copyright (c) 2010-2017 Benjamin Peterson | 
 | # | 
 | # Permission is hereby granted, free of charge, to any person obtaining a copy | 
 | # of this software and associated documentation files (the "Software"), to deal | 
 | # in the Software without restriction, including without limitation the rights | 
 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
 | # copies of the Software, and to permit persons to whom the Software is | 
 | # furnished to do so, subject to the following conditions: | 
 | # | 
 | # The above copyright notice and this permission notice shall be included in all | 
 | # copies or substantial portions of the Software. | 
 | # | 
 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
 | # SOFTWARE. | 
 |  | 
 | import builtins | 
 | import collections.abc | 
 | import io | 
 | import math | 
 | import sys | 
 | import types | 
 | import queue  # noqa: F401 | 
 |  | 
 | inf = math.inf | 
 | nan = math.nan | 
 | string_classes = (str, bytes) | 
 | int_classes = int | 
 | FileNotFoundError = builtins.FileNotFoundError | 
 | StringIO = io.StringIO | 
 | container_abcs = collections.abc | 
 | PY3 = sys.version_info[0] == 3 | 
 | PY37 = sys.version_info[0] == 3 and sys.version_info[1] >= 7 | 
 |  | 
 | def with_metaclass(meta: type, *bases) -> type: | 
 |     """Create a base class with a metaclass.""" | 
 |     # This requires a bit of explanation: the basic idea is to make a dummy | 
 |     # metaclass for one level of class instantiation that replaces itself with | 
 |     # the actual metaclass. | 
 |     class metaclass(meta):  # type: ignore[misc, valid-type] | 
 |  | 
 |         def __new__(cls, name, this_bases, d): | 
 |             return meta(name, bases, d) | 
 |  | 
 |         @classmethod | 
 |         def __prepare__(cls, name, this_bases): | 
 |             return meta.__prepare__(name, bases) | 
 |  | 
 |     return type.__new__(metaclass, 'temporary_class', (), {}) | 
 |  | 
 |  | 
 | def raise_from(value: BaseException, from_value: BaseException) -> None: | 
 |     try: | 
 |         raise value from from_value | 
 |     finally: | 
 |         value = None  # type: ignore[assignment] | 
 |  | 
 |  | 
 | # Gets a function from the name of a method on a type | 
 | def get_function_from_type(cls, name): | 
 |     return getattr(cls, name, None) | 
 |  | 
 |  | 
 | # The codes below is not copied from the six package, so the copyright | 
 | # declaration at the beginning does not apply. | 
 | # | 
 | # Copyright(c) PyTorch contributors | 
 | # | 
 |  | 
 | def istuple(obj) -> bool: | 
 |     # Usually instances of PyStructSequence is also an instance of tuple | 
 |     # but in some py2 environment it is not, so we have to manually check | 
 |     # the name of the type to determine if it is a namedtupled returned | 
 |     # by a pytorch operator. | 
 |     t = type(obj) | 
 |     return isinstance(obj, tuple) or t.__module__ == 'torch.return_types' | 
 |  | 
 | def bind_method(fn, obj, obj_type): | 
 |     return types.MethodType(fn, obj) |