Package: counterparts
Thecounterpartsmodule takes mappings, specified via files in theConfigParser[1]format (default file name:.counterc), and
uses them to look up a string value corresponding to each string that
it is given.  For example, given a file with a different path in your
present tree than in another tree, when generating a list of files,
you might wish to automatically substitute that other tree’s path (the
counterpart of the present path).  First you would keep a list of
those special cases in a human-readable config file, and second,
arrange to let your shell or Python script use whatevercounterpartsfinds.Thecounterpartcommand provides shell access to the string
mapping abilities of thecounterpartsmodule.  Help for that
command is available[2] by runningcounterpart--help.Notice the slightly different names ofcounterpart(the shell
command) andcounterparts(the Python module).  Besides giving a
clue as to which is being referred to, the choice of names reflects
that the commandis for looking up a counterpartwhereas the moduleis a more general treatment of counterparts.  Except where noted,
thecounterpartcommand and thecounterpartsmodule behave the
same: The command is essentially a front-end to the module’sget_counterpart_mappingfunction; it runs the input string(s)
through the returned mapping, echoing the results as specified.[1]https://docs.python.org/2/library/configparser.html[2]counterpartis available after installingcounterpartsand updating yourPATHenvironment variable if necessary.RequirementsPython 2.6+ and Python 3 are supported.Tests have been run (and passed) on:Mac OS X 10.5 and 10.8, using Python 2.7 and 3.4.Installationpipis the recommended way to obtain and installcounterparts:pip install counterpartsWritten in Python, this package’s source code is on GitHub:git clone https://github.com/lionel/counterpartsFrom the top-level source directory, the usualsetuptoolsoperations
are available, i.e.:python setup.py installUsage SummaryBy default,counterpartstries to read both~/.countercand./.counterc.  Their existence is optional.  Any additional config
files specified by the caller are mandatory.  In general,ConfigParseroverrides earlier values with ones from files read
later, so values in a user-supplied config file take precedence over
the default files when they exist.Given a.countercfile in the PWD containing:[COUNTERPART_MAP]
foo = barUsing thecounterpartcommand:$ counterpart foo
bar
$

$ diff foo `counterpart foo`
# output diff between foo and bar

$ counterpart baz
Traceback (most recent call last):
...
KeyError: 'Mapping not found in COUNTERPART_MAP: baz'
$BecausecounterpartsexpectsConfigParser-format files, the
sections in[SQUARE BRACES]are case sensitive, but theoptionlines (left-hand side) ignore case.  Therefore, in the above config
example:foo,Foo, andFOOwould all map tobar, even
though[COUNTERPART_map]willnotwork correctly in place of[COUNTERPART_MAP].Next, using thecounterpartsmodule:import counterparts
before = "foo"
after = counterparts.map_counterpart(before)

# or, to avoid need for repeated map_counterpart calls to re-read config file(s):
mapping = counterparts.get_counterpart_mapping()
after = mapping[before]
# the variable 'after' is assigned the value '"bar"'You can specify, via aCOUNTERPART_DIRsection, a default mapping
for strings (“paths” in this case) that are not listed in theCOUNTERPART_MAP.  Theprepend_pathoption in theCOUNTERPART_DIRsection tellscounterpartsto prepend its value
to any input that doesn’t hit in theCOUNTERPART_MAP.So, for example, given the.counterc:[DEFAULT]
up = ..
[COUNTERPART_MAP]
foo = %(home)s/bar
[COUNTERPART_DIR]
prepend_path = %(up)s/quux

$ counterpart baz
../quux/baz
$The previous.countercexample also shows another feature:homeis pre-populated in theDEFAULTsection.  Hence, you can
manually provide a path relative to$HOMEto use in the other
sections’ right-hand-side values:$ [ `counterpart foo` == "$HOME/bar" ] && echo '%(home)s equals $HOME'
%(home)s equals $HOME
$Finally,counterpartsalso supports anINCLUDEdirective.  It
is specified as a section by that same name, and it accepts apathsoption, which is a newline-separated list of one or more
other config files.  Some files that demonstrate valid uses of theINCLUDEsection are:tests/counterparts_data/conf-include-loggingtests/counterparts_data/conf-include-moretests/counterparts_data/conf-2-with-includetests/counterparts_data/conf-include-still-moreTheINCLUDEsection has proven useful for things like controlling
logging, setting site-specific options, and picking up global
defaults.Configuration FileThe configuration file is in the format used by theConfigParsermodule.  SeeDocumentation, below, for more about the format.The special sections and options used bycounterpartsare
described above in theUsage Summary.Thesectionsandoptionscan be read from the config files of
other applications, as long as those applications ignore unknown
sections andcounterpartsis told to look in those files.If no configuration file is provided tocounterparts, it looks
first in./.countercand second in~/.counterc.DocumentationFor the most part, you’re looking at it.For some useful information onConfigParser-format files, see:https://docs.python.org/2/library/configparser.htmlLicensecounterpartsis released under the GPLv2, contained in theLICENSE.txtfile.AuthorsCopyright (c) 2015 by Lionel D. Hummel.RoadmapI putcounterpartsup on GitHub to give me a bite-sized (but
meaningful) sample with which to explore the site’s features such as
continuous integration and documentation.  So this is what I’ve got
for its roadmap so far:More tests and documentation are needed.I’m glad to discuss an expanded roadmap ifcounterpartsproves
useful to any contributors besides myself.Contributingcounterpartsis meant to be a solid, idiomatic, and readable
example of Python code.  I can think of several ways it is not quite
there yet in this release.  If you’ve got one in mind, please use the
GitHub page to contact the author, ask questions, report bugs, suggest
patches, receive updates, etc.:https://github.com/lionel/counterparts