Package: gentag
The Python packagegentagprovides simple and powerful tagging for arbitrary
Python objects. After defining your tags and associated objects you can query
for the difference, intersection and union of tags to select specific objects.
The package is currently tested on cPython 2.6, 2.7, 3.4, 3.5, 3.6 and PyPy
(2.7).StatusInstallationUsageCreating a scopeDefining tagsQuerying tagsSupported operatorsThe default tagNamed composite tagsHistoryAbout the nameContactLicenseStatusWhile the ideas behindgentaghave been floating around in my head since
2012 I didn’t publish this as a standalone Python package until 2018 which
explains why I’m publishing the initial version as a beta. Looking ahead
towards the future:It may be that the current version serves my needs fine and at some point I
decide to replace the ‘beta’ label with a ‘stable’ label without making any
substantive changes.Releasinggentagis one step in the direction of releasing another Python
package that I’ve been thinking about for a very long time now and if I turn
out to have trouble integratinggentaginto that package I won’t hesitate
to make (potentially major) changes togentag.InstallationThegentagpackage is available onPyPIwhich means installation should be
as simple as:$pipinstallgentagThere’s actually a multitude of ways to install Python packages (e.g. theper
user site-packages directory,virtual environmentsor just installing
system wide) and I have no intention of getting into that discussion here, so
if this intimidates you then read up on your options before returning to these
instructions ;-).UsageThe following sections give an overview of how to get started. For more details
about the Python API please refer to the API documentation available onRead
the Docs.Creating a scopeDefining tagsQuerying tagsSupported operatorsThe default tagNamed composite tagsCreating a scopeTo get started you have to create aScopeobject:>>>fromgentagimportScope>>>tags=Scope()The purpose ofScopeobjects is to group together related tags into an
evaluation context for tag expressions.Defining tagsScopeinstances allow you to define tags and associated objects:>>>tags.define('archiving',['deb','tar','zip'])>>>tags.define('compression',['bzip2','deb','gzip','lzma','zip'])>>>tags.define('encryption',['gpg','luks','zip'])Querying tagsOnce you’ve defined some tags and associated objects you can query them,
for example here we query for the union of two tags:>>>tags.evaluate('archiving | encryption')['deb','gpg','luks','tar','zip']These tag expressions can get arbitrarily complex:>>>tags.evaluate('(archiving | encryption) & compression')['deb','zip']Supported operatorsThe following operators can be used to compose tags:OperatorSet operation&intersection|union-difference^symmetric differenceThese operators create newTagobjects that can be composed further. Although
tags composed at runtime in Python syntax don’t have a name, it is possible
define named composite tags using theScope.define()method (see below).The default tagThere’s one special tag that is always available under the name ‘all’. As you
might have guessed it provides access to a set with all tagged objects:>>>tags.evaluate('all')['bzip2','deb','gpg','gzip','luks','lzma','tar','zip']This can be useful to select all but a specific tag of objects:>>>tags.evaluate('all - encryption')['bzip2','deb','gzip','lzma','tar']Named composite tagsThe expressions shown in thequerying tagssection above demonstrate that
tags can be composed using set operators. You can also define a named tag based
on an expression:>>>tags.define('flexible','archiving & compression & encryption')Such named composite tags can be evaluated like regular tags:>>>tags.evaluate('flexible')['zip']You can also nest composite tags inside other composite tags.HistoryThe example in theusagesection isn’t actually very useful, this is partly
because I didn’t want a complicated subject matter to distract readers from
usage instructions :-).The actual use case that triggered the ideas behindgentagpresented itself
to me in 2012 when I wanted to query a database of more than 200 Linux server
names categorized by aspects such as:The distributor id (a string like ‘debian’ or ‘ubuntu’).The distribution codename (a string like ‘trusty’ or ‘xenial’).The server’s role (database, mailserver, webserver, etc).The server’s environment (production, development).The easy selection of subsets of servers for my Python programs to operate on
quickly evolved into my main interface for selecting groups of servers. Since
then I’ve wanted to use similar functionality in other places, but found it too
much work to develop one-off solutions. This is howgentagwas born.About the nameThe namegentagstands for “generative tags”, because the package allows new
tags to be composed (generated) from existing tags. I’d like to thank my
colleagueSeán Murphyfor coming up with
this name :-).ContactThe latest version ofgentagis available onPyPIandGitHub. The
documentation is hosted onRead the Docs. For bug reports please create an
issue onGitHub. If you have questions, suggestions, etc. feel free to send me
an e-mail atpeter@peterodding.com.LicenseThis software is licensed under theMIT license.© 2018 Peter Odding.