tri.token


Nametri.token JSON
Version 4.0.0 PyPI version JSON
download
home_pagehttps://github.com/TriOptima/tri.token
Summarytri.token provides enriched enum functionality
upload_time2023-03-10 14:59:30
maintainer
docs_urlNone
authorJohan Lübcke
requires_python
licenseBSD
keywords tri.token
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI
coveralls test coverage No coveralls.
            .. image:: https://travis-ci.org/TriOptima/tri.token.svg?branch=master
    :target: https://travis-ci.org/TriOptima/tri.token


.. image:: https://codecov.io/github/TriOptima/tri.token/coverage.svg?branch=master
    :target: https://codecov.io/github/TriOptima/tri.token?branch=master


tri.token
=========

tri.token provides enriched enum functionality. tri.token enum structures are declared using:

- TokenAttribute: overridable attribute definitions with support for dynamic values.
- Token: holds TokenAttributes objects.
- TokenContainer: holds Token objects.

In other words: a Token is an enum which has TokenInstance members. Token instances are declared within TokenContainer(s).


Basic usage
-----------

.. code:: python

    from tri_token import Token, TokenAttribute, TokenContainer, PRESENT


    class Taste(Token):
        name = TokenAttribute()
        display_name = TokenAttribute(value=lambda name, **_: name.upper() + '!!')
        opinion = TokenAttribute()


    class Tastes(TokenContainer):
        vanilla = Taste()
        pecan_nut = Taste(display_name="pecan nutz", opinion="Tasty")


    # A TokenContainer is a collection of Token objects.
    assert Tastes.vanilla in Tastes

    # The order of Token objects in a TokenContainer is by order of declaration.
    assert list(Tastes) == [Tastes.vanilla, Tastes.pecan_nut]
    assert list(Tastes) != [Tastes.pecan_nut, Tastes.vanilla]

    # Magic for 'name' TokenAttribute. It is set automatically from the token declaration within it's container.
    assert Tastes.vanilla.name == "vanilla"

    # A TokenAttribute will have a None value if not set during Token instantiation.
    assert Tastes.vanilla.opinion is None

    # A TokenAttribute can have a dynamic value, derived from the invocation to the callable
    # set as 'value' in the TokenAttribute definition
    # (see declaration of 'display_name' TokenAttribute further up in the code).

    # The real value of the token attribute will be the return value of an invocation to said callable.
    # The invocation will receive the values of all other token attributes passed as keyword arguments.
    assert Tastes.vanilla.display_name == "VANILLA!!"

    # TokenAttribute dynamic value behavior is overridden/not used if value is set explicitly during Token instantiation.
    assert Tastes.pecan_nut.display_name == "pecan nutz"

    # A TokenContainer can be rendered as csv, excel, rst etc
    assert """\
    +--------------+---------+
    | display_name | opinion |
    +==============+=========+
    |  VANILLA!!   |         |
    +--------------+---------+
    |  pecan nutz  |  Tasty  |
    +--------------+---------+\
    """ == Tastes.to_rst(['display_name', 'opinion'])


Optional token attributes
-------------------------

.. code:: python

    # A TokenAttribute may be declared as having optional dynamic values.
    # That is, we want these dynamic attributes to be evaluated sometimes, but not always.
    # In the example below, we want some superheroes to have homes, but not others.

    SUPERHERO_HOMES = {'superman': 'Fortress of Solitude',
                       'batman': 'Batcave'}


    class Superhero(Token):
        name = TokenAttribute()
        home = TokenAttribute(optional_value=lambda name, **_: SUPERHERO_HOMES[name])


    # The PRESENT special value is used during Token instantiation to decide what
    # optional token attributes should be evaluated.
    class Superheroes(TokenContainer):
        batman = Superhero(home=PRESENT)
        hawkman = Superhero()
        wonder_woman = Superhero(home='Themyscira')

    # Batman has a home, but poor Hawkman does not.
    assert Superheroes.batman.home == 'Batcave'
    assert Superheroes.hawkman.home is None

    # Just as with dynamic attributes, the logic for TokenAttribute optional dynamic values is overridden
    if value is set explicitly during Token instantiation.
    assert Superheroes.wonder_woman.home = 'Themyscira'

    # As a shortcut, PRESENT for specific optional token attributes may be assigned to
    # variables, and used in declarations, for enhanced readability.
    # This is useful when one has tokens with many attributes declared using dynamic values,
    # but we don't want all of them to be evaluated in all tokens.
    home = PRESENT('home')

    class Superheroes(TokenContainer):
        batman = Superhero(home)
        hawkman = Superhero()

    # Again, Batman has a home, but poor Hawkman does not.
    assert Superheroes.batman.home == 'Batcave'
    assert Superheroes.hawkman.home is None


TokenAttribute inheritance
--------------------------

.. code:: python

    class FooToken(Token):
        foo = TokenAttribute(value=lambda **kwargs: 'foo_value')

    class BarToken(Token):
        bar = TokenAttribute()

    class FieToken(FooToken, BarToken):
        fie = TokenAttribute()

    class FooBarFieTokenContainer(TokenContainer):
        t = FieToken(fie=3)

    assert dict(FooBarFieTokenContainer.t) == {'foo': 'foo_value', 'bar': None, 'name': 't', 'fie': 3}


