mirror of
https://github.com/Steffo99/cfig.git
synced 2024-11-24 08:54:20 +00:00
💥 yay more things
This commit is contained in:
parent
aeb382fcde
commit
775c8c8a38
15 changed files with 324 additions and 26 deletions
14
cfig.iml
14
cfig.iml
|
@ -5,8 +5,22 @@
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/cfig" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/cfig" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/cfig/tests" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/cfig/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/docs" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/docs/_extra" type="java-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/docs/_static" type="java-resource" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/docs/_build" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.pytest_cache" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/cfig/.pytest_cache" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="PyNamespacePackagesService">
|
||||||
|
<option name="namespacePackageFolders">
|
||||||
|
<list>
|
||||||
|
<option value="$MODULE_DIR$/cfig/sources" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
</module>
|
</module>
|
|
@ -4,11 +4,27 @@ This package provides a simple but powerful configuration manager for Python app
|
||||||
A goal is to allow easy integration of an application with multiple configuration standards, such as environment
|
A goal is to allow easy integration of an application with multiple configuration standards, such as environment
|
||||||
variables, dotenv files, and Docker Secrets files.
|
variables, dotenv files, and Docker Secrets files.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@config.required()
|
||||||
|
def SECRET_KEY(val: str) -> str:
|
||||||
|
"Secret string used to manage tokens."
|
||||||
|
return val
|
||||||
|
|
||||||
Another goal is to provide informative error messages to the user who is configuring the application, so that they may
|
Another goal is to provide informative error messages to the user who is configuring the application, so that they may
|
||||||
understand what they are doing wrong and fix it immediately.
|
understand what they are doing wrong and fix it immediately.
|
||||||
|
|
||||||
The final goal is for the package to be fully typed, so that useful information can be received by the developer
|
.. code-block:: console
|
||||||
programming the consumption the configuration files.
|
|
||||||
|
$ python -m cfig.sample
|
||||||
|
=== Configuration ===
|
||||||
|
|
||||||
|
SECRET_KEY → Required, but not set.
|
||||||
|
Secret string used to manage HTTP session tokens.
|
||||||
|
|
||||||
|
HIDDEN_STRING = 'amogus'
|
||||||
|
A string which may be provided to silently print a string to the console.
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
=======
|
=======
|
||||||
|
@ -46,8 +62,8 @@ application::
|
||||||
return sqlalchemy.create_engine(val)
|
return sqlalchemy.create_engine(val)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# TODO: If the configuration file is executed as main, handle the call and display a user-friendly CLI interface.
|
# If the configuration file is executed as main, handle the call and display a user-friendly CLI interface.
|
||||||
config()
|
config.cli()
|
||||||
|
|
||||||
Values can later be accessed by the program by importing the configuration file:
|
Values can later be accessed by the program by importing the configuration file:
|
||||||
|
|
||||||
|
@ -66,11 +82,11 @@ Values can later be accessed by the program by importing the configuration file:
|
||||||
Terminology
|
Terminology
|
||||||
===========
|
===========
|
||||||
|
|
||||||
In this documentation, some terminology is used repeatedly:
|
In this documentation, the following terms are used:
|
||||||
|
|
||||||
Configuration key
|
Key
|
||||||
The name of a configuration value, usually in SCREAMING_SNAKE_CASE.
|
The name of a configuration value, usually in SCREAMING_SNAKE_CASE.
|
||||||
For example, `PATH`, the name of the environment variable.
|
For example, ``PATH``, the name of the environment variable.
|
||||||
|
|
||||||
Value
|
Value
|
||||||
A single non-processed configuration value in :class:`str` form.
|
A single non-processed configuration value in :class:`str` form.
|
||||||
|
|
|
@ -131,7 +131,7 @@ class Configuration:
|
||||||
log.debug("Item created successfully!")
|
log.debug("Item created successfully!")
|
||||||
|
|
||||||
log.debug("Registering item in the configuration...")
|
log.debug("Registering item in the configuration...")
|
||||||
self.register(key, item, doc or configurable.__doc__)
|
self.register(key, item, doc if doc is not None else configurable.__doc__)
|
||||||
log.debug("Registered successfully!")
|
log.debug("Registered successfully!")
|
||||||
|
|
||||||
# Return the created item, so it will take the place of the decorated function
|
# Return the created item, so it will take the place of the decorated function
|
||||||
|
@ -168,7 +168,7 @@ class Configuration:
|
||||||
log.debug("Item created successfully!")
|
log.debug("Item created successfully!")
|
||||||
|
|
||||||
log.debug("Registering item in the configuration...")
|
log.debug("Registering item in the configuration...")
|
||||||
self.register(key, item, doc or configurable.__doc__)
|
self.register(key, item, doc if doc is not None else configurable.__doc__)
|
||||||
log.debug("Registered successfully!")
|
log.debug("Registered successfully!")
|
||||||
|
|
||||||
# Return the created item, so it will take the place of the decorated function
|
# Return the created item, so it will take the place of the decorated function
|
||||||
|
@ -215,9 +215,6 @@ class Configuration:
|
||||||
val = self._retrieve_value_optional(key)
|
val = self._retrieve_value_optional(key)
|
||||||
log.debug("Retrieved value successfully!")
|
log.debug("Retrieved value successfully!")
|
||||||
|
|
||||||
if val is None:
|
|
||||||
log.debug(f"Not running user-defined configurable function since value is {val!r}.")
|
|
||||||
else:
|
|
||||||
log.debug("Running user-defined configurable function...")
|
log.debug("Running user-defined configurable function...")
|
||||||
val = resolver(val)
|
val = resolver(val)
|
||||||
|
|
||||||
|
@ -237,7 +234,7 @@ class Configuration:
|
||||||
else:
|
else:
|
||||||
raise errors.MissingValueError(key)
|
raise errors.MissingValueError(key)
|
||||||
|
|
||||||
def _create_proxy_required(self, key: str, f: ct.ResolverRequired) -> lazy_object_proxy.Proxy:
|
def _create_proxy_required(self, key: str, resolver: ct.ResolverRequired) -> lazy_object_proxy.Proxy:
|
||||||
"""
|
"""
|
||||||
Create, from a resolver, a proxy intolerant about non-specified values.
|
Create, from a resolver, a proxy intolerant about non-specified values.
|
||||||
"""
|
"""
|
||||||
|
@ -249,7 +246,7 @@ class Configuration:
|
||||||
log.debug("Retrieved val successfully!")
|
log.debug("Retrieved val successfully!")
|
||||||
|
|
||||||
log.debug("Running user-defined configurable function...")
|
log.debug("Running user-defined configurable function...")
|
||||||
val = f(val)
|
val = resolver(val)
|
||||||
|
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
@ -262,7 +259,7 @@ class Configuration:
|
||||||
:param key: The configuration key to register the proxy to.
|
:param key: The configuration key to register the proxy to.
|
||||||
:param proxy: The proxy to register in :attr:`.proxies`.
|
:param proxy: The proxy to register in :attr:`.proxies`.
|
||||||
:param doc: The docstring to register in :attr:`.docs`.
|
:param doc: The docstring to register in :attr:`.docs`.
|
||||||
:raises .errors.DuplicateProxyNameError` if the key already exists in either :attr:`.proxies` or :attr:`.docs`.
|
:raises .errors.DuplicateProxyNameError`: if the key already exists in either :attr:`.proxies` or :attr:`.docs`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if key in self.proxies:
|
if key in self.proxies:
|
||||||
|
|
|
@ -21,7 +21,7 @@ def MY_FAVOURITE_STRING(val: str) -> str:
|
||||||
@config.optional()
|
@config.optional()
|
||||||
def MY_OPTIONAL_STRING(val: typing.Optional[str]) -> str:
|
def MY_OPTIONAL_STRING(val: typing.Optional[str]) -> str:
|
||||||
"""
|
"""
|
||||||
Your favourite string, including the empty one!
|
Your favourite string, but optional!
|
||||||
"""
|
"""
|
||||||
return val or ""
|
return val or ""
|
||||||
|
|
||||||
|
@ -51,5 +51,13 @@ def MY_FAVOURITE_EVEN_INT(val: str) -> int:
|
||||||
return n
|
return n
|
||||||
|
|
||||||
|
|
||||||
|
@config.required(key="KEY_NAME")
|
||||||
|
def VAR_NAME(val: str) -> str:
|
||||||
|
"""
|
||||||
|
This config value looks for a key in the configuration sources but is available at a different key to the programmer.
|
||||||
|
"""
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
config.cli()
|
config.cli()
|
||||||
|
|
|
@ -8,7 +8,7 @@ class EnvironmentSource(Source):
|
||||||
A source which gets values from environment variables.
|
A source which gets values from environment variables.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *, prefix: str = "", suffix: str = "", environment=os.environ):
|
def __init__(self, *, prefix: str = "", suffix: str = "", environment=None):
|
||||||
self.prefix: str = prefix
|
self.prefix: str = prefix
|
||||||
"""
|
"""
|
||||||
The prefix to be prepended to all environment variable names.
|
The prefix to be prepended to all environment variable names.
|
||||||
|
@ -23,7 +23,7 @@ class EnvironmentSource(Source):
|
||||||
For example, ``_VAL`` for raw values.
|
For example, ``_VAL`` for raw values.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.environment = environment
|
self.environment = environment if environment is not None else os.environ
|
||||||
"""
|
"""
|
||||||
The environment to retrieve variable values from.
|
The environment to retrieve variable values from.
|
||||||
|
|
||||||
|
@ -36,4 +36,3 @@ class EnvironmentSource(Source):
|
||||||
def get(self, key: str) -> t.Optional[str]:
|
def get(self, key: str) -> t.Optional[str]:
|
||||||
key = self._process_key(key)
|
key = self._process_key(key)
|
||||||
return self.environment.get(key)
|
return self.environment.get(key)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import os
|
|
||||||
import typing as t
|
import typing as t
|
||||||
from cfig.sources.env import EnvironmentSource
|
from cfig.sources.env import EnvironmentSource
|
||||||
|
|
||||||
|
@ -6,9 +5,11 @@ from cfig.sources.env import EnvironmentSource
|
||||||
class EnvironmentFileSource(EnvironmentSource):
|
class EnvironmentFileSource(EnvironmentSource):
|
||||||
"""
|
"""
|
||||||
A source which gets values from files at paths specified in environment variables.
|
A source which gets values from files at paths specified in environment variables.
|
||||||
|
|
||||||
|
Useful for example with Docker Secrets.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *, prefix: str = "", suffix: str = "_FILE", environment=os.environ):
|
def __init__(self, *, prefix: str = "", suffix: str = "_FILE", environment=None):
|
||||||
super().__init__(prefix=prefix, suffix=suffix, environment=environment)
|
super().__init__(prefix=prefix, suffix=suffix, environment=environment)
|
||||||
|
|
||||||
def get(self, key: str) -> t.Optional[str]:
|
def get(self, key: str) -> t.Optional[str]:
|
||||||
|
|
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Minimal makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line, and also
|
||||||
|
# from the environment for the first two.
|
||||||
|
SPHINXOPTS ?=
|
||||||
|
SPHINXBUILD ?= sphinx-build
|
||||||
|
SOURCEDIR = .
|
||||||
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
# Put it first so that "make" without argument is like "make help".
|
||||||
|
help:
|
||||||
|
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
|
|
||||||
|
.PHONY: help Makefile
|
||||||
|
|
||||||
|
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||||
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
|
%: Makefile
|
||||||
|
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
0
docs/_extra/.gitignore
vendored
Normal file
0
docs/_extra/.gitignore
vendored
Normal file
0
docs/_static/.gitignore
vendored
Normal file
0
docs/_static/.gitignore
vendored
Normal file
0
docs/_templates/.gitignore
vendored
Normal file
0
docs/_templates/.gitignore
vendored
Normal file
145
docs/conf.py
Normal file
145
docs/conf.py
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
# Extended Sphinx configuration
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Imports #
|
||||||
|
###########
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
###########################
|
||||||
|
# Developer configuration #
|
||||||
|
###########################
|
||||||
|
# Alter these to reflect the nature of your project!
|
||||||
|
|
||||||
|
# Project name
|
||||||
|
project = 'cfig'
|
||||||
|
# Project author
|
||||||
|
author = 'Stefano Pigozzi'
|
||||||
|
# Project copyright
|
||||||
|
project_copyright = f'{datetime.date.today().year}, {author}'
|
||||||
|
|
||||||
|
# Sphinx language
|
||||||
|
language = "en"
|
||||||
|
|
||||||
|
# Configuration for the theme
|
||||||
|
html_theme_options = {
|
||||||
|
# Set this to the main color of your project
|
||||||
|
"style_nav_header_background": "#b72f37",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# Advanced configuration #
|
||||||
|
##########################
|
||||||
|
# Change these options only if you need further customization
|
||||||
|
|
||||||
|
# Sphinx extensions
|
||||||
|
extensions = [
|
||||||
|
"sphinx.ext.intersphinx",
|
||||||
|
"sphinx.ext.autodoc",
|
||||||
|
"sphinx.ext.autosectionlabel",
|
||||||
|
"sphinx.ext.todo",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Source files encoding
|
||||||
|
source_encoding = "UTF-8"
|
||||||
|
# Source file extensions
|
||||||
|
source_suffix = {
|
||||||
|
".rst": "restructuredtext",
|
||||||
|
}
|
||||||
|
# Source files parsers
|
||||||
|
source_parsers = {}
|
||||||
|
|
||||||
|
# The doc from which to start rendering
|
||||||
|
root_doc = "index"
|
||||||
|
# Files to ignore when rendering
|
||||||
|
exclude_patterns = [
|
||||||
|
"build",
|
||||||
|
"_build",
|
||||||
|
"Thumbs.db",
|
||||||
|
".DS_Store",
|
||||||
|
]
|
||||||
|
# Sphinx template files
|
||||||
|
templates_path = [
|
||||||
|
'_templates',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Prologue of all rst files
|
||||||
|
rst_prolog = ""
|
||||||
|
# Epilogue of all rst files
|
||||||
|
rst_epilog = ""
|
||||||
|
|
||||||
|
# Default domain
|
||||||
|
primary_domain = "py"
|
||||||
|
# Default role
|
||||||
|
default_role = "any"
|
||||||
|
|
||||||
|
# Print warnings on the page
|
||||||
|
keep_warnings = False
|
||||||
|
# Display more warnings than usual
|
||||||
|
nitpicky = False
|
||||||
|
|
||||||
|
# Intersphinx URLs
|
||||||
|
intersphinx_mapping = {
|
||||||
|
"python": ("https://docs.python.org/3.10/", None),
|
||||||
|
"lazy-object-proxy": ("https://python-lazy-object-proxy.readthedocs.io/en/latest/", None),
|
||||||
|
"click": ("https://click.palletsprojects.com/en/latest/", None),
|
||||||
|
}
|
||||||
|
# Manpages URL
|
||||||
|
manpages_url = "https://man.archlinux.org/"
|
||||||
|
|
||||||
|
# HTML builder theme
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
# Title of the HTML page
|
||||||
|
html_title = f"{project}"
|
||||||
|
# Short title of the HTML page
|
||||||
|
html_short_title = f"{project}"
|
||||||
|
# Path of the documentation static files
|
||||||
|
html_static_path = [
|
||||||
|
"_static",
|
||||||
|
]
|
||||||
|
# Path of extra files to add to the build
|
||||||
|
html_extra_path = [
|
||||||
|
"_extra",
|
||||||
|
]
|
||||||
|
# Disable additional indexes
|
||||||
|
html_domain_indices = False
|
||||||
|
|
||||||
|
# LaTeX rendering engine to use
|
||||||
|
latex_engine = "lualatex"
|
||||||
|
# LaTeX top level title type
|
||||||
|
latex_toplevel_sectioning = "chapter"
|
||||||
|
# LaTeX URLs rendering
|
||||||
|
latex_show_urls = "footnote"
|
||||||
|
# LaTeX theme
|
||||||
|
latex_theme = "manual"
|
||||||
|
|
||||||
|
# TODOs
|
||||||
|
todo_include_todos = True
|
||||||
|
todo_emit_warnings = True
|
||||||
|
todo_link_only = False
|
||||||
|
|
||||||
|
# Smartquotes
|
||||||
|
smartquotes_excludes = {
|
||||||
|
"languages": [
|
||||||
|
# Smartquotes is completely broken in italian!
|
||||||
|
"it",
|
||||||
|
# Keep the default, just in case
|
||||||
|
"ja",
|
||||||
|
],
|
||||||
|
"builders": [
|
||||||
|
"man",
|
||||||
|
"text",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Autodoc
|
||||||
|
autodoc_member_order = "bysource"
|
||||||
|
autodoc_default_options = {
|
||||||
|
"members": True,
|
||||||
|
"undoc-members": True,
|
||||||
|
}
|
63
docs/index.rst
Normal file
63
docs/index.rst
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
####
|
||||||
|
cfig
|
||||||
|
####
|
||||||
|
|
||||||
|
|
||||||
|
.. automodule:: cfig
|
||||||
|
|
||||||
|
|
||||||
|
Classes
|
||||||
|
=======
|
||||||
|
|
||||||
|
:mod:`cfig.config`
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. automodule:: cfig.config
|
||||||
|
|
||||||
|
|
||||||
|
:mod:`cfig.errors`
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. automodule:: cfig.errors
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
|
Built-in sources
|
||||||
|
----------------
|
||||||
|
|
||||||
|
:mod:`cfig.sources.base`
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. automodule:: cfig.sources.base
|
||||||
|
|
||||||
|
|
||||||
|
:mod:`cfig.sources.env`
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. automodule:: cfig.sources.env
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
|
:mod:`cfig.sources.envfile`
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. automodule:: cfig.sources.envfile
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
|
||||||
|
Table of contents
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. error::
|
||||||
|
|
||||||
|
I think I broke Sphinx, since the table of contents doesn't seem to show up...
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
|
||||||
|
Other tables and links
|
||||||
|
======================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" (
|
||||||
|
set SPHINXBUILD=sphinx-build
|
||||||
|
)
|
||||||
|
set SOURCEDIR=.
|
||||||
|
set BUILDDIR=_build
|
||||||
|
|
||||||
|
%SPHINXBUILD% >NUL 2>NUL
|
||||||
|
if errorlevel 9009 (
|
||||||
|
echo.
|
||||||
|
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||||
|
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||||
|
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||||
|
echo.may add the Sphinx directory to PATH.
|
||||||
|
echo.
|
||||||
|
echo.If you don't have Sphinx installed, grab it from
|
||||||
|
echo.https://www.sphinx-doc.org/
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "" goto help
|
||||||
|
|
||||||
|
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:help
|
||||||
|
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
|
||||||
|
:end
|
||||||
|
popd
|
4
poetry.lock
generated
4
poetry.lock
generated
|
@ -383,12 +383,12 @@ secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "cer
|
||||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||||
|
|
||||||
[extras]
|
[extras]
|
||||||
cli = ["click"]
|
cli = ["click", "colorama"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.10"
|
python-versions = "^3.10"
|
||||||
content-hash = "9003e7beceb925ef6b11961ef2a2bb818fbd8f659b312345dd58d86b786e589f"
|
content-hash = "5616faafcbdebee63818206fa4529a7dfad7b388a04e3ce34de995046a756e5b"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
alabaster = [
|
alabaster = [
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "cfig"
|
name = "cfig"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "The ultimate configuration manager"
|
description = "A configuration manager for Python"
|
||||||
authors = ["Stefano Pigozzi <me@steffo.eu>"]
|
authors = ["Stefano Pigozzi <me@steffo.eu>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue