Package: tri.token
tri.tokentri.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 usagefromtri_tokenimportToken,TokenAttribute,TokenContainer,PRESENTclassTaste(Token):name=TokenAttribute()display_name=TokenAttribute(value=lambdaname,**_:name.upper()+'!!')opinion=TokenAttribute()classTastes(TokenContainer):vanilla=Taste()pecan_nut=Taste(display_name="pecan nutz",opinion="Tasty")# A TokenContainer is a collection of Token objects.assertTastes.vanillainTastes# The order of Token objects in a TokenContainer is by order of declaration.assertlist(Tastes)==[Tastes.vanilla,Tastes.pecan_nut]assertlist(Tastes)!=[Tastes.pecan_nut,Tastes.vanilla]# Magic for 'name' TokenAttribute. It is set automatically from the token declaration within it's container.assertTastes.vanilla.name=="vanilla"# A TokenAttribute will have a None value if not set during Token instantiation.assertTastes.vanilla.opinionisNone# 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.assertTastes.vanilla.display_name=="VANILLA!!"# TokenAttribute dynamic value behavior is overridden/not used if value is set explicitly during Token instantiation.assertTastes.pecan_nut.display_name=="pecan nutz"# A TokenContainer can be rendered as csv, excel, rst etcassert"""\+--------------+---------+
| display_name | opinion |
+==============+=========+
|  VANILLA!!   |         |
+--------------+---------+
|  pecan nutz  |  Tasty  |
+--------------+---------+\"""==Tastes.to_rst(['display_name','opinion'])Optional token attributes# 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'}classSuperhero(Token):name=TokenAttribute()home=TokenAttribute(optional_value=lambdaname,**_:SUPERHERO_HOMES[name])# The PRESENT special value is used during Token instantiation to decide what# optional token attributes should be evaluated.classSuperheroes(TokenContainer):batman=Superhero(home=PRESENT)hawkman=Superhero()wonder_woman=Superhero(home='Themyscira')# Batman has a home, but poor Hawkman does not.assertSuperheroes.batman.home=='Batcave'assertSuperheroes.hawkman.homeisNone# Just as with dynamic attributes, the logic for TokenAttribute optional dynamic values is overriddenifvalueissetexplicitlyduringTokeninstantiation.assertSuperheroes.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')classSuperheroes(TokenContainer):batman=Superhero(home)hawkman=Superhero()# Again, Batman has a home, but poor Hawkman does not.assertSuperheroes.batman.home=='Batcave'assertSuperheroes.hawkman.homeisNoneTokenAttribute inheritanceclassFooToken(Token):foo=TokenAttribute(value=lambda**kwargs:'foo_value')classBarToken(Token):bar=TokenAttribute()classFieToken(FooToken,BarToken):fie=TokenAttribute()classFooBarFieTokenContainer(TokenContainer):t=FieToken(fie=3)assertdict(FooBarFieTokenContainer.t)=={'foo':'foo_value','bar':None,'name':'t','fie':3}TokenAttribute container inheritanceclassMyToken(Token):name=TokenAttribute()stuff=TokenAttribute()classMyTokens(TokenContainer):foo=MyToken(stuff='Hello')bar=MyToken(stuff='World')assertMyTokens.fooinMyTokensclassMoreTokens(MyTokens):boink=MyToken(stuff='Other Stuff')assertMyTokens.fooinMoreTokensassertlist(MoreTokens)==[MyTokens.foo,MyTokens.bar,MoreTokens.boink]assertMoreTokens.fooisMyTokens.fooFor more tri.token examples, please have a look at the contents of tests/test_tokens.py in the installation directory.Running testsYou need tox installed then justmake test.LicenseBSDDocumentationhttp://tritoken.readthedocs.org.