# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['dyndis']

package_data = \
{'': ['*']}

install_requires = \
['sortedcontainers']

setup_kwargs = {
    'name': 'dyndis',
    'version': '0.2.0',
    'description': '',
    'long_description': '# Dyndis\n\n[`pip install dyndis`](https://pypi.org/project/dyndis/)\n\n## About\n\nDyndis is a library to easily and fluently make multiple-dispatch functions and methods. It was originally made for\noperators in non-strict hierarchical systems but can also serve any other multiple-dispatch purpose.\n\n## Simple Example\n\n```python\nfrom typing import Union\n\nfrom dyndis import MultiDispatch\n\n\n@MultiDispatch\ndef foo(a, b):\n    # default implementation in case no candidates match\n    raise TypeError\n\n\n@foo.register()\ndef _(a: int, b: Union[int, str]):\n    return "overload 1 <int, (int|str)>"\n\n\n@foo.register()\ndef _(a: object, b: float):\n    return "overload 2 <any, float>"\n\n\nfoo(1, "hello")  # overload 1\nfoo(("any", "object", "here"), 2.5)  # overload 2\nfoo(2, 3)  # overload 1\nfoo(2, 3.0)  # overload 2\n```\n\n## Features\n\n* dynamic upcasting.\n* seamless usage of type-hints and type variables.\n* advanced data structures to minimize candidate lookup time.\n* implementor interface makes it easy to create method-like overloads\n\n## How Does it Work?\n\nThe central class (and only one users need to import) is `MultiDispatch`. `MultiDispatch` contains candidate\nimplementations sorted by both priority and types of the parameters they accept. When the `MultiDispatch` is called, it\ncalls its relevant candidates (ordered by both priority, inheritance, and compatibility, expanded upon below) until one\nreturns a non-`NotImplemented` return value.\n\n## The Lookup Order\n\nAll candidates for parameters of types <T0, T1, T2..., TN> are ordered as follows:\n\n* Any candidate with a types that is incompatible with any type in the key is excluded. That is, if for any 0 <= `i` <=\n  N, a candidate\'s type constraint for parameter `i` is not a superclass of Ti, the candidate is excluded.\n* Candidates are ordered by inheritance. A candidate is considered to inherit another candidate if all its parameter\n  types are subclasses of (or are likewise covered by) the other\'s respective parameter type. A candidate will be\n  considered before any other candidate it inherits. So for example, <int,object> will be considered before <Number,\n  object>.\n\nIf there are two candidates that do not inherit each other, an exception (of type `dyndis.AmbiguityError`) is raised (\nunless a candidate with greater precedence than both succeeds first).\n\nIf a candidate returns `NotImplemented`, the next candidate in the order is tried. If no candidates are accepted or all\ncandidates returned `NotImplemented`, the default implementation is called.\n\n## Topology and Caches\n\n`dyndis` uses a topological set to order all its candidates by the parameter types, so that most of the candidates can\nbe disregarded without any overhead.\n\nConsidering all these candidates for every lookup gets quite slow and encumbering very quickly. For this reason,\nevery `MultiDispatch` automatically caches these computation for both sorting and processing candidates.\n\n## Default, Variadic, and Keyword parameters\n\n* If a candidate has positional parameters with a default value and a type annotation, the default value will be ignored\n  for the purposes of candidate resolution.\n* If a candidate has a variadic positional parameter, it is ignored. When called from a `MultiDispatch`, its value will\n  always be `()`.\n* If a candidate has keyword-only parameters, the parameter will not be considered for candidate types, it must either\n  have a default value or be set when the `MultiDispatch` is called.\n* If a candidate has a variadic keyword parameter, it is ignored. When called from a `MultiDispatch`, its value will be\n  according to the (type-ignored) keyword arguments.\n\nIn general, when a `MultiDispatch` is called with keyword arguments, those arguments are not considered for candidate\nresolution and are sent to each attempted candidate as-is.\n\n## Implementors\n\nan `Implementor` is a descriptor that makes it easy to create method-like candidates inside classes.\n\n```python\nfrom dyndis import MultiDispatch\n\n\n@MultiDispatch\ndef add(self, other):\n    return NotImplemented\n\n\nclass Base:\n    __add__ = add\n\n\nclass A(Base):\n    @add.implement(__qualname__)\n    def add(self, other: \'A\'):\n        # in implementor methods, `self` is assumed to be of the owner class\n        return "A+A"\n\n    @add.implement(__qualname__)\n    def add(self, other: Base):\n        return "A+Base"\n\n\nclass B(Base):\n    @add.implement(__qualname__)\n    def add(self, other: A):\n        return \'B+A\'\n\n\na = A()\nb = B()\nbase = Base()\na + b  # A+B\na + base  # A+Base\na + a  # A+A\n```\n\n## Special Type Annotations\n\ntype annotations can be of any type, or among any of these special values\n\n* `typing.Union`: accepts parameters of any of the enclosed type\n* `typing.Optional`: accepts the enclosed type or `None`\n* `typing.Any`: is considered a supertype for any type, including `object`\n* Any of typing\'s aliases and abstract classes such as `typing.List` or `typing.Sized`: equivalent to their origin\n  type (note that specialized aliases such as `typing.List[str]` are invalid)\n* `typing.TypeVar`: see below\n* `None`, `...`, `NotImplemented`: equivalent to their types\n\n## `TypeVar` annotations\n\nParameters can also be annotated with `typing.TypeVar`s. These variables bind greedily as they are encountered, and\ncount as matched upon first binding. After first binding, they are treated as the bound type (or the lowest constraint\nof the `TypeVar`) for all respects.\n\n```python\nfrom typing import TypeVar, Any\n\nfrom dyndis import MultiDispatch\n\nT = TypeVar(\'T\')\n\n\n@MultiDispatch\ndef foo(*args):\n    raise TypeError\n\n\n@foo.register()\ndef _(a: T, b: T):\n    return "type(b) <= type(a)"\n\n\n@foo.register()\ndef _(a: Any, b: Any):\n    return "type(b) </= type(a"\n\n\nfoo(1, 1)  # <=\nfoo(1, True)  # <=\nfoo(2, \'a\')  # </=\nfoo(object(), object())  # <=\n# type variables bind greedily, meaning their exact value will be equal to the first type they encounter\nfoo(False, 2)  # </=\n```\n',
    'author': 'ben avrahami',
    'author_email': 'dontcallme@illcall.you',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/bentheiii/dyndis',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
