Metadata-Version: 2.1
Name: byoc
Version: 0.27.0
Summary: An object-oriented framework for command-line apps.
Home-page: https://github.com/kalekundert/byoc
Author: Kale Kundert
Author-email: kale@thekunderts.net
Requires-Python: ~=3.6
Description-Content-Type: text/x-rst
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Requires-Dist: autoprop
Requires-Dist: appdirs
Requires-Dist: docopt~=0.6.2
Requires-Dist: mako
Requires-Dist: more_itertools
Requires-Dist: nestedtext
Requires-Dist: pyyaml
Requires-Dist: tidyexc
Requires-Dist: tomli
Requires-Dist: sphinx ; extra == "docs"
Requires-Dist: sphinx_rtd_theme ; extra == "docs"
Requires-Dist: autoclasstoc ; extra == "docs"
Requires-Dist: pytest ; extra == "tests"
Requires-Dist: pytest-cov ; extra == "tests"
Requires-Dist: coveralls ; extra == "tests"
Requires-Dist: parametrize_from_file ; extra == "tests"
Requires-Dist: voluptuous ; extra == "tests"
Requires-Dist: re-assert ; extra == "tests"
Project-URL: Bug Tracker, https://github.com/kalekundert/byoc/issues
Project-URL: Continuous Integration, https://github.com/kalekundert/byoc/actions
Project-URL: Documentation, https://byoc.readthedocs.io/en/latest/
Project-URL: Test Coverage, https://coveralls.io/github/kalekundert/byoc
Project-URL: Version Control, https://github.com/kalekundert/byoc
Provides-Extra: docs
Provides-Extra: tests

********************************
``byoc`` — Bring Your Own Config
********************************

.. image:: https://img.shields.io/pypi/v/byoc.svg
   :target: https://pypi.python.org/pypi/byoc

.. image:: https://img.shields.io/pypi/pyversions/byoc.svg
   :target: https://pypi.python.org/pypi/byoc

.. image:: https://img.shields.io/readthedocs/byoc.svg
   :target: https://byoc.readthedocs.io/en/latest/?badge=latest

.. image:: https://img.shields.io/github/workflow/status/kalekundert/byoc/Test%20and%20release/master
   :target: https://github.com/kalekundert/byoc/actions

.. image:: https://img.shields.io/coveralls/kalekundert/byoc.svg
   :target: https://coveralls.io/github/kalekundert/byoc?branch=master

BYOC is a python library for loading configuration values from any number of 
sources, e.g. files, command-line arguments, environment variables, remote JSON 
APIs, etc.  The primary goal of BYOC is to give you complete control over your 
configuration.  This means:

- Complete control over how things are named and organized.

- Complete control over how values from different config sources are merged.

- Support for any kind of file format, argument parsing library, etc.

- No opinions about anything enforced by BYOC.

The basic idea is to create a class with special attributes that know where to 
look for configuration values.  When such an attribute is accessed, the correct 
value(s) are looked up, possibly merged, possibly cached, and returned.  Here's 
a brief example to show what this looks like::

    import byoc
    from byoc import App, DocoptConfig, AppDirsConfig, Key

    class Greet(App):
        """
    Say a greeting.

    Usage:
        greet <name> [-g <greeting>]
    """
        # Define which config sources are available to this class.
        __config__ = [
                DocoptConfig,
                AppDirsConfig.setup(name='conf.yml'),
        ]

        # Define how to search for each config value.
        name = byoc.param(
                Key(DocoptConfig, '<name>'),
        )
        greeting = byoc.param(
                Key(DocoptConfig, '-g'),
                Key(AppDirsConfig, 'greeting'),
                default='Hello',
        )

        def main(self):
            self.load(DocoptConfig)
            print(f"{self.greeting}, {self.name}!")

    if __name__ == '__main__':
        Greet.entry_point()

We can configure this script from the command line::

  $ ./greet 'Sir Bedevere'
  Hello, Sir Bedevere!
  $ ./greet 'Sir Lancelot' -g Goodbye
  Goodbye, Sir Lancelot!

We can also configure this script via its configuration files::

  $ mkdir -p ~/.config/greet
  $ echo "greeting: Run away" > ~/.config/greet/conf.yml
  $ greet 'Sir Robin'
  Run away, Sir Robin!

This example only scratches the surface, but hopefully you can already get a 
sense for how powerful and flexible this property-based approach is.  For more 
information, refer to the following examples (in lieu of complete 
documentation).

Examples
========
For some examples of ``byoc`` being used in real scripts, check out the 
`Stepwise — Molecular Biology`__ repository.  Almost every script in this 
repository uses ``byoc``.  Below are some particular scripts that might be 
useful:

Simple scripts:

- `aliquot.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/aliquot.py>`_
- `anneal.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/anneal.py>`_
- `kld.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/kld.py>`_

Long but straight-forward scripts:

- `pcr.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/pcr.py>`_
- `spin_cleanup.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/spin_cleanup.py>`_
- `gels/gel.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/gels/gel.py>`_
- `gels/stain.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/gels/stain.py>`_

Complex scripts:

- `serial_dilution.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/serial_dilution.py>`_

  This script features parameters that depend on other parameters.  
  Specifically, the user must provide values for any three of ``volume``, 
  ``conc_high``, ``conc_low``, and ``factor``.  Whichever one isn't specified 
  is inferred from the ones that are.  This is implemented by making the 
  ``byoc`` parameters (which in this case read only from the command-line and 
  not from any config files) private, then adding public properties that are 
  calculated from the private ones.

- `digest.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/digest.py>`_

  This script is actually pretty simple, but it makes used of 
  ``__bareinit__()`` to download some data from the internet.  As alluded to 
  above, ``__init__()`` is not called when ``App`` instances are initialized 
  from the command-line, because ``__init__()`` might require arbitrary 
  arguments and is therefore considered to be part of the python API.  Instead, 
  ``App`` instances are initialized by calling ``__bareinit__()`` with no 
  arguments.

- `ivtt.py <https://github.com/kalekundert/stepwise_mol_bio/blob/master/stepwise_mol_bio/ivtt.py>`_

  This script defines a custom ``Config`` class to read from a sequence 
  database. (This example might go out of date, though; I have plans to move 
  that custom ``Config`` into a different package.)

__ https://github.com/kalekundert/stepwise_mol_bio 