TokenAttribute container inheritance
------------------------------------

.. code:: python

    class MyToken(Token):

        name = TokenAttribute()
        stuff = TokenAttribute()


    class MyTokens(TokenContainer):

        foo = MyToken(stuff='Hello')
        bar = MyToken(stuff='World')

    assert MyTokens.foo in MyTokens

    class MoreTokens(MyTokens):
        boink = MyToken(stuff='Other Stuff')

    assert MyTokens.foo in MoreTokens

    assert list(MoreTokens) == [MyTokens.foo, MyTokens.bar, MoreTokens.boink]
    assert MoreTokens.foo is MyTokens.foo


For more tri.token examples, please have a look at the contents of tests/test_tokens.py in the installation directory.

.. _test_tokens: tests/test_tokens.py


Running tests
-------------

You need tox installed then just `make test`.


License
-------

BSD


Documentation
-------------

http://tritoken.readthedocs.org.



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/TriOptima/tri.token",
    "name": "tri.token",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "tri.token",
    "author": "Johan L\u00fcbcke",
    "author_email": "johan.lubcke@trioptima.com",
    "download_url": "https://files.pythonhosted.org/packages/bb/2f/90a8b665507ca872c0cc8d0224ba6025af5c2b408e8a032a1a68c347698b/tri.token-4.0.0.tar.gz",
    "platform": null,
    "description": ".. image:: https://travis-ci.org/TriOptima/tri.token.svg?branch=master\n    :target: https://travis-ci.org/TriOptima/tri.token\n\n\n.. image:: https://codecov.io/github/TriOptima/tri.token/coverage.svg?branch=master\n    :target: https://codecov.io/github/TriOptima/tri.token?branch=master\n\n\ntri.token\n=========\n\ntri.token provides enriched enum functionality. tri.token enum structures are declared using:\n\n- TokenAttribute: overridable attribute definitions with support for dynamic values.\n- Token: holds TokenAttributes objects.\n- TokenContainer: holds Token objects.\n\nIn other words: a Token is an enum which has TokenInstance members. Token instances are declared within TokenContainer(s).\n\n\nBasic usage\n-----------\n\n.. code:: python\n\n    from tri_token import Token, TokenAttribute, TokenContainer, PRESENT\n\n\n    class Taste(Token):\n        name = TokenAttribute()\n        display_name = TokenAttribute(value=lambda name, **_: name.upper() + '!!')\n        opinion = TokenAttribute()\n\n\n    class Tastes(TokenContainer):\n        vanilla = Taste()\n        pecan_nut = Taste(display_name=\"pecan nutz\", opinion=\"Tasty\")\n\n\n    # A TokenContainer is a collection of Token objects.\n    assert Tastes.vanilla in Tastes\n\n    # The order of Token objects in a TokenContainer is by order of declaration.\n    assert list(Tastes) == [Tastes.vanilla, Tastes.pecan_nut]\n    assert list(Tastes) != [Tastes.pecan_nut, Tastes.vanilla]\n\n    # Magic for 'name' TokenAttribute. It is set automatically from the token declaration within it's container.\n    assert Tastes.vanilla.name == \"vanilla\"\n\n    # A TokenAttribute will have a None value if not set during Token instantiation.\n    assert Tastes.vanilla.opinion is None\n\n    # A TokenAttribute can have a dynamic value, derived from the invocation to the callable\n    # set as 'value' in the TokenAttribute definition\n    # (see declaration of 'display_name' TokenAttribute further up in the code).\n\n    # The real value of the token attribute will be the return value of an invocation to said callable.\n    # The invocation will receive the values of all other token attributes passed as keyword arguments.\n    assert Tastes.vanilla.display_name == \"VANILLA!!\"\n\n    # TokenAttribute dynamic value behavior is overridden/not used if value is set explicitly during Token instantiation.\n    assert Tastes.pecan_nut.display_name == \"pecan nutz\"\n\n    # A TokenContainer can be rendered as csv, excel, rst etc\n    assert \"\"\"\\\n    +--------------+---------+\n    | display_name | opinion |\n    +==============+=========+\n    |  VANILLA!!   |         |\n    +--------------+---------+\n    |  pecan nutz  |  Tasty  |\n    +--------------+---------+\\\n    \"\"\" == Tastes.to_rst(['display_name', 'opinion'])\n\n\nOptional token attributes\n-------------------------\n\n.. code:: python\n\n    # A TokenAttribute may be declared as having optional dynamic values.\n    # That is, we want these dynamic attributes to be evaluated sometimes, but not always.\n    # In the example below, we want some superheroes to have homes, but not others.\n\n    SUPERHERO_HOMES = {'superman': 'Fortress of Solitude',\n                       'batman': 'Batcave'}\n\n\n    class Superhero(Token):\n        name = TokenAttribute()\n        home = TokenAttribute(optional_value=lambda name, **_: SUPERHERO_HOMES[name])\n\n\n    # The PRESENT special value is used during Token instantiation to decide what\n    # optional token attributes should be evaluated.\n    class Superheroes(TokenContainer):\n        batman = Superhero(home=PRESENT)\n        hawkman = Superhero()\n        wonder_woman = Superhero(home='Themyscira')\n\n    # Batman has a home, but poor Hawkman does not.\n    assert Superheroes.batman.home == 'Batcave'\n    assert Superheroes.hawkman.home is None\n\n    # Just as with dynamic attributes, the logic for TokenAttribute optional dynamic values is overridden\n    if value is set explicitly during Token instantiation.\n    assert Superheroes.wonder_woman.home = 'Themyscira'\n\n    # As a shortcut, PRESENT for specific optional token attributes may be assigned to\n    # variables, and used in declarations, for enhanced readability.\n    # This is useful when one has tokens with many attributes declared using dynamic values,\n    # but we don't want all of them to be evaluated in all tokens.\n    home = PRESENT('home')\n\n    class Superheroes(TokenContainer):\n        batman = Superhero(home)\n        hawkman = Superhero()\n\n    # Again, Batman has a home, but poor Hawkman does not.\n    assert Superheroes.batman.home == 'Batcave'\n    assert Superheroes.hawkman.home is None\n\n\nTokenAttribute inheritance\n--------------------------\n\n.. code:: python\n\n    class FooToken(Token):\n        foo = TokenAttribute(value=lambda **kwargs: 'foo_value')\n\n    class BarToken(Token):\n        bar = TokenAttribute()\n\n    class FieToken(FooToken, BarToken):\n        fie = TokenAttribute()\n\n    class FooBarFieTokenContainer(TokenContainer):\n        t = FieToken(fie=3)\n\n    assert dict(FooBarFieTokenContainer.t) == {'foo': 'foo_value', 'bar': None, 'name': 't', 'fie': 3}\n\n\nTokenAttribute container inheritance\n------------------------------------\n\n.. code:: python\n\n    class MyToken(Token):\n\n        name = TokenAttribute()\n        stuff = TokenAttribute()\n\n\n    class MyTokens(TokenContainer):\n\n        foo = MyToken(stuff='Hello')\n        bar = MyToken(stuff='World')\n\n    assert MyTokens.foo in MyTokens\n\n    class MoreTokens(MyTokens):\n        boink = MyToken(stuff='Other Stuff')\n\n    assert MyTokens.foo in MoreTokens\n\n    assert list(MoreTokens) == [MyTokens.foo, MyTokens.bar, MoreTokens.boink]\n    assert MoreTokens.foo is MyTokens.foo\n\n\nFor more tri.token examples, please have a look at the contents of tests/test_tokens.py in the installation directory.\n\n.. _test_tokens: tests/test_tokens.py\n\n\nRunning tests\n-------------\n\nYou need tox installed then just `make test`.\n\n\nLicense\n-------\n\nBSD\n\n\nDocumentation\n-------------\n\nhttp://tritoken.readthedocs.org.\n\n\n",
    "bugtrack_url": null,
    "license": "BSD",
    "summary": "tri.token provides enriched enum functionality",
    "version": "4.0.0",
    "split_keywords": [
        "tri.token"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8562b2b7257d281cd0ebc5f03c1c02edf9ca90a4a0821f7394a352eb01ac539d",
                "md5": "89fa086f2cee8ce098ed72dcf611f380",
                "sha256": "56c491bed5996567130ca4e58bd70c81362e1ed17e9888883d7e64055aacf15d"
            },
            "downloads": -1,
            "filename": "tri.token-4.0.0-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "89fa086f2cee8ce098ed72dcf611f380",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": null,
            "size": 8033,
            "upload_time": "2023-03-10T14:59:28",
            "upload_time_iso_8601": "2023-03-10T14:59:28.881121Z",
            "url": "https://files.pythonhosted.org/packages/85/62/b2b7257d281cd0ebc5f03c1c02edf9ca90a4a0821f7394a352eb01ac539d/tri.token-4.0.0-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bb2f90a8b665507ca872c0cc8d0224ba6025af5c2b408e8a032a1a68c347698b",
                "md5": "311d8c63b823cd9f37a649bc6fb964e8",
                "sha256": "17ab78a63ac2efbfd99ce63d8e04aad0de312f01ca91a3a4ca9ad80e54be8516"
            },
            "downloads": -1,
            "filename": "tri.token-4.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "311d8c63b823cd9f37a649bc6fb964e8",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 10584,
            "upload_time": "2023-03-10T14:59:30",
            "upload_time_iso_8601": "2023-03-10T14:59:30.798503Z",
            "url": "https://files.pythonhosted.org/packages/bb/2f/90a8b665507ca872c0cc8d0224ba6025af5c2b408e8a032a1a68c347698b/tri.token-4.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-03-10 14:59:30",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "TriOptima",
    "github_project": "tri.token",
    "travis_ci": true,
    "coveralls": false,
    "github_actions": false,
    "requirements": [],
    "test_requirements": [],
    "tox": true,
    "lcname": "tri.token"
}
        
Elapsed time: 0.04257s