{ "info": { "author": "Mike Miller", "author_email": "mixmastamyk@bitbucket.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Systems Administration" ], "description": "\nEZ-Environment\n================\n\n*\"For easy access, baby!\u00a0 \u2026That's right.'\"\u2014Eazy-E*\n\nHave you ever thought handling environment variables in Python should be easier?\nIt is now.\n\n\nTL;DR:\n\n.. code:: python\n\n >>> import env\n\n >>> env.SERVER_PORT.int\n 8080\n\n*\"BAM!\" \u2014Emeril Lagasse*\n\nThe E.Z.E.nvironment module also has its own\n`theme song `_:\n\n *\"We want Eazy!\"*\n\n | *EAZY!*\n | *Everybody come on!*\n | *EAZY!*\n | *Who yall came to see?*\n | *EAZY!*\n | *A little louder come on!*\n | *EAZY!*\n | *Get those hands in the air!*\n | *EAZY!*\n | *Come on, come on say it!*\n | *EAZY!*\n | *A little louder come on!*\n | *EAZY!*\n | *Come on make some noise!*\n |\n | *A miracle of modern creation\u2026*\n | *EZ E's on the set, hyped up with the bass*\n | *And a little bit of what ya love*\n | *From a brother who's smooth like a criminal*\n | *I mean subliminal\u2026*\n\n\nBackground\n---------------\n\nIt's always been a tad clumsy to access environment variables and combine them\nwith other strings in Python\u2014\\\ncompared to shell languages at least.\nFor example, look how easy it is in (ba)sh:\n\n.. code:: shell\n\n \u23f5 echo \"Libraries: $PWD/lib\"\n Libraries: /usr/local/lib\n\nUnfortunately over in Python-land,\nrequired, escaped quotes and brackets\nserve mostly to complicate and add to visual clutter,\nreducing speed of comprehension.\n\n.. code:: python\n\n >>> from os import environ\n >>> from os.path import join\n\n >>> join(environ['PWD'], 'lib')\n '/usr/local/lib'\n\nEven the new-fangled string interpolation doesn't help as much as might be\nexpected:\n\n.. code:: python\n\n >>> print(f'Libraries: {environ[\"PWD\"]}/lib')\n Libraries: /usr/local/lib\n\n\nWith that in mind, allow me to introduce the ``env`` module.\nWith it I've tried to whittle complexity down,\nprimarily through direct attribute access:\n\n.. code:: python\n\n >>> import env\n\n >>> print('Term:', env.TERM)\n Term: xterm-256color\n\n >>> print(f'Libraries: {env.PWD}/lib')\n Libraries: /usr/local/lib\n\nBut wait, there's more!\n\n\nInstall\n---------------\n\n.. code:: shell\n\n \u23f5 pip3 install --user ezenv # env was taken :-/\n\n\u00a0\u261b LGPL licensed. \u261a\n\n\nEnvironment and options\n------------------------\n\nOn import the module loads the environment into its namespace,\nthereby working like a dictionary with convenient attribute access.\n\nSo, no additional mapping instance has to be created or imported,\nunless you'd like to configure the interface further.\nThe following options are available to customize:\n\n.. code:: python\n\n >>> from env import Environment\n\n >>> env = Environment(\n environ=os.environ,\n sensitive=True|False, # case: platform default\n writable=False,\n pathsep=os.pathsep,\n )\n\nParam: environ\n~~~~~~~~~~~~~~\n\nA mapping of your own choosing may optionally be passed in as the first argument,\nfor testing and/or other purposes.\nI've recently learned that\n`os.environb `_\n(bytes interface) is a thing that could be passed,\nfor example.\n\n\n.. ~ Noneify\n.. ~ ~~~~~~~~~~~~\n\n.. ~ Enabled by default,\n.. ~ this one signals non-existent variables by returning None.\n.. ~ It allows one to easily test for a variable and not have to worry about\n.. ~ catching exceptions.\n.. ~ If the variable is not set,\n.. ~ None will be returned instead:\n\n.. ~ .. code:: python\n\n .. ~ >>> if env.COLORTERM: # is not None or ''\n .. ~ pass\n\n\n.. ~ **Default Values**\n\n.. ~ The one drawback to returning ``None`` is that there is no ``.get()`` method\n.. ~ to return a default when the variable isn't found.\n.. ~ That's easily rectified like so:\n\n.. ~ .. code:: python\n\n .. ~ >>> env.FOO or 'bar'\n .. ~ 'bar'\n\n\n.. ~ Blankify\n.. ~ ~~~~~~~~~~~~\n\n.. ~ Off by default,\n.. ~ this option mimics the behavior of most command-line shells.\n.. ~ Namely if the variable isn't found,\n.. ~ it doesn't complain and returns an empty string instead.\n.. ~ This can make some cases simpler,\n.. ~ as fewer checks for errors are needed when checking contents::\n\n .. ~ if env.LANG.endswith('UTF-8'):\n .. ~ pass\n\n.. ~ instead of the Noneify version::\n\n .. ~ if env.LANG and env.LANG.endswith('UTF-8'):\n .. ~ pass\n\n.. ~ However,\n.. ~ it may be a bug-magnet in the case the variable is misspelled,\n.. ~ It is here if you need it for compatibility.\n.. ~ Blankify takes precedence over Noneify if enabled.\n\n\nParam: writable\n~~~~~~~~~~~~~~~\n\nBy default the Environment object/module does not allow modification since\nwriting is rarely needed.\nThis default helps to remind us of that fact,\nthough the object can be easily be changed to writable if need be by enabling\nthis option.\n\nParam: sensitivity \ud83d\ude22\n~~~~~~~~~~~~~~~~~~~~~~\n\nVariables are case-sensitive by default on Unix,\n*insensitive* under Windows.\n\nWhile case sensitivity can be disabled to use variable names in mixed or\nlower-case,\nbe aware that variables and dictionary methods are in the same namespace,\nwhich could potentially be problematic if they are not divided by case.\nFor this reason, using variable names such as \"keys\" and \"items\"\nare not a good idea while in insensitive mode.\n*shrug*\n\nWorkaround: use \"get item\" / dictionary-style syntax if needed:\n\n.. code:: python\n\n env['keys'] # :-/\n\n.. ~ varname = 'COLORTERM'\n.. ~ env[varname]\n\n\nEntry Objects\n----------------\n\nWhile using ``env`` at the interactive prompt,\nyou may be surprised that a variable value is not a simple string but rather\nan extended string-like object called an \"Entry.\"\nThis is most evident at the prompt since it prints a \"representation\"\nform by default:\n\n.. code:: python\n\n >>> env.PWD # a.k.a. repr()\n Entry('PWD', '/usr/local')\n\nThe reason behind this custom object is so that the variables can offer\nadditional functionality,\nsuch as parsing or conversion of the value to another type,\nwhile not crashing on a non-existent attribute access.\n\nNo matter however,\nas we've seen in the previous sections,\njust about any operation renders the string value as normal.\nAttributes ``.name`` and ``.value`` are also available for belt &\nsuspenders types:\n\n.. code:: python\n\n >>> print(env.PWD)\n /usr/local\n\n >>> env.PWD.name, env.PWD.value, str(env.PWD)\n ('PWD', '/tmp', '/tmp')\n\nRemember the ``env`` object/module is also a standard dictionary,\nwhile entry values are also strings,\nso full Python functionality is available:\n\n.. code:: python\n\n >>> for key, value in env.items(): # it's a dict*\n print(key, value)\n\n # USER\u00a0fred\u2026\n\n >>> env.USER.title() # it's a str*\n 'Fred'\n\n >>> env.TERM.partition('-') # tip: a safer split\n ('xterm', '-', '256color')\n\n*\u00a0 Sung to the tune, *\"It's a Sin,\"* by the Pet Shop Boys.\n\n\nParsing & Conversions\n-----------------------\n\nAnother handy feature of Entry objects is convenient type conversion and\nparsing of values from strings.\nAdditional properties for this functionality are available.\nFor example:\n\n.. code:: python\n\n >>> env.PI.float\n 3.1416\n\n >>> env.STATUS.int\n 5150\n\n >>> env.DATA.from_json\n {'one': 1, 'two': 2, 'three': 3}\n\n\nTruthy Values\n~~~~~~~~~~~~~~~~~~~~\n\nVariable entries may contain boolean-*like* string values,\nsuch as ``0, 1, yes, no, true, false``, etc.\nTo interpret them in a case-insensitive manner use the ``.truthy`` property:\n\n.. code:: python\n\n >>> env.QT_ACCESSIBILITY\n Entry('QT_ACCESSIBILITY', '1')\n\n >>> env.QT_ACCESSIBILITY.truthy\n True\n\n >>> env = Environment(writable=True)\n >>> env.QT_ACCESSIBILITY = '0' #\u00a0set to '0'\n\n >>> env.QT_ACCESSIBILITY.truthy\n False\n\n\nStandard Boolean Tests\n++++++++++++++++++++++++\n\nAs always, standard tests or ``bool()`` on the entry can be done to check a\nstring.\nRemember, such a test checks merely if the string is empty or not,\nand would also return ``True`` on ``'0'`` or ``'false'``.\n\n\nPaths\n~~~~~~~~\n\nEnvironment vars often contain a list of filesystem paths.\nTo split such path strings on ``os.pathsep``\\\n`\ud83d\udd17 `_,\nwith optional conversion to ``pathlib.Path``\\\n`\ud83d\udd17\u00b2 `_\nobjects,\nuse one or more of the following:\n\n.. code:: python\n\n >>> env.XDG_DATA_DIRS.list\n ['/usr/local/share', '/usr/share', ...] #\u00a0strings\n\n >>> env.SSH_AUTH_SOCK.path\n Path('/run/user/1000/keyring/ssh')\n\n >>> env.XDG_DATA_DIRS.path_list\n [Path('/usr/local/share'), Path('/usr/share'), ...]\n\nTo split on a different character,\nsimply do the split/partition on the string manually.\n(There is a ._pathsep variable that can be set on each entry,\nbut not particularly more convenient.)\n\n\nExamples\n---------------\n\nThere are generally three cases for environment variables:\n\n**Variable exists, has value:**\n\n.. code:: python\n\n >>> env.USER # exists, repr\n Entry('USER', 'fred')\n\n >>> env.USER + '_suffix' # str ops\n 'fred_suffix'\n\n >>> env.USER.title() # str ops II\n 'Fred'\n\n >>> print(f'term: {env.TERM}') # via interpolation\n term: xterm-256color\n\n >>> bool(env.USER) # check exists & not empty\n True\n\n >>> key_name = 'PI'\n >>> env[key_name] # getitem syntax\n '3.1416'\n\n >>> env.PI.float # type conversion\n 3.1416\n\n >>> env.PORT.int or 9000 #\u00a0type conv. w/ default\n 5150\n\n >>> env.QT_ACCESSIBILITY.truthy # 0/1/yes/no/true/false\n True\n\n >>> env.JSON_DATA.from_json.keys()\n ['one', 'three', 'two']\n\n >>> env.XDG_DATA_DIRS.list\n ['/usr/local/share', '/usr/share']\n\n\n**Variable exists, but is blank:**\n\n.. code:: python\n\n >>> 'EMPTY' in env # check existence\n True\n\n >>> env.EMPTY #\u00a0exists but empty\n Entry('EMPTY', '')\n\n >>> bool(env.EMPTY) # check exists & not empty\n False\n\n >>> env.EMPTY or 'default' #\u00a0exists, blank\u00a0w/ default\n 'default'\n\n\n**Variable doesn't exist:**\n\n.. code:: python\n\n >>> 'NO_EXISTO' in env # check existence\n False\n\n >>> env.NO_EXISTO or 'default' #\u00a0DNE\u00a0with default\n 'default'\n\n >>> env.NO_EXISTO #\u00a0Doesn't exist repr\n NullEntry('NO_EXISTO')\n\n >>> bool(env.NO_EXISTO) # check exists & not empty\n False\n\n >>> env.XDG_DATA_DIRz.list # DNE fallback\n []\n\n for data_dir in env.XDG_DATA_DIR.list:\n # Don't need to worry if this exists or not,\n # if not, it will be skipped.\n pass\n\n\n\nCompatibility\n---------------\n\n*\"What's the frequency Kenneth?\"*\n\nThis module attempts compatibility with KR's existing\n`env `_\npackage by implementing its ``prefix`` and ``map`` functions:\n\n.. code:: python\n\n >>> env.prefix('XDG_') #\u00a0from_prefix preferred\n {'config_dirs': '/etc/xdg/xdg-mate:/etc/xdg', ...}\n\n >>> env.map(username='USER')\n {'username': 'fred'}\n\nThe lowercase transform can be disabled by passing another false-like value\nas the second argument to ``prefix().``\n\nWhile the package above has the coveted ``env`` namespace on PyPI,\nezenv uses the same simple module name and provides an implementation of the\ninterface.\n\n\nTests\n---------------\n\nCan be run here:\n\n.. code:: shell\n\n \u23f5 python3 -m env -v\n\nThough this module works under Python2,\nseveral of the tests *don't*,\nbecause Py2 does Unicode differently or\ndoesn't have the facilities available to handle them by default\n(pathlib/f-string).\nHaven't had the urge to work around that due to declining interest.\n\nFYI, a reference to the original module object is kept at ``env._module``\njust in case it is needed for some reason.\n\n\nTesting *with* ezenv\n~~~~~~~~~~~~~~~~~~~~~\n\nWhen you've used ``ezenv`` in your project,\nit is easy to create a custom environment to operate under:\n\n.. code:: python\n\n from env import Environment\n\n def test_foo():\n import mymodule\n\n mymodule.env = Environment(environ=dict(NO_COLOR='1'))\n assert mymodule.color_is_disabled() == True\n\n\nPricing\n---------------\n\n*\"I'd buy THAT for a dollar!\" :-D*\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/mixmastamyk/env", "keywords": "", "license": "LGPL", "maintainer": "", "maintainer_email": "", "name": "ezenv", "package_url": "https://pypi.org/project/ezenv/", "platform": "", "project_url": "https://pypi.org/project/ezenv/", "project_urls": { "Homepage": "https://github.com/mixmastamyk/env" }, "release_url": "https://pypi.org/project/ezenv/0.91/", "requires_dist": null, "requires_python": "", "summary": "A more convenient interface to environment variables.", "version": "0.91" }, "last_serial": 5908370, "releases": { "0.86": [ { "comment_text": "", "digests": { "md5": "b8597a89c4809aea9203d1eabbd1b274", "sha256": "aa0eba21338886fc0b195a825204eef13c5bc09d9dc9ae6562e7065a9236ae21" }, "downloads": -1, "filename": "ezenv-0.86-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b8597a89c4809aea9203d1eabbd1b274", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 9708, "upload_time": "2018-10-09T01:01:48", "url": "https://files.pythonhosted.org/packages/d1/3c/323d00957ec94ee3a20d445a9bec463574838a6f64a4b1182cd0e76bf8ed/ezenv-0.86-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "49ffa0d9b8856611ca0c3e5836a3ce7d", "sha256": "e540fcc2e56cb378ba3f1bdbb524e24f7aa72b88bc823a6aee095ec32de4ff73" }, "downloads": -1, "filename": "ezenv-0.86.tar.gz", "has_sig": false, "md5_digest": "49ffa0d9b8856611ca0c3e5836a3ce7d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8518, "upload_time": "2018-10-09T01:01:46", "url": "https://files.pythonhosted.org/packages/0e/41/a229f6007a47f588c6bcd09631883f99e3e11ee21f82ea778a39337169d4/ezenv-0.86.tar.gz" } ], "0.91": [ { "comment_text": "", "digests": { "md5": "c3c39e6cec49bb933b02bd2f164e34b6", "sha256": "205d67c1124771c41c76ea5b036863f5556a3b555a2cf068f6262ab6d6cd73ee" }, "downloads": -1, "filename": "ezenv-0.91-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c3c39e6cec49bb933b02bd2f164e34b6", "packagetype": "bdist_wheel", "python_version": "3.7", "requires_python": null, "size": 10872, "upload_time": "2019-09-30T05:52:03", "url": "https://files.pythonhosted.org/packages/05/76/baabc32ea7188454cfb14770cd65a59d04603aec1d9b9037a9a233a4cf07/ezenv-0.91-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "fec80b756676d6acd73f0ebdaaf33907", "sha256": "2648ea10168d9299cd295c99045e7c886e3b3124223af642769423e53bc0ae2b" }, "downloads": -1, "filename": "ezenv-0.91.tar.gz", "has_sig": false, "md5_digest": "fec80b756676d6acd73f0ebdaaf33907", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9558, "upload_time": "2019-09-30T05:51:59", "url": "https://files.pythonhosted.org/packages/5b/4b/8682242c4115b73f603367d271f51078bb960f749ae0ec6ce8ea9c43d7e5/ezenv-0.91.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c3c39e6cec49bb933b02bd2f164e34b6", "sha256": "205d67c1124771c41c76ea5b036863f5556a3b555a2cf068f6262ab6d6cd73ee" }, "downloads": -1, "filename": "ezenv-0.91-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c3c39e6cec49bb933b02bd2f164e34b6", "packagetype": "bdist_wheel", "python_version": "3.7", "requires_python": null, "size": 10872, "upload_time": "2019-09-30T05:52:03", "url": "https://files.pythonhosted.org/packages/05/76/baabc32ea7188454cfb14770cd65a59d04603aec1d9b9037a9a233a4cf07/ezenv-0.91-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "fec80b756676d6acd73f0ebdaaf33907", "sha256": "2648ea10168d9299cd295c99045e7c886e3b3124223af642769423e53bc0ae2b" }, "downloads": -1, "filename": "ezenv-0.91.tar.gz", "has_sig": false, "md5_digest": "fec80b756676d6acd73f0ebdaaf33907", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9558, "upload_time": "2019-09-30T05:51:59", "url": "https://files.pythonhosted.org/packages/5b/4b/8682242c4115b73f603367d271f51078bb960f749ae0ec6ce8ea9c43d7e5/ezenv-0.91.tar.gz" } ] }