Package: yay
Yay is a non-strict lazily evaluated configuration language. It combines
YAML-like data declarations with lazy python expressions. We really hope you
like this, please let us know if it’s useful.It works with python 2.6+, 3.2+ and pypy 1.9.Yay is very new software, and although we have tested it a lot it is
certainly full of bugs. Please subscribe to the yaybu-dev mailing list, which
you can find onhttp://lists.yaybu.com.All documentation can be found athttp://yay.readthedocs.org/en/latest/which
includes a tour of the language and an explanation of the grammar.If you are interested in this project, you should probably check out Yaybu,
which uses Yay to drive a complete system deployment and management system.
You can find Yaybu athttp://yaybu.com.Changelog for yay3.1.1 (2013-11-06)Nothing changed yet.3.1.0 (2013-11-06)Now supported on python 3.2 and python 3.3 (in addition to 2.6, 2.7 and
pypy).Many fixes to YAML multiline block modeLots of test coverage improvementsRemove unnecessary support for Extended SlicesCommand line output is prettier3.0.1 (2013-09-04)Nothing changed yet.3.0 (2013-09-04)This is a full rewrite on top of the ply parsing framework.0.0.62 (2012-09-27)Try importing first as it might yield a hit and save checking the internets
for things.0.0.61 (2012-09-15)An earlier version added validation to stop you replacing lists with mappings
or vice versa. However the implementation didn’t consider that you might
extend a mapping that comes from a lookup.0.0.60 (2012-09-15)Fix filter node. It was previously unaware of its parent when expanded and
this stopped its children from being able to look up values in the global
namespace.0.0.59 (2012-09-01)Fix setting GPG_TTY.0.0.58 (2012-08-15)Capture GPG failures and throw exceptions. Unfortunately without talking to
GPG over the status fd we can’t get much information about what went wrong.Run in batch mode. This stops GPG from ignoring the stdout/stderr redirection
but means you nowMUSTuse a GPG agent as it can no longer prompt for a
passphrase.GPG_TTY is set - this means gpg-agent can actually prompt now.FixConfig.addwhen using nested dictionaries.0.0.57 (2012-08-02)Add new lazy lookup method to the root config object. This is useful if you
are building a lazy iterator over a dictionary key:def example_iterator(self, expression):
    try:
        for item in expression.expand():
            resolved = item.resolve()
            create_obj_from_settings(resolved)
    except CreateObjectError:
        # You can get line and column from the item object!
    except yay.errors.Error:
        # Ideal place to wrap Yay errors in your apps exceptions

example_iterator(config.lookup("somekey"))You can see here that the API lets you defer any messy “key not found”
exceptions until the iterator needs to access they key - and the iterator
already has apropriate exception handling.Add additional test cases for backwards compatibility0.0.56 (2012-07-31)Code paths are now decorated with tracing context. This__context__metadata gives a sense of what yay was doing when it went off the handle.0.0.55 (2012-07-25)Fix PackageIndex to not warn() on missing package - we capture this
ourselves!0.0.54 (2012-07-22)Line number and file information should be available for nodes that have been
cloned leading to much more useful error output.Index errors on Sequence nodes will be properly dealt withTreating a sequence as a mapping node will trigger an appropriate Yay error.0.0.53 (2012-07-21)Allow python code using yay to set default configuration for openers0.0.52 (2012-07-21)Fix regression inpackage://for existing users..0.0.51 (2012-07-19)Introduce a lazily evaluated mechanism for expanding the search path:.search:
  - package://some.egg/
  - http://raw.github.com/isotoma/yay/Any subsequent.importstatements will use the modified search path.If a package specified either as part of a .include or as part of a .search
is not available on sys.path then an attempt will be made to install it.Can pass config to opener backends using.config. For example, you might
want to have thepackage://opener to use your internal package
repository:.config:
    openers:
        packages:
            index: https://my-python-mirror/simple/
            username: joe
            password: penguin55You can use variable subsitution and to define the password in a GPG
encrypted yay file or to push the variable from application that is using
Yay.Yay openers support basic auth in the url. If used with .include then use of
secrets to concatenate to hide the password is suggsted:# Define ${password} in a GPG armored file
.include: home://.credentials.yay.gpg

.search:
  - https://username:${password}@svn.yourcompany.org/svn/cookbook/trunk.includeand.searchmay be a single scalar value rather than a list
if you desire.0.0.50 (2012-07-10)Allow expressions to return an empty dictionary:result: ${site.vhosts else {}}0.0.49 (2012-06-27)Added a string replacement function allowing people to do things like:something: jolly good show
slug: ${replace(something, " ", "-")}thereafter the value ofslugwill bejolly-good-show.0.0.48 (2012-04-07)Support in operator during foreach:result.foreach v in somevalues if v in somelist: ${v}.0.0.47 (2012-04-06)Allow expressions to contain literal strings and floats:result: ${site.description else "No description"}
result2: ${3.212121}Allow expressions to return an empty list:result: ${site.vhosts else []}Allow equality checks of undefined keys to pass or fail appropriately without
raising a NoMatching exception:data:
  part1:
    a: 1
  part2:
    c: 2

