diff --git a/.coafile b/.coafile index 9667e4d..993a188 100644 --- a/.coafile +++ b/.coafile @@ -1,5 +1,5 @@ [all] -files = src/kwonfig/**.py, test/**.py, *.(yml|yaml), *.md, *requirements.txt, .coafile +files = src/konfetti/**.py, test/**.py, *.(yml|yaml), *.md, *requirements.txt, .coafile indent_size = 4 use_spaces = yes @@ -15,14 +15,14 @@ bears = LineCountBear [all.python] language = python -files = src/kwonfig/**.py, test/**.py +files = src/konfetti/**.py, test/**.py [all.python.keywords] language = python -files = src/kwonfig/**.py +files = src/konfetti/**.py bears = KeywordBear keywords = - from kwonfig, + from konfetti, FIXME, pdb.set_trace(), sys.path.insert, @@ -44,7 +44,7 @@ preferred_quotation = " [all.python.imports] bears = PyImportSortBear force_single_line_imports = no -known_first_party_imports = kwonfig, test +known_first_party_imports = konfetti, test isort_multi_line_output = 3 include_trailing_comma_in_import = yes default_import_section = THIRDPARTY diff --git a/.coveragerc b/.coveragerc index 1be359e..541d3f8 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,12 +1,12 @@ [run] branch = True parallel = True -source = kwonfig +source = konfetti [paths] source = - src/kwonfig - .tox/*/lib/python*/site-packages/kwonfig + src/konfetti + .tox/*/lib/python*/site-packages/konfetti [report] show_missing = True diff --git a/.travis.yml b/.travis.yml index 1bd8b43..0b58d6d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,4 +33,4 @@ before_cache: - rm -rf $HOME/.cache/pip/log after_success: - - codecov \ No newline at end of file + - codecov diff --git a/Makefile b/Makefile index c3426d1..cc20f3e 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ test: pytest test -v docker-test: - docker-compose -f docker-compose-tests.yml run kwonfig + docker-compose -f docker-compose-tests.yml run konfetti tox-test: tox -p all @@ -21,10 +21,10 @@ pylint: tox -e pylint black: - black -l 120 src/kwonfig docs test setup.py + black -l 120 src/konfetti docs test setup.py mypy: - mypy --config-file ./mypy.ini -p kwonfig + mypy --config-file ./mypy.ini src/konfetti install: ARCHFLAGS="-arch x86_64" pip install -r ./requirements.txt diff --git a/README.md b/README.md index 2a1217e..b118c26 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ -# kwonfig +# konfetti -![codecov](https://codecov.io/gh/kiwicom/kwonfig/branch/master/graph/badge.svg) -![Build](https://img.shields.io/travis/kiwicom/kwonfig.svg) -![Version](https://img.shields.io/pypi/v/kwonfig.svg) -![Python versions](https://img.shields.io/pypi/pyversions/kwonfig.svg) -![License](https://img.shields.io/pypi/l/kwonfig.svg) +![codecov](https://codecov.io/gh/kiwicom/konfetti/branch/master/graph/badge.svg) +![Build](https://img.shields.io/travis/kiwicom/konfetti.svg) +![Version](https://img.shields.io/pypi/v/konfetti.svg) +![Python versions](https://img.shields.io/pypi/pyversions/konfetti.svg) +![License](https://img.shields.io/pypi/l/konfetti.svg) ## Description NOTE: The documentation is in progress -`kwonfig` provides a framework-independent way for configuration of applications or libraries written in Python. +`konfetti` provides a framework-independent way for configuration of applications or libraries written in Python. Key features: @@ -30,7 +30,7 @@ The interface design and features are heavily inspired by `Django` & `decouple`. ## Quickstart -To use `kwonfig` you need to define: +To use `konfetti` you need to define: - configuration variables in a module or a class; - an access point; @@ -39,7 +39,7 @@ To use `kwonfig` you need to define: ```python # app_name/settings/production.py -from kwonfig import env, vault +from konfetti import env, vault VAULT_ADDR = env("VAULT_ADDR") VAULT_TOKEN = env("VAULT_TOKEN") @@ -54,14 +54,14 @@ DATABASE_URI = vault("path/to/db") ```python # app_name/settings/__init__.py -from kwonfig import KWonfig, VaultBackend +from konfetti import Konfig, VaultBackend -config = KWonfig(vault_backend=VaultBackend("/secret/team")) +config = Konfig(vault_backend=VaultBackend("/secret/team")) ``` -`kwonfig` relies on `KWONFIG` environment variable to discover your settings module, in the case above: +`konfetti` relies on `KONFETTI_SETTINGS` environment variable to discover your settings module, in the case above: -`export KWONFIG=app_name.settings.production` +`export KONFETTI_SETTINGS=app_name.settings.production` ### Usage @@ -79,10 +79,10 @@ def something(): **Table of contents**: -- [Lazy evaluation](https://github.com/kiwicom/kwonfig#lazy-evaluation) -- [Environment](https://github.com/kiwicom/kwonfig#environment) -- [Vault](https://github.com/kiwicom/kwonfig#vault) -- [Testing](https://github.com/kiwicom/kwonfig#testing) +- [Lazy evaluation](https://github.com/kiwicom/konfetti#lazy-evaluation) +- [Environment](https://github.com/kiwicom/konfetti#environment) +- [Vault](https://github.com/kiwicom/konfetti#vault) +- [Testing](https://github.com/kiwicom/konfetti#testing) ### Lazy evaluation @@ -100,7 +100,7 @@ It could be done either with direct accessing needed variables or with `config.r ### Environment ```python -from kwonfig import env +from konfetti import env VARIABLE = env("VARIABLE_NAME", default="foo") ``` @@ -109,7 +109,7 @@ Since environment variables are strings, there is a `cast` option to convert given variable from a string to the desired type: ```python -from kwonfig import env +from konfetti import env VARIABLE = env("VARIABLE_NAME", default=42, cast=int) ``` @@ -119,7 +119,7 @@ If there is a need to use the environment variable immediately, it could be evaluated via `str` call (other ways could be added on demand): ```python -from kwonfig import env, vault +from konfetti import env, vault DATABASE_ROLE = env("DATABASE_ROLE", default="booking") @@ -138,9 +138,9 @@ both the environment variable and the `.env` record exists, `False` by default. ```python # app_name/settings/__init__.py -from kwonfig import KWonfig +from konfetti import Konfig -config = KWonfig(dotenv="path/to/.env", dotenv_override=False) +config = Konfig(dotenv="path/to/.env", dotenv_override=False) ``` ### Vault @@ -151,15 +151,15 @@ To use Vault as a secrets storage you need to configure the access point: ```python # app_name/settings/__init__.py -from kwonfig import KWonfig, VaultBackend +from konfetti import Konfig, VaultBackend -config = KWonfig(vault_backend=VaultBackend("your/prefix")) +config = Konfig(vault_backend=VaultBackend("your/prefix")) ``` There are two Vault backends available: -- `kwonfig.VaultBackend` -- `kwonfig.AsyncVaultBackend` +- `konfetti.VaultBackend` +- `konfetti.AsyncVaultBackend` The main difference is that the latter requires using `await` to access the secret value (the call will be handled asynchronously under the hood), otherwise the interfaces and capabilities are the same. @@ -173,7 +173,7 @@ Every Vault secret needs a `path` to be used as a lookup (leading and trailing s ```python # app_name/settings/production.py -from kwonfig import vault +from konfetti import vault WHOLE_SECRET = vault("path/to") ``` @@ -190,7 +190,7 @@ You can specify a specific key to be returned for a config option with `[]` synt ```python # app_name/settings/production.py -from kwonfig import vault +from konfetti import vault KEY = vault("path/to")["key"] ``` @@ -205,7 +205,7 @@ Using square brackets will not trigger evaluation - you could specify as many le ```python # app_name/settings/production.py -from kwonfig import vault +from konfetti import vault DEEP = vault("path/to")["deeply"]["nested"]["key"] ``` @@ -215,7 +215,7 @@ Casting could be specified as well: ```python # app_name/settings/production.py from decimal import Decimal -from kwonfig import vault +from konfetti import vault DECIMAL = vault("path/to", cast=Decimal)["fee_amount"] # stored as string ``` @@ -226,7 +226,7 @@ DECIMAL = vault("path/to", cast=Decimal)["fee_amount"] # stored as string Decimal("0.15") ``` -Sometimes you need to access to some secrets dynamically. `KWonfig` provides a way to do it: +Sometimes you need to access to some secrets dynamically. `Konfig` provides a way to do it: ```python >>> from app_name.settings import config @@ -240,7 +240,7 @@ It is possible to get a file-like interface for vault secret. ```python # app_name/settings/production.py -from kwonfig import vault_file +from konfetti import vault_file KEY = vault_file("path/to/file")["key"] ``` @@ -285,7 +285,7 @@ Example: ```python # app_name/settings/production.py -from kwonfig import vault +from konfetti import vault KEY = vault("path/to")["key"] ``` @@ -322,23 +322,23 @@ If you don't need this behavior, it could be turned off with `try_env_first=Fals ```python # app_name/settings/__init__.py -from kwonfig import KWonfig, VaultBackend +from konfetti import Konfig, VaultBackend -config = KWonfig(vault_backend=VaultBackend("your/prefix", try_env_first=False)) +config = Konfig(vault_backend=VaultBackend("your/prefix", try_env_first=False)) ``` ##### Disabling access to secrets -If you want to forbid any access to Vault (e.g. in your tests) you can set `KWONFIG_DISABLE_SECRETS` environment +If you want to forbid any access to Vault (e.g. in your tests) you can set `KONFETTI_DISABLE_SECRETS` environment variable with `1` / `on` / `true` / `yes`. ```python >>> import os >>> from app_name.settings import config ->>> os.environ["KWONFIG_DISABLE_SECRETS"] = "1" +>>> os.environ["KONFETTI_DISABLE_SECRETS"] = "1" >>> config.get_secret("path/to")["key"] ... -RuntimeError: Access to secrets is disabled. Unset KWONFIG_DISABLE_SECRETS variable to enable it. +RuntimeError: Access to secrets is disabled. Unset KONFETTI_DISABLE_SECRETS variable to enable it. ``` ##### Caching @@ -346,18 +346,18 @@ RuntimeError: Access to secrets is disabled. Unset KWONFIG_DISABLE_SECRETS varia Vault values could be cached in memory: ```python -config = KWonfig(vault_backend=VaultBackend("your/prefix", cache_ttl=60)) +config = Konfig(vault_backend=VaultBackend("your/prefix", cache_ttl=60)) ``` By default, caching is disabled. #### Lazy options -If there is a need to calculate config options dynamically (e.g., if it depends on values of other options) `kwonfig` +If there is a need to calculate config options dynamically (e.g., if it depends on values of other options) `konfetti` provides `lazy`: ```python -from kwonfig import lazy +from konfetti import lazy LAZY_LAMBDA = lazy(lambda config: config.KEY + "/" + config.SECRET + "/" + config.REQUIRED) @@ -372,10 +372,10 @@ def lazy_property(config): It is usually a good idea to use a slightly different configuration for tests (disabled tracing, sentry, etc.). ``` -export KWONFIG=app_name.settings.tests +export KONFETTI_SETTINGS=app_name.settings.tests ``` -It is very useful to override some config options in tests. `KWonfig.override` will override config options defined +It is very useful to override some config options in tests. `Konfig.override` will override config options defined in the settings module. It works as a context manager or a decorator to provide explicit setup & clean up for overridden options. ```python @@ -422,13 +422,13 @@ def test_not_affected(): NOTE. `setup_class/setUp` and `teardown_class/tearDown` methods will work with `override`. -`kwonfig` includes a pytest integration that gives you a fixture, that allows you to override given config without +`konfetti` includes a pytest integration that gives you a fixture, that allows you to override given config without using a context manager/decorator approach and automatically rollbacks changes made: ```python import pytest from app_name.settings import config -from kwonfig.pytest_plugin import make_fixture +from konfetti.pytest_plugin import make_fixture # create a fixture. the default name is "settings", # but could be specified via `name` option @@ -472,13 +472,13 @@ NOTE. It is forbidden to create two fixtures from the same config instances. The environment variable name could be customized via `config_variable_name` option: ```python -config = KWonfig(config_variable_name="APP_CONFIG") +config = Konfig(config_variable_name="APP_CONFIG") ``` Alternatively, it is possible to specify class-based settings: ```python -from kwonfig import env, vault +from konfetti import env, vault class ProductionSettings: @@ -602,7 +602,7 @@ $ make docker-test or alternatively: ```bash -$ docker-compose -f docker-compose-tests.yml run kwonfig +$ docker-compose -f docker-compose-tests.yml run konfetti ``` ## Contributing diff --git a/docker-compose-tests.yml b/docker-compose-tests.yml index 525163d..0f5ed8f 100644 --- a/docker-compose-tests.yml +++ b/docker-compose-tests.yml @@ -2,7 +2,7 @@ version: "3.7" services: - kwonfig: + konfetti: image: kiwicom/tox environment: TEST_VAULT_ADDR: http://vault:8200 diff --git a/docs/Makefile b/docs/Makefile index 2d93f8e..2ae3619 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,7 +4,7 @@ # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build -SPHINXPROJ = kwonfig +SPHINXPROJ = konfetti SOURCEDIR = . BUILDDIR = _build diff --git a/docs/conf.py b/docs/conf.py index ccf2ae1..2df1662 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,9 +48,9 @@ master_doc = "index" # General information about the project. -project = "kwonfig" -copyright = "2019, finance team" -author = "finance team" +project = "konfetti" +copyright = "2019, kiwi.com" +author = "kiwi.com" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -102,7 +102,7 @@ # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = "kwonfigdoc" +htmlhelp_basename = "konfettidoc" # -- Options for LaTeX output --------------------------------------------- @@ -125,14 +125,14 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). -latex_documents = [(master_doc, "kwonfig.tex", "kwonfig Documentation", "finance team", "manual")] +latex_documents = [(master_doc, "konfetti.tex", "konfetti Documentation", "finance team", "manual")] # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "kwonfig", "kwonfig Documentation", [author], 1)] +man_pages = [(master_doc, "konfetti", "konfetti Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- @@ -143,10 +143,10 @@ texinfo_documents = [ ( master_doc, - "kwonfig", - "kwonfig Documentation", + "konfetti", + "konfetti Documentation", author, - "kwonfig", + "konfetti", "One line description of project.", "Miscellaneous", ) diff --git a/docs/index.rst b/docs/index.rst index 9014b37..1d0a5b1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,18 +1,15 @@ -.. kwo`nfig documentation master file, created by +.. konfetti documentation master file, created by sphinx-quickstart on Fri Jan 13 12:59:16 2017. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to kwonfig's documentation! +Welcome to konfetti's documentation! =================================== .. toctree:: :maxdepth: 2 :caption: Contents: - kw/kw - - Indices and tables ================== diff --git a/setup.py b/setup.py index 5ef8f5a..92ed01e 100644 --- a/setup.py +++ b/setup.py @@ -21,13 +21,13 @@ def read(fname): tests_require = [line for line in f if line and line[0] not in "#-"] setup( - name="kwonfig", + name="konfetti", version="0.6.0", - url="https://github.com/kiwicom/kwonfig", + url="https://github.com/kiwicom/konfetti", license="MIT", author="Dmitry Dygalo", author_email="dmitry.dygalo@kiwi.com", - description="`kwonfig` provides a framework-independent way for " + description="`konfetti` provides a framework-independent way for " "configuration of applications or libraries written in Python.", long_description=read("README.md"), long_description_content_type="text/markdown", diff --git a/src/kwonfig/__init__.py b/src/konfetti/__init__.py similarity index 89% rename from src/kwonfig/__init__.py rename to src/konfetti/__init__.py index a71b33c..c764189 100644 --- a/src/kwonfig/__init__.py +++ b/src/konfetti/__init__.py @@ -1,4 +1,4 @@ -from .core import KWonfig +from .core import Konfig from .environ import EnvVariable from .laziness import LazyVariable from .vault import * diff --git a/src/kwonfig/_async.py b/src/konfetti/_async.py similarity index 96% rename from src/kwonfig/_async.py rename to src/konfetti/_async.py index f223bef..c614a41 100644 --- a/src/kwonfig/_async.py +++ b/src/konfetti/_async.py @@ -21,7 +21,7 @@ async def inner(*args, **kwargs): def make_async_callback(coro, callback): """Wrap calling of the callback on the coro result in a coro. - Needed to provide an awaitable response to the KWonfig users. + Needed to provide an awaitable response to the Konfig users. """ async def inner(): diff --git a/src/kwonfig/_compat.py b/src/konfetti/_compat.py similarity index 100% rename from src/kwonfig/_compat.py rename to src/konfetti/_compat.py diff --git a/src/kwonfig/cache.py b/src/konfetti/cache.py similarity index 100% rename from src/kwonfig/cache.py rename to src/konfetti/cache.py diff --git a/src/kwonfig/core.py b/src/konfetti/core.py similarity index 98% rename from src/kwonfig/core.py rename to src/konfetti/core.py index 03214a1..9065c03 100644 --- a/src/kwonfig/core.py +++ b/src/konfetti/core.py @@ -45,7 +45,7 @@ def get_config_option_names(module): @attr.s(slots=True) -class KWonfig(object): +class Konfig(object): """Configuration holder.""" vault_backend = attr.ib( @@ -55,7 +55,7 @@ class KWonfig(object): dotenv_override = attr.ib(default=False, type=bool) # Forbids overriding with options that are not defined in the config module strict_override = attr.ib(default=True, type=bool) - config_variable_name = attr.ib(default="KWONFIG", type=str) + config_variable_name = attr.ib(default="KONFETTI_SETTINGS", type=str) _initialized = attr.ib(type=bool, init=False, default=False) _dotenv_loaded = attr.ib(type=bool, init=False, default=False) _conf = attr.ib(init=False, default=None) @@ -210,7 +210,7 @@ def _get_secret(self, obj): raise exceptions.VaultBackendMissing( "Vault backend is not configured. " "Please specify `vault_backend` option in " - "your `KWonfig` initialization" + "your `Konfig` initialization" ) # A closure is needed to avoid a need to evaluate VAULT_{ADDR,TOKEN} variables @@ -259,7 +259,7 @@ def vault(self): class _Vault(object): """A namespace holder to provide `config.vault.get_override_examples()` API.""" - _config = attr.ib(type=KWonfig) + _config = attr.ib(type=Konfig) _overrides = attr.ib(init=False, default=None, type=Dict[str, Dict[str, str]]) def get_override_examples(self): @@ -285,7 +285,7 @@ class OverrideContextManager: __slots__ = ("config", "kwargs") def __init__(self, config, **kwargs): - # type: (KWonfig, **Any) -> None + # type: (Konfig, **Any) -> None self.config = config self.kwargs = kwargs diff --git a/src/kwonfig/environ.py b/src/konfetti/environ.py similarity index 100% rename from src/kwonfig/environ.py rename to src/konfetti/environ.py diff --git a/src/kwonfig/exceptions.py b/src/konfetti/exceptions.py similarity index 65% rename from src/kwonfig/exceptions.py rename to src/konfetti/exceptions.py index 96924bc..51fc402 100644 --- a/src/kwonfig/exceptions.py +++ b/src/konfetti/exceptions.py @@ -1,23 +1,23 @@ -class KWonfigError(Exception): - """Common error for all errors in `kwonfig`.""" +class KonfettiError(Exception): + """Common error for all errors in `konfetti`.""" -class MissingError(AttributeError, KWonfigError): +class MissingError(AttributeError, KonfettiError): """Config option is missing in the given settings module.""" # Should be inherited from AttributeError because tools like Celery rely # on this behavior -class SettingsNotSpecified(KWonfigError): +class SettingsNotSpecified(KonfettiError): """Environment variable, that points to a setting module is not set.""" -class SettingsNotLoadable(KWonfigError): +class SettingsNotLoadable(KonfettiError): """Settings module is not found or can't be imported.""" -class VaultBackendMissing(KWonfigError): +class VaultBackendMissing(KonfettiError): """A secret variable is accessed, but vault backend is not configured.""" @@ -25,9 +25,9 @@ class SecretKeyMissing(MissingError): """Path exists in Vault, but doesn't contain specified value.""" -class ForbiddenOverrideError(KWonfigError): +class ForbiddenOverrideError(KonfettiError): """An attempt to override configuration with a key that doesn't exist in the configuration.""" -class InvalidSecretOverrideError(KWonfigError): +class InvalidSecretOverrideError(KonfettiError): """Environment variable for secret override contains invalid or non-JSON data.""" diff --git a/src/kwonfig/laziness.py b/src/konfetti/laziness.py similarity index 100% rename from src/kwonfig/laziness.py rename to src/konfetti/laziness.py diff --git a/src/konfetti/log.py b/src/konfetti/log.py new file mode 100644 index 0000000..13efe69 --- /dev/null +++ b/src/konfetti/log.py @@ -0,0 +1,5 @@ +import logging + +cache_logger = logging.getLogger("konfetti.cache") +core_logger = logging.getLogger("konfetti.core") +vault_logger = logging.getLogger("konfetti.vault") diff --git a/src/kwonfig/mixins.py b/src/konfetti/mixins.py similarity index 95% rename from src/kwonfig/mixins.py rename to src/konfetti/mixins.py index ecbfd73..4adf8d5 100644 --- a/src/kwonfig/mixins.py +++ b/src/konfetti/mixins.py @@ -62,6 +62,6 @@ def _get_default(self): raise exceptions.MissingError( "Variable `{}` is not found and has no `default` specified".format(self.name) # type: ignore ) - if callable(self.default): - return self.default() + if callable(self.default): # type: ignore + return self.default() # type: ignore return self.default # type: ignore diff --git a/src/kwonfig/pytest_plugin.py b/src/konfetti/pytest_plugin.py similarity index 94% rename from src/kwonfig/pytest_plugin.py rename to src/konfetti/pytest_plugin.py index 11eceb2..ba00c47 100644 --- a/src/kwonfig/pytest_plugin.py +++ b/src/konfetti/pytest_plugin.py @@ -7,7 +7,7 @@ @attr.s class ConfigWrapper(object): - """For proxying `__setattr__` calls as `_configure` to `KWonfig` instances.""" + """For proxying `__setattr__` calls as `_configure` to `Konfig` instances.""" config = attr.ib() diff --git a/src/kwonfig/utils.py b/src/konfetti/utils.py similarity index 100% rename from src/kwonfig/utils.py rename to src/konfetti/utils.py diff --git a/src/kwonfig/vault/__init__.py b/src/konfetti/vault/__init__.py similarity index 100% rename from src/kwonfig/vault/__init__.py rename to src/konfetti/vault/__init__.py diff --git a/src/kwonfig/vault/asynchronous.py b/src/konfetti/vault/asynchronous.py similarity index 100% rename from src/kwonfig/vault/asynchronous.py rename to src/konfetti/vault/asynchronous.py diff --git a/src/kwonfig/vault/base.py b/src/konfetti/vault/base.py similarity index 100% rename from src/kwonfig/vault/base.py rename to src/konfetti/vault/base.py diff --git a/src/kwonfig/vault/core.py b/src/konfetti/vault/core.py similarity index 98% rename from src/kwonfig/vault/core.py rename to src/konfetti/vault/core.py index 26d3024..3b108e3 100644 --- a/src/kwonfig/vault/core.py +++ b/src/konfetti/vault/core.py @@ -11,7 +11,7 @@ from .synchronous import VaultBackend SEPARATOR = "__" -SECRETS_DISABLED_VARIABLE = "KWONFIG_DISABLE_SECRETS" +SECRETS_DISABLED_VARIABLE = "KONFETTI_DISABLE_SECRETS" def are_defaults_disabled(): diff --git a/src/kwonfig/vault/synchronous.py b/src/konfetti/vault/synchronous.py similarity index 100% rename from src/kwonfig/vault/synchronous.py rename to src/konfetti/vault/synchronous.py diff --git a/src/kwonfig/log.py b/src/kwonfig/log.py deleted file mode 100644 index 7b7a95d..0000000 --- a/src/kwonfig/log.py +++ /dev/null @@ -1,5 +0,0 @@ -import logging - -cache_logger = logging.getLogger("kwonfig.cache") -core_logger = logging.getLogger("kwonfig.core") -vault_logger = logging.getLogger("kwonfig.vault") diff --git a/test/conftest.py b/test/conftest.py index c02bfcf..15df686 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -6,8 +6,8 @@ import hvac import pytest -from kwonfig.core import KWonfig -from kwonfig.vault import VaultBackend +from konfetti.core import Konfig +from konfetti.vault import VaultBackend pytest_plugins = ["pytester"] @@ -27,10 +27,10 @@ def vault_prefix(): def config(request, vault_prefix): marker = request.node.get_closest_marker("async_vault") if marker: - from kwonfig.vault import AsyncVaultBackend as vault_backend + from konfetti.vault import AsyncVaultBackend as vault_backend else: vault_backend = VaultBackend - yield KWonfig(vault_backend=vault_backend(vault_prefix)) + yield Konfig(vault_backend=vault_backend(vault_prefix)) sys.modules.pop("settings.production", None) @@ -46,7 +46,7 @@ def vault_token(): @pytest.fixture def env(monkeypatch): - monkeypatch.setenv("KWONFIG", "test_app.settings.production") + monkeypatch.setenv("KONFETTI_SETTINGS", "test_app.settings.production") monkeypatch.setenv("VAULT_ADDR", VAULT_ADDR) monkeypatch.setenv("VAULT_TOKEN", VAULT_TOKEN) monkeypatch.setenv("REQUIRED", "important") @@ -58,10 +58,10 @@ def settings(testdir, env, vault_prefix): settings = testdir.mkdir("settings") settings.ensure("__init__.py").write( """ -from kwonfig import KWonfig -from kwonfig.vault import VaultBackend +from konfetti import Konfig +from konfetti.vault import VaultBackend -config = KWonfig(vault_backend=VaultBackend("{}")) +config = Konfig(vault_backend=VaultBackend("{}")) """.format( vault_prefix ) @@ -95,4 +95,4 @@ def mocked_import_config_module(mocker): module = ModuleType("fake") module.EXAMPLE = "test" module.SOMETHING = "else" - return mocker.patch("kwonfig.core.import_config_module", return_value=module) + return mocker.patch("konfetti.core.import_config_module", return_value=module) diff --git a/test/test_app/settings/production.py b/test/test_app/settings/production.py index 14b734b..a7f19b3 100644 --- a/test/test_app/settings/production.py +++ b/test/test_app/settings/production.py @@ -1,7 +1,7 @@ from datetime import date, datetime from decimal import Decimal -from kwonfig import env, lazy, vault, vault_file +from konfetti import env, lazy, vault, vault_file KEY = "value" DEBUG = env("DEBUG", default=True, cast=bool) diff --git a/test/test_app/settings/subset.py b/test/test_app/settings/subset.py index 51049ad..2c84530 100644 --- a/test/test_app/settings/subset.py +++ b/test/test_app/settings/subset.py @@ -1,4 +1,4 @@ -from kwonfig import env, vault +from konfetti import env, vault KEY = "value" DEBUG = env("DEBUG", default=True, cast=bool) diff --git a/test/test_async_vault.py b/test/test_async_vault.py index 356f380..c46a2df 100644 --- a/test/test_async_vault.py +++ b/test/test_async_vault.py @@ -5,10 +5,10 @@ import aiohttp import pytest -from kwonfig import env, KWonfig -from kwonfig._async import make_async_callback, make_simple_coro -from kwonfig.exceptions import MissingError, SecretKeyMissing -from kwonfig.vault import AsyncVaultBackend +from konfetti import env, Konfig +from konfetti._async import make_async_callback, make_simple_coro +from konfetti.exceptions import MissingError, SecretKeyMissing +from konfetti.vault import AsyncVaultBackend pytestmark = [pytest.mark.asyncio, pytest.mark.async_vault, pytest.mark.usefixtures("env", "vault_data")] @@ -53,10 +53,10 @@ async def test_get_secret(config): @pytest.mark.parametrize("action", (lambda c: c.get_secret("path/to"), lambda c: c.SECRET)) async def test_disable_secrets(config, monkeypatch, action): # This option completely disables Vault access - monkeypatch.setenv("KWONFIG_DISABLE_SECRETS", "1") + monkeypatch.setenv("KONFETTI_DISABLE_SECRETS", "1") with pytest.raises( RuntimeError, - match="Access to vault is disabled. Unset `KWONFIG_DISABLE_SECRETS` environment variable to enable it.", + match="Access to vault is disabled. Unset `KONFETTI_DISABLE_SECRETS` environment variable to enable it.", ): await action(config) @@ -70,7 +70,7 @@ async def test_override_with_default(config, monkeypatch): @pytest.mark.parametrize("url", ("http://localhost:8200", "http://localhost:8200/")) async def test_get_full_url(url): # Slashes don't matter - from kwonfig.vault.asynchronous import _get_full_url + from konfetti.vault.asynchronous import _get_full_url assert _get_full_url(url, "path/to") == "http://localhost:8200/v1/path/to" @@ -93,7 +93,7 @@ async def test_make_simple_coro(): @pytest.fixture def config_with_cached_vault(vault_prefix): - return KWonfig(vault_backend=AsyncVaultBackend(vault_prefix, cache_ttl=1)) + return Konfig(vault_backend=AsyncVaultBackend(vault_prefix, cache_ttl=1)) SECRET_DATA = {"DECIMAL": "1.3", "IS_SECRET": True, "SECRET": "value"} @@ -134,8 +134,8 @@ async def test_no_recaching(config_with_cached_vault, mocker, freezer, vault_tok async def test_asdict(monkeypatch, vault_prefix, vault_addr, vault_token): # All options, including dicts should be evaluated - monkeypatch.setenv("KWONFIG", "test_app.settings.subset") - config = KWonfig(vault_backend=AsyncVaultBackend(vault_prefix)) + monkeypatch.setenv("KONFETTI_SETTINGS", "test_app.settings.subset") + config = Konfig(vault_backend=AsyncVaultBackend(vault_prefix)) assert await config.asdict() == { "DEBUG": True, "SECRET": "value", @@ -150,7 +150,7 @@ async def test_asdict(monkeypatch, vault_prefix, vault_addr, vault_token): async def test_asdict_shortcut(vault_prefix, vault_addr, vault_token): # If there are no coroutines - nothing should be awaited - config = KWonfig(vault_backend=AsyncVaultBackend(vault_prefix)) + config = Konfig(vault_backend=AsyncVaultBackend(vault_prefix)) class TestSettings: SECRET = 1 diff --git a/test/test_cache.py b/test/test_cache.py index b290a12..10b7398 100644 --- a/test/test_cache.py +++ b/test/test_cache.py @@ -2,7 +2,7 @@ import pytest -from kwonfig.cache import EMPTY, InMemoryCache +from konfetti.cache import EMPTY, InMemoryCache @pytest.fixture diff --git a/test/test_core.py b/test/test_core.py index cdbcf51..c93ff74 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -4,9 +4,9 @@ from dotenv import load_dotenv import pytest -from kwonfig.core import import_config_module, KWonfig -from kwonfig.exceptions import MissingError, SettingsNotLoadable, SettingsNotSpecified -from kwonfig.vault import VaultBackend +from konfetti.core import import_config_module, Konfig +from konfetti.exceptions import MissingError, SettingsNotLoadable, SettingsNotSpecified +from konfetti.vault import VaultBackend pytestmark = [pytest.mark.usefixtures("settings")] @@ -18,7 +18,7 @@ def test_simple_var_access(config): def test_forbid_setattr(config): - """`setattr` is forbidden for options in KWonfig.""" + """`setattr` is forbidden for options in Konfig.""" with pytest.raises(AttributeError): config.KEY = "value" @@ -31,7 +31,7 @@ def test_missing_variable(config): def test_no_reinitialization(mocked_import_config_module): """When config instance is accessed second time, the underlying module is not re-imported.""" - config = KWonfig() + config = Konfig() for _ in (1, 2): assert config.EXAMPLE == "test" # Py2.7, Py3.5: replace with `assert_called_once` when 2.7/3.5 support will be dropped. @@ -49,7 +49,7 @@ def test_config_module_not_exists(config, monkeypatch): def test_config_var_not_specified(config, monkeypatch): """If config is not specified, an error should occur.""" monkeypatch.delenv(config.config_variable_name) - with pytest.raises(SettingsNotSpecified, match="The environment variable `KWONFIG` is not set"): + with pytest.raises(SettingsNotSpecified, match="The environment variable `KONFETTI_SETTINGS` is not set"): config.MISSING @@ -68,7 +68,7 @@ def test_import_single_string_module(config, monkeypatch): def test_custom_config_variable_name(monkeypatch): # Config variable name is customizable - config = KWonfig(config_variable_name="APP_CONFIG") + config = Konfig(config_variable_name="APP_CONFIG") monkeypatch.setenv("APP_CONFIG", "test_app.settings.production") assert config.KEY == "value" @@ -76,21 +76,21 @@ def test_custom_config_variable_name(monkeypatch): @pytest.mark.usefixtures("mocked_import_config_module") def test_require(): """Validate config and raise proper exception if required variables are missing.""" - config = KWonfig() + config = Konfig() with pytest.raises(MissingError, match=r"Options \['MISSING', 'YET_ANOTHER_MISSING'\] are required"): config.require("MISSING", "YET_ANOTHER_MISSING") @pytest.mark.usefixtures("mocked_import_config_module") def test_require_ok(): - config = KWonfig() + config = Konfig() assert config.require("EXAMPLE") is None @pytest.mark.usefixtures("mocked_import_config_module") def test_require_nothing(): """Given keys should contain at least one element.""" - config = KWonfig() + config = Konfig() with pytest.raises(RuntimeError, match="You need to specify at least one key"): config.require() @@ -98,7 +98,7 @@ def test_require_nothing(): def test_dotenv(testdir): settings = testdir.tmpdir.ensure_dir("settings") settings.ensure(".env").write("FROM_DOTENV=loaded") - config = KWonfig(dotenv=os.path.join(str(settings), ".env")) + config = Konfig(dotenv=os.path.join(str(settings), ".env")) assert config.FROM_DOTENV == "loaded" @@ -108,7 +108,7 @@ def test_dotenv_override(testdir, monkeypatch, override, expected_value): settings = testdir.tmpdir.ensure_dir("settings") settings.ensure(".env").write("FROM_DOTENV=loaded") monkeypatch.setenv("FROM_DOTENV", "loaded_from_env") - config = KWonfig(dotenv=os.path.join(str(settings), ".env"), dotenv_override=override) + config = Konfig(dotenv=os.path.join(str(settings), ".env"), dotenv_override=override) assert config.FROM_DOTENV == expected_value @@ -116,8 +116,8 @@ def test_dotenv_reloading(testdir, mocker): """The dotenv file shouldn't be reloaded after first time.""" settings = testdir.tmpdir.ensure_dir("settings") settings.ensure(".env").write("FROM_DOTENV=loaded") - config = KWonfig(dotenv=os.path.join(str(settings), ".env"), dotenv_override=True) - load_env = mocker.patch("kwonfig.core.load_dotenv", wraps=load_dotenv) + config = Konfig(dotenv=os.path.join(str(settings), ".env"), dotenv_override=True) + load_env = mocker.patch("konfetti.core.load_dotenv", wraps=load_dotenv) assert config.FROM_DOTENV == "loaded" assert load_env.called @@ -138,15 +138,15 @@ def test_contains_invalid(config): def test_contains_override(): - config = KWonfig(strict_override=False) + config = Konfig(strict_override=False) with config.override(MISSING="awesome"): with config.override(): assert "MISSING" in config def test_asdict(monkeypatch, vault_prefix, vault_addr, vault_token): - monkeypatch.setenv("KWONFIG", "test_app.settings.subset") - config = KWonfig(vault_backend=VaultBackend(vault_prefix)) + monkeypatch.setenv("KONFETTI_SETTINGS", "test_app.settings.subset") + config = Konfig(vault_backend=VaultBackend(vault_prefix)) assert config.asdict() == { "DEBUG": True, "SECRET": "value", @@ -160,8 +160,8 @@ def test_asdict(monkeypatch, vault_prefix, vault_addr, vault_token): def test_vault_override_variables(monkeypatch, vault_prefix): - monkeypatch.setenv("KWONFIG", "test_app.settings.subset") - config = KWonfig(vault_backend=VaultBackend(vault_prefix)) + monkeypatch.setenv("KONFETTI_SETTINGS", "test_app.settings.subset") + config = Konfig(vault_backend=VaultBackend(vault_prefix)) assert config.vault.get_override_examples() == { "NESTED_SECRET": {"PATH__TO__NESTED": '{"NESTED_SECRET": {"nested": "example_value"}}'}, "SECRET": {"PATH__TO": '{"SECRET": "example_value"}'}, @@ -170,8 +170,8 @@ def test_vault_override_variables(monkeypatch, vault_prefix): def test_vault_override_variables_cache(monkeypatch, vault_prefix): - monkeypatch.setenv("KWONFIG", "test_app.settings.subset") - config = KWonfig(vault_backend=VaultBackend(vault_prefix)) + monkeypatch.setenv("KONFETTI_SETTINGS", "test_app.settings.subset") + config = Konfig(vault_backend=VaultBackend(vault_prefix)) assert config.vault is config.vault assert config.vault.get_override_examples() is config.vault.get_override_examples() diff --git a/test/test_environ.py b/test/test_environ.py index 7465133..f49dce8 100644 --- a/test/test_environ.py +++ b/test/test_environ.py @@ -1,8 +1,8 @@ import pytest -from kwonfig import env -from kwonfig.exceptions import MissingError -from kwonfig.mixins import _cast_boolean +from konfetti import env +from konfetti.exceptions import MissingError +from konfetti.mixins import _cast_boolean pytestmark = [pytest.mark.usefixtures("settings", "env")] diff --git a/test/test_fixture.py b/test/test_fixture.py index c0e2f61..41ba6e3 100644 --- a/test/test_fixture.py +++ b/test/test_fixture.py @@ -8,7 +8,7 @@ def test_fixtures(testdir): """ import pytest from settings import config - from kwonfig.pytest_plugin import make_fixture + from konfetti.pytest_plugin import make_fixture make_fixture(config) @@ -89,7 +89,7 @@ def test_invalid_name(testdir): """ import pytest from settings import config - from kwonfig.pytest_plugin import make_fixture + from konfetti.pytest_plugin import make_fixture make_fixture(config, name="config") """ diff --git a/test/test_lazy.py b/test/test_lazy.py index 8c51f08..51d2e2d 100644 --- a/test/test_lazy.py +++ b/test/test_lazy.py @@ -1,6 +1,6 @@ import pytest -from kwonfig import lazy +from konfetti import lazy pytestmark = [pytest.mark.usefixtures("settings")] diff --git a/test/test_override.py b/test/test_override.py index cdfa640..445ba01 100644 --- a/test/test_override.py +++ b/test/test_override.py @@ -2,8 +2,8 @@ import pytest -from kwonfig import KWonfig -from kwonfig.exceptions import ForbiddenOverrideError +from konfetti import Konfig +from konfetti.exceptions import ForbiddenOverrideError pytestmark = [pytest.mark.usefixtures("settings")] @@ -302,7 +302,7 @@ def test_override_unknown_option(): Active only with `strict_override` config option. """ - config = KWonfig(strict_override=True) + config = Konfig(strict_override=True) with pytest.raises( ForbiddenOverrideError, match="Can't override `NOT_EXIST` config option, because it is not defined in the config module", @@ -312,7 +312,7 @@ def test_override_unknown_option(): def test_strict_override_valid(): - config = KWonfig(strict_override=True) + config = Konfig(strict_override=True) with config.override(INTEGER=123): assert config.INTEGER == 123 @@ -362,7 +362,7 @@ def test_disable(): def test_no_setup_on_override(mocked_import_config_module): """If overridden option is accessed, then config is not loaded.""" - config = KWonfig(strict_override=False) + config = Konfig(strict_override=False) with config.override(EXAMPLE="awesome"): assert config.EXAMPLE == "awesome" mocked_import_config_module.assert_not_called() @@ -370,7 +370,7 @@ def test_no_setup_on_override(mocked_import_config_module): def test_setup_on_override(mocked_import_config_module): """If non-overridden option is accessed, then config should be loaded.""" - config = KWonfig() + config = Konfig() with config.override(SOMETHING="awesome"): assert config.EXAMPLE == "test" # Py2.7, Py3.5: replace with `assert_called` when 2.7/3.5 support will be dropped. diff --git a/test/test_utils.py b/test/test_utils.py index 174ae88..03b371a 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -1,6 +1,6 @@ import pytest -from kwonfig.utils import flatten_dict, rebuild_dict +from konfetti.utils import flatten_dict, rebuild_dict @pytest.mark.parametrize("value, expected", (({}, []), ({"A": 1}, [(["A"], 1)]), ({"A": {"B": 1}}, [(["A", "B"], 1)]))) diff --git a/test/test_vault.py b/test/test_vault.py index 20b006a..6886511 100644 --- a/test/test_vault.py +++ b/test/test_vault.py @@ -5,12 +5,12 @@ import pytest -import kwonfig -from kwonfig import KWonfig -from kwonfig.exceptions import InvalidSecretOverrideError, MissingError, SecretKeyMissing, VaultBackendMissing -from kwonfig.utils import NOT_SET -from kwonfig.vault import VaultBackend -from kwonfig.vault.core import VaultVariable +import konfetti +from konfetti import Konfig +from konfetti.exceptions import InvalidSecretOverrideError, MissingError, SecretKeyMissing, VaultBackendMissing +from konfetti.utils import NOT_SET +from konfetti.vault import VaultBackend +from konfetti.vault.core import VaultVariable pytestmark = [pytest.mark.usefixtures("env", "vault_data")] @@ -44,11 +44,11 @@ def test_missing_variable(config, vault_prefix): def test_missing_vault_backend(): - config = KWonfig() + config = Konfig() with pytest.raises( VaultBackendMissing, match="Vault backend is not configured. " - "Please specify `vault_backend` option in your `KWonfig` initialization", + "Please specify `vault_backend` option in your `Konfig` initialization", ): config.SECRET @@ -68,16 +68,16 @@ def test_get_secret(path, config): ) def test_get_secret_with_prefix(vault_prefix, transform): """Trailing and leading slashes don't matter.""" - config = KWonfig(vault_backend=VaultBackend(transform(vault_prefix), try_env_first=False)) + config = Konfig(vault_backend=VaultBackend(transform(vault_prefix), try_env_first=False)) assert config.get_secret("/path/to") == {"SECRET": "value", "IS_SECRET": True, "DECIMAL": "1.3"} @pytest.mark.parametrize("action", (lambda c: c.get_secret("path/to"), lambda c: c.SECRET)) def test_disable_secrets(config, monkeypatch, action): - monkeypatch.setenv("KWONFIG_DISABLE_SECRETS", "1") + monkeypatch.setenv("KONFETTI_DISABLE_SECRETS", "1") with pytest.raises( RuntimeError, - match="Access to vault is disabled. Unset `KWONFIG_DISABLE_SECRETS` environment variable to enable it.", + match="Access to vault is disabled. Unset `KONFETTI_DISABLE_SECRETS` environment variable to enable it.", ): action(config) @@ -103,7 +103,7 @@ def test_path_not_string(): else: message = "'path' must be " with pytest.raises(TypeError, match=message): - kwonfig.vault(1) + konfetti.vault(1) @pytest.mark.parametrize( @@ -157,7 +157,7 @@ def test_disable_defaults(config, monkeypatch): @pytest.fixture def config_with_cached_vault(vault_prefix): - return KWonfig(vault_backend=VaultBackend(vault_prefix, cache_ttl=1)) + return Konfig(vault_backend=VaultBackend(vault_prefix, cache_ttl=1)) SECRET_DATA = {"DECIMAL": "1.3", "IS_SECRET": True, "SECRET": "value"} diff --git a/tox.ini b/tox.ini index 9f2356e..78bc904 100644 --- a/tox.ini +++ b/tox.ini @@ -8,7 +8,7 @@ passenv = deps = -r requirements.txt -r test-requirements.txt -commands = coverage run --source=kwonfig -m pytest {posargs:} test +commands = coverage run --source=konfetti -m pytest {posargs:} test [testenv:pylint] basepython = python3.7 @@ -19,13 +19,13 @@ deps = aiohttp pytest -r requirements.txt -commands = pylint {posargs:} src/kwonfig +commands = pylint {posargs:} src/konfetti [testenv:py27-tests] deps = -r requirements.txt -r 2.7-test-requirements.txt -commands = coverage run --source=kwonfig -m pytest {posargs:} test --ignore=test/test_async_vault.py +commands = coverage run --source=konfetti -m pytest {posargs:} test --ignore=test/test_async_vault.py [testenv:coverage-report] description = Report coverage over all measured test runs.