Metadata-Version: 2.1
Name: piny
Version: 0.6.0
Summary: Load YAML configs with environment variables interpolation
Home-page: https://github.com/pilosus/piny/
Author: Vitaly R. Samigullin
Author-email: vrs@pilosus.org
License: MIT
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Unix
Classifier: Operating System :: POSIX :: Linux
Classifier: Environment :: Console
Classifier: Environment :: MacOS X
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet
Requires-Python: >=3.6
Description-Content-Type: text/x-rst
Requires-Dist: PyYAML (>=5.1)
Requires-Dist: Click (>=7.0)
Provides-Extra: marshmallow
Requires-Dist: marshmallow (>=2.19.3) ; extra == 'marshmallow'
Provides-Extra: pydantic
Requires-Dist: pydantic (>=0.28) ; extra == 'pydantic'
Provides-Extra: trafaret
Requires-Dist: trafaret (>=1.2.0) ; extra == 'trafaret'

Piny
====

|Logo|

|Build| |Coverage| |Black| |Versions| |License|

**Piny** is YAML config loader with environment variables interpolation for Python.

Keep your app's configuration in a YAML file.
Mark up sensitive data in the config as *environment variables*.
Set environment variables on application deployment.
Now let the *Piny* load your config and substitute environment variables
in it with their values.

Piny is developed with Docker and Kubernetes in mind,
though it's not limited to any deployment system.


Rationale
---------

Piny combines *readability and versioning* you get when using config files,
and *security* that environment variables provide. Read more about this approach
in the `blog post`_.


Help
----

See `documentation`_ for more details.


Installation
------------

Just run::

  pip install -U piny


Usage
-----

Set your environment variables, add them to your YAML configuration file:

.. code-block:: yaml

    db:
      login: user
      password: ${DB_PASSWORD}
    mail:
      login: user
      password: ${MAIL_PASSWORD:-my_default_password}
    sentry:
      dsn: ${VAR_NOT_SET}

Then load your config:

.. code-block:: python

    from piny import YamlLoader

    config = YamlLoader(path="config.yaml").load()
    print(config)
    # {'db': {'login': 'user', 'password': 'my_db_password'},
    # 'mail': {'login': 'user', 'password': 'my_default_password'},
    # 'sentry': {'dsn': None}}

You may want to discourage Bash-style envs with defaults in your configs.
In such case, use a ``StrictMatcher``:

.. code-block:: python

    from piny import YamlLoader, StrictMatcher

    config = YamlLoader(path="config.yaml", matcher=StrictMatcher).load()

Both strict and default matchers produce ``None`` value if environment variable
matched is not set in the system (and no default syntax used in the case of
default matcher).

Piny also comes with *command line utility* that works both with files and standard
input and output:

.. code-block:: bash

  $ export PASSWORD=mySecretPassword
  $ echo "db: \${PASSWORD}" | piny
  db: mySecretPassword


Validation
----------

Piny supports *optional* data validation using third-party libraries:
`Marshmallow`_, `Pydantic`_, `Trafaret`_.

.. code-block:: python

  import marshmallow as ma
  from piny import MarshmallowValidator, StrictMatcher, YamlLoader

  class DBSchema(ma.Schema):
      login = ma.fields.String(required=True)
      password = ma.fields.String()

  class ConfigSchema(ma.Schema):
      db = ma.fields.Nested(DBSchema)

  config = YamlLoader(
      path="database.yaml",
      matcher=StrictMatcher,
      validator=MarshmallowValidator,
      schema=ConfigSchema,
      strict=True
  ).load(many=False)


Exceptions
----------

``LoadingError`` is thrown when something goes wrong with reading or parsing YAML-file.
``ValidationError`` is a wrapper for exceptions raised by the libraries for optional data validation.
Original exception can be accessed by ``origin`` attribute. It comes in handy when you need more than
just an original exception message (e.g. a dictionary of validation errors).

Both exceptions inherit from the ``ConfigError``.


Best practices
--------------

- Maintain a healthy security/convenience balance for your config

- Mark up entity as an environment variable in your YAML if and only if
  it really is a *secret* (login/passwords, private API keys, crypto keys,
  certificates, or maybe DB hostname too? You decide)

- When loading config file, validate your data.
  Piny supports a few popular data validation tools.