res1.foreach p in data if data[p].a = 2: ${p}
res2.foreach p in data if data[p].c != 1: ${p}res1 will be empty as neither part1 nor part2 have an a field with a value of
2, and res2 will contain part1 and part2 as neither have a c field wth a
value of 1.Add anundefinedthat raises a NoMatch exception when resolved. This
allows one to filter by whether or not a key is present in a mapping.data:part1:a: 1part2:c: 2res.foreach p in data if data[p].c = undefined: ${p}res will contain part1 as part1 doesn’t have a c field.0.0.46 (2012-04-04)Fixelseexpression inside an.include0.0.45 (2012-03-22)You can now pass an etag to the open method ofOpeners. This will throw a
NotModified exception if etag matching shows the request URI is unchanged.
This can be used to implement caching strategies and reduce the amount of data
that yay pulls over network connections:>>> from yay.openers import Openers
>>> fp = Openers().open("/tmp/somefile, etag="1234535462356456fa")
NotModified: File '/tmp/somefile' not modifiedAll openers will now have an etag property. This property can be None if a
suitable etag cannot be provided. Otherwise it should be some hash that
guarantees the state of the file so that later requests can just ask “has it
changed since it was in this state”. To get an etag:>>> from yay.openers import Openers
>>> fp = Openers().open("/tmp/somefile")
>>> print fp.etag
1234535462356456fa0.0.44 (2012-03-17)Fix .select when value that is resolved is a complicated expression.Better validation when you accidentally mix up list and mapping types.0.0.43 (2012-02-12)Fix handling of paths on searchpath without a scheme.0.0.42 (2012-01-01)Change how Django boxing works so that a .bind isn’t required for the
boxing mechanism to work. This allows raw Django mdoels to be pushed
into Yay using the.addAPI from 0.0.41.0.0.41 (2011-12-21)You can inject Python objects into the Yay Config object, as long as Yay
knows how to box them. If you had a Yay file like this:hello: abc
result: ${hello}And the following python code:from yay.config import Config
c = Config()
c.load_uri(example_file)
c.add(dict(hello="xyx"))Then the following assertion is true:c.get() == dict(hello="xyz", result="xyz")0.0.40 (2011-12-13)Fixes calling macros defined in other files.0.0.39 (2011-11-30)Fix string builder so that configs containing secrets can be pickled.0.0.38 (2011-11-22)This is a bugfix release to improve existing features, especially boxing of
foreign data.Move more code away from direct use ofBoxedtoBoxingFactory.boxWrap any dictionary objects in a Mapping object so they can be merged with
other mappings that come from within Yay.0.0.37 (2011-11-20)Brown paper bag release to remove stray print.0.0.36 (2011-11-20)There is now ahome://URL handler. For my laptop this means:import yay
yay.load_uri("home://foo/bar.yay")Is equivalent to:import yay
yay.load_uri("/home/john/foo/bar.yay")Improve searchpath handling to better cope with URIs.Add support forelsekeyword in expressions as per YEP2:foo:
    bar: ${foo.baz else 52}This is useful for providing sensible defaults in your recipes.The loop block is now autoflattening. This means that constructs that yield
lists of lists will be turned into 1-dimensional lists by.foreach. For
example:somelist:
  - - - a
      - b
    - c
  - d

someotherlist.foreach var in somelist: ${var}The listsomeotherlistwould now contain:somelist:
 - a
 - b
 - c
 - dThe previous behaviour can be obtained with thechainmodifier:somelist.foreach var in somelist chain: ${var}Add a simple macro language. This is highly EXPERIMENTAL and subject to
frequent syntax tweaks. You can define a reusable block of configuration
using the .define statement. An example of this in Yaybu to create a reusable
virtualenv step:.define Virtualenv:
  - Directory:
      name: ${venv.location}
      owner: ${venv.owner}
  - Execute:
      name: create-virtualenv-${venv.location}
      command: virtualenv --no-site-packages ${venv.location}
      creates: ${venv.location}/bin/pip
  - Execute:
      name: install-requirements-${venv.location}
      command: ${venv.location}/bin/pip install -r ${venv.requirements}The macro is callable inline as part of an expression. For example:resources.append:
  .foreach venv in virtualenvs: ${Virtualenv!}Equally you can do this:.define Virtualenv:
  - Directory:
      name: ${location}
      owner: ${owner}
# SNIP

resources.append:
    Virtualenv!:
      location: /tmp/example
      owner: dave
      requirements: /tmp/requirements.txt0.0.35 (2011-11-12)This release refactors ProtectedString to make it more useful outside Yay.
Instead of importingyay.protectedstring.ProtectedStringyou should
importyay.StringYou can now pass strings to the constructor and they will automatically be
wrapped. Previously you had to pass StringPart’s to the constructor. That is
now an internal implementation detail.There is now an extend() function. This accepts lists that contains a mixture
of raw strings and otherStringobjects:s = String("echo")
y = String("supersekritpassword", secret=True)
s.extend(["a", "b", y, "d"])There is now an as_list() function. This returns all the parts you have added
to a string. This is useful if you are building a command line to pass to
subprocess:s.String(["someprogram", "--pasword"])
s.add_secret("password")

# Log the obfuscated version but execute with the real password
log.info(s.protected)
p = subprocess.Popen(s.as_list(secret=False), cwd="/")There is now asecretcall in Yay for exercising secret Yay without
needing to use GPG. This is mainly for test purposes, but might be useful if
you have strings which arent closely guarded secrets yet you dont want them
show in logs. To use it you do something like this:resources.append:
  - Checkout:
      name: /checkouts/mycode
      repository: http://github.com/whatever
      scm_password.secret: mypasswordThis example is from Yaybu and would stop Yaybu from logging your SVN
password.0.0.34 (2011-11-10)Compose now reuses Opener() rather than creating a new one for each stream
loaded.0.0.33 (2011-11-10)You can now passsearchpathto theConfigobject.0.0.32 (2011-11-10)Working package:// imports0.0.31 (2011-11-10)Better absolute path handling0.0.30 (2011-11-10)Any stream objects returned by theOpeners()API now have alenproperty.The internalOpeners()API can now load from any package on the Python path:fp = Openers().open("package://some.egg/hello.txt")0.0.29 (2011-11-10)The internalOpeners()API now has support for a search path:fp = Openers(searchpath=['file:///home/john', 'http://google.com']).open("foo.txt")TheOpeners()API now supportshttps://0.0.28 (2011-11-07)Fully remove all Mapping default crud0.0.27 (2011-11-03)Fix ${django.SomeModel} to properly resolve0.0.26 (2011-11-03)Add support for a Django DataStoreAllow objects exposed from Python, including simple method calls0.0.25 (2011-10-28)Fix regression in .append0.0.24 (2011-10-22)Can now foreach over a mappingAdd.foreach x in y if x.z = aAdd ‘.with expression as foo:’Add chain and nochain mode to foreach. chain is the default.Major refactoring, context variable is no longer needed to resolve the graphThe ‘semi_resolve’ API is now more correctly named ‘expand’0.0.23 (2011-07-26)$$ escapes $ - so $${foo} is treated as a string, not a variable lookup0.0.22 (2011-07-19)Remove spurious debug messagesFix .import on a .foreach0.0.21 (2011-07-19)New .include directive that can use variables and appear anywhere in file0.0.20 (2011-06-29)Change ProtectedString to inherit from basestring0.0.19 (2011-06-29)Concept of a protected yay file, where any strings that end up containing
secrets will be obscuredProtectedString that handles concatenation of protected and unprocted stringsGPG used to decrypt .yay.gpg files, any variables they spawn are protected0.0.18 (2011-06-10)Brown paper bag to remove stray debugging scaffold0.0.17 (2011-06-10)Fix appending to NoneFix list access where list has already been partially resolved0.0.16 (2011-06-10)Add range tests, fixed range() as a ${} expansionAdded sum() (but no syntax sugar)Allow index operations against filtersFix iterating over Flatten() nodesFix iterating over ForEach() nodesAdd test for empty documents that got away0.0.15 (2011-05-18)Raise an error if field access is invalidAdd a LanguageError for displaying helpful messages when yay files
are wrongIt is now a bug if we raise an error that doesn’t descend from
yay.errors.Error0.0.14 (2011-05-12)Don’t break on empty (e.g. {})0.0.13 (2011-03-06)Fix Append nodes0.0.12 (2011-03-03)Export that method ;)0.0.11 (2011-03-03)Don’t be unicode unless neededAdd a dump() method0.0.10 (2011-02-22)Don’t chomp whitespace in bracketed_expression0.0.9 (2011-02-22)Don’t chomp whitespace in templated_string0.0.8 (2011-02-18)Replace ‘foreach bar as foo’ with ‘foreach foo in bar’0.0.7 (2011-02-16)Numbers starting 0 are treated as base 8.0.0.6 (2011-02-13)Avoid unicode mapping keys where possible - they break kwargs in Py2.x0.0.5 (2011-02-09)Add support for nested foreachAt least for now, support a ruby style .flatten0.0.4 (2011-02-04){foo} can be interpreted as a map by YAML. For now, we will use ${foo} to avoid thisFunction calls to python are implemented - there is now range()There is now a foo.select key so switch statements can be used0.0.3 (2011-01-24)Egg packaging fixes0.0.2 (2011-01-24)Lots more unittests for expression evaluation and expression parsingDrop dependency on OrderedDict0.0.1This is still pre-release, no API or language stability guaranteesVariable resolving is now done in expression tree without a seperate resolve stageUses pyparsing to parse {foo[bar][@.baz > 5]} type syntax0.0.0This is a pre-alpha release to experiment with what we can and can’t do.New PyYAML Loader subclass for getting ordered maps without ugly !!omap markupResolves {} markup within YAML nodesLazily evaluates .copy, .append and .remove instructions