# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['typenv']

package_data = \
{'': ['*']}

install_requires = \
['python-dotenv>=0.10.3']

extras_require = \
{':python_version < "3.8"': ['typing-extensions>=3.7.4,<4.0.0']}

setup_kwargs = {
    'name': 'typenv',
    'version': '0.2.0',
    'description': 'Typed environment variable parsing for Python',
    'long_description': '[![Build Status](https://github.com/hukkinj1/typenv/workflows/Tests/badge.svg?branch=master)](https://github.com/hukkinj1/typenv/actions?query=workflow%3ATests+branch%3Amaster+event%3Apush)\n[![codecov.io](https://codecov.io/gh/hukkinj1/typenv/branch/master/graph/badge.svg)](https://codecov.io/gh/hukkinj1/typenv)\n[![PyPI version](https://img.shields.io/pypi/v/typenv)](https://pypi.org/project/typenv)\n\n# typenv\n\n<!--- Don\'t edit the version line below manually. Let bump2version do it for you. -->\n\n> Version 0.2.0\n\n> Typed environment variable parsing for Python\n\n**Table of Contents**  *generated with [mdformat-toc](https://github.com/hukkinj1/mdformat-toc)*\n\n<!-- mdformat-toc start --slug=github --maxlevel=6 --minlevel=2 -->\n\n- [Background](#background)\n- [Installing](#installing)\n- [Usage](#usage)\n  - [Basics](#basics)\n  - [Supported types](#supported-types)\n  - [Default values](#default-values)\n  - [Name prefixes](#name-prefixes)\n  - [Name character set](#name-character-set)\n  - [Name uppercasing](#name-uppercasing)\n  - [Validation](#validation)\n  - [Reading from a `.env` file](#reading-from-a-env-file)\n  - [Dumping parsed values](#dumping-parsed-values)\n- [Acknowledgments](#acknowledgments)\n\n<!-- mdformat-toc end -->\n\n## Background<a name="background"></a>\n\nTypenv does environment variable parsing with an API almost identical to the excellent [environs](https://github.com/sloria/environs).\nThere are a few reasons why typenv might be preferred:\n\n- Type annotated typecast functions: type checkers are able to understand types of parsed environment variables.\n- More flexible prefix manipulation of environment variable names.\n- Validation of environment variable names.\n- Optional automatic uppercasing of environment variable names.\n- Ability to generate a .env.example that shows expected types of environment variables.\n- Less dependencies. No [marshmallow](https://github.com/marshmallow-code/marshmallow) required.\n\n## Installing<a name="installing"></a>\n\nInstalling from PyPI repository (https://pypi.org/project/typenv):\n\n```bash\npip install typenv\n```\n\n## Usage<a name="usage"></a>\n\n### Basics<a name="basics"></a>\n\nSet environment variables:\n\n```bash\nexport NAME=\'Harry Potter\'\nexport AGE=14\nexport IS_WIZARD=true\nexport PATRONUM_SUCCESS_RATE=0.92\nexport BANK_BALANCE=134599.01\nexport LUCKY_NUMBERS=7,3,11\nexport EXTRA_DETAILS=\'{"friends": ["Hermione", "Ron"]}\'\nexport FAVORITE_COLOR=0x7f0909\n```\n\nParse the values in Python:\n\n```python\nfrom typenv import Env\n\nenv = Env()\n\nNAME = env.str("NAME")  # => "Harry Potter"\nAGE = env.int("AGE")  # => 14\nIS_WIZARD = env.bool("IS_WIZARD")  # => True\nPATRONUM_SUCCESS_RATE = env.float("PATRONUM_SUCCESS_RATE")  # => 0.92\nBANK_BALANCE = env.decimal("BANK_BALANCE")  # => decimal.Decimal("134599.01")\nLUCKY_NUMBERS = env.list("LUCKY_NUMBERS", subcast=int)  # => [7, 3, 11]\nEXTRA_DETAILS = env.json("EXTRA_DETAILS")  # => {"friends": ["Hermione", "Ron"]}\nFAVORITE_COLOR = env.bytes("FAVORITE_COLOR", encoding="hex")  # => b"\\x7f\\t\\t"\n\n# Optional settings must have a default value\nIS_DEATH_EATER = env.bool("IS_DEATH_EATER", default=False)  # => False\n```\n\n### Supported types<a name="supported-types"></a>\n\nThe types supported by typenv are:\n\n- `env.str`\n- `env.int`\n- `env.bool`\n- `env.float`\n- `env.decimal`\n- `env.list`\n  - Takes a `subcast` keyword argument for casting list items to one of `str`, `int` , `bool`, `float` or `decimal.Decimal`\n- `env.json`\n- `env.bytes`\n  - Takes an `encoding` keyword argument for indicating how the bytes are encoded.\n    For now only `hex` is supported.\n\n### Default values<a name="default-values"></a>\n\nNormally, if an environment variable is not found, typenv raises an exception.\nIf a default value is provided, however, that will be returned instead of raising.\n\n```python\nfrom typenv import Env\n\nenv = Env()\n\nBOOL = env.bool("NON_EXISTING_NAME", default=False)  # => False\nLIST = env.list("NON_EXISTING_NAME", default=["a", "b"])  # => ["a", "b"]\nOPTIONAL_INT = env.int("NON_EXISTING_NAME", default=None)  # => None\n```\n\n### Name prefixes<a name="name-prefixes"></a>\n\n```bash\nexport FLASK_HOST=127.0.0.1\nexport FLASK_PORT=44144\n```\n\n```python\nfrom typenv import Env\n\nenv = Env()\n\n# Explicitly prefixing variable names works, but repeats itself\n# (especially given more environment variables and nested prefixes).\nHOST = env.str("FLASK_HOST")  # => "127.0.0.1"\nPORT = env.int("FLASK_PORT")  # => 44144\n\n# This reads the same variables as above, and can be a nice way of\n# reducing repetition and expressing structure. Note that it is possible\n# to have nested `with` statements.\nwith env.prefixed("FLASK_"):\n    HOST = env.str("HOST")  # => "127.0.0.1"\n    PORT = env.int("PORT")  # => 44144\n\n# For more control, one can mutate `env.prefix` (of type list[str])\n# directly. Note that if an exception occurs reading the environment\n# variables, then `env.prefix` will not be reset to its initial value,\n# which is something that the `with` statement would take care of.\nenv.prefix.append("FLASK_")\nHOST = env.str("HOST")  # => "127.0.0.1"\nPORT = env.int("PORT")  # => 44144\nenv.prefix.pop()\n```\n\n### Name character set<a name="name-character-set"></a>\n\nTypenv validates environment variable names.\nBy default, the set of allowed characters includes upper case ASCII letters, digits and the underscore (`_`).\n\nThe set of allowed characters can be configured:\n\n```python\nfrom typenv import Env\n\nenv = Env(allowed_chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ")\n```\n\n### Name uppercasing<a name="name-uppercasing"></a>\n\n```bash\nexport UPPER_CASE_NAME=true\n```\n\n```python\nfrom typenv import Env\n\n# Environment variable names in type cast methods will automatically be upper\n# cased when `upper=True` is set here.\nenv = Env(upper=True)\n\nNAME = env.bool("upper_casE_Name")\n```\n\n### Validation<a name="validation"></a>\n\n```bash\nexport NAME=\'Harry Potter\'\nexport AGE=14\n```\n\n```python\nfrom typenv import Env\n\nenv = Env()\n\n# A single validator function\nNAME = env.str("NAME", validate=lambda n: n.startswith("Harry"))\n\n# A validator function can signal error by raising an exception\ndef is_positive(num):\n    if num <= 0:\n        raise Exception("Number is not positive")\n\n\n# A validator function can alternatively return `False` to signal an error\ndef is_less_than_thousand(num):\n    if num >= 1000:\n        return False\n    return True\n\n\n# Multiple validator functions can be passed as an iterable of callables\nAGE = env.int("AGE", validate=(is_positive, is_less_than_thousand))\n```\n\n### Reading from a `.env` file<a name="reading-from-a-env-file"></a>\n\nWhile developing, it is often useful to read environment variables from a file.\nTypenv supports this via the `Env.read_end()` method.\nThe method will look for a file (by default) named `.env` in current working directory\nand import environment variables from it.\nIf a file is not found,\nthe method will walk up in the directory tree until a file is found or the root directory is reached.\nThe method returns a boolean that is `True` if a file is found.\n\nGiven a `.env` file in current working directory with the following content\n\n```sh\nSOME_VAR=\'some value\'\n```\n\nThe following code will be able to read and parse the value\n\n```python\nfrom typenv import Env\n\nenv = Env()\nenv.read_env()\n\nSOME_VAR = env.str("SOME_VAR")  # => "some value"\n```\n\n### Dumping parsed values<a name="dumping-parsed-values"></a>\n\n```bash\nexport SOME_STR=blaablaa\nexport SOME_INT=99\n```\n\n```python\nfrom typenv import Env, ParsedValue\n\nenv = Env()\n\nSOME_STR = env.str("SOME_STR")\nSOME_INT = env.int("SOME_INT")\n\nassert env.dump() == {\n    "SOME_INT": ParsedValue(value=99, type="int", optional=False),\n    "SOME_STR": ParsedValue(value="blaablaa", type="str", optional=False),\n}\n```\n\n## Acknowledgments<a name="acknowledgments"></a>\n\nThe public API of this library is almost an exact copy of [environs](https://github.com/sloria/environs),\nwhich is based on [envparse](https://github.com/rconradharris/envparse) and [django-environ](https://github.com/joke2k/django-environ).\nCredit for the interface goes to the authors of those libraries.\n',
    'author': 'hukkinj1',
    'author_email': 'hukkinj1@users.noreply.github.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/hukkinj1/typenv',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'extras_require': extras_require,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