- Store your config files in the version control system along with your app’s code.

- Environment variables are set by whoever is responsible for the deployment.
  Modern orchestration systems like `Kubernetes`_ make it easier to keep envs secure
  (see `Kubernetes Secrets`_).


Fun facts
---------

*Piny* is a recursive acronym for *Piny Is Not YAML*.
Not only it's a library name, but also a name for YAML marked up
with environment variables.


Contributing
------------

See `CONTRIBUTING.rst`_.


.. |Build| image:: https://travis-ci.org/pilosus/piny.svg?branch=master
   :target: https://travis-ci.org/pilosus/piny
.. |Coverage| image:: https://img.shields.io/codecov/c/github/pilosus/piny.svg
   :alt: Codecov
   :target: https://codecov.io/gh/pilosus/piny
.. |Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
   :target: https://github.com/python/black
   :alt: Black Formatter
.. |Versions| image:: https://img.shields.io/pypi/pyversions/piny.svg
   :alt: PyPI - Python Version
   :target: https://pypi.org/project/piny/
.. |License| image:: https://img.shields.io/github/license/pilosus/piny.svg
   :alt: MIT License
   :target: https://github.com/pilosus/piny/blob/master/LICENSE
.. |Logo| image:: https://github.com/pilosus/piny/blob/master/docs/piny_logo_noborder.png
   :alt: Piny logo
   :target: https://pypi.org/project/piny/

.. _blog post: https://blog.pilosus.org/posts/2019/06/07/application-configs-files-or-environment-variables-actually-both/?utm_source=github&utm_medium=link&utm_campaign=rationale
.. _future releases: https://github.com/pilosus/piny/issues/2
.. _Kubernetes: https://kubernetes.io/
.. _Kubernetes Secrets: https://kubernetes.io/docs/concepts/configuration/secret/
.. _Pydantic: https://pydantic-docs.helpmanual.io/
.. _Marshmallow: https://marshmallow.readthedocs.io/
.. _Trafaret: https://trafaret.readthedocs.io/
.. _tests: https://github.com/pilosus/piny/tree/master/tests
.. _source code: https://github.com/pilosus/piny/tree/master/piny
.. _coming soon: https://github.com/pilosus/piny/issues/12
.. _CONTRIBUTING.rst: https://github.com/pilosus/piny/tree/master/CONTRIBUTING.rst
.. _documentation: https://piny.readthedocs.io/


Changelog
---------

v0.6.0 (2019-06-27)
...................
* Add CLI utility (#35) by @pilosus
* Update documentation, add integration examples (#34) by @pilosus

v0.5.2 (2019-06-17)
...................
* Fix ``Help`` section in ``README.rst`` (#31) by @pilosus
* Fix Sphinx release variable (#30) by @pilosus

v0.5.1 (2019-06-17)
...................
* Fix Sphinx config, fix README.rst image markup (#28) by @pilosus

v0.5.0 (2019-06-17)
...................
* Sphinx documentation added (#12) by @pilosus
* Piny artwork added (#6) by Daria Runenkova and @pilosus

v0.4.2 (2019-06-17)
...................
* Rename parent exception ``PinyError`` to ``ConfigError`` (#18) by @pilosus
* Add feature request template for GitHub Issues (#20) by @pilosus

v0.4.1 (2019-06-17)
...................
* Issue and PR templates added, minor docs fixes (#16) by @pilosus

v0.4.0 (2019-06-16)
...................
* Data validators support added for ``Pydantic``, ``Marshmallow`` (#2) by @pilosus
* ``CONTRIBUTING.rst`` added (#4) by @pilosus

v0.3.1 (2019-06-09)
...................
* Minor RST syntax fix in README.rst (#9) by @pilosus

v0.3.0 (2019-06-09)
...................
* README.rst extended with ``Rationale`` and ``Best practices`` sections (#5) by @pilosus

v0.2.0 (2019-06-09)
...................
* StrictMatcher added (#3) by @pilosus

v0.1.1 (2019-06-07)
...................
* CI/CD config minor tweaks
* README updated

v0.1.0 (2019-06-07)
...................
* YamlLoader added
* Makefile added
* CI/CD minimal pipeline added

v0.0.1 (2019-06-07)
...................
* Start the project


