commit e78719d41488d610e692111a63d3937601b41bdb Author: kirbylife Date: Thu Nov 2 02:14:32 2023 -0600 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/dist/nvexpo-0.1.0-py3-none-any.whl b/dist/nvexpo-0.1.0-py3-none-any.whl new file mode 100644 index 0000000..6c19651 Binary files /dev/null and b/dist/nvexpo-0.1.0-py3-none-any.whl differ diff --git a/dist/nvexpo-0.1.0.tar.gz b/dist/nvexpo-0.1.0.tar.gz new file mode 100644 index 0000000..eb6a95c Binary files /dev/null and b/dist/nvexpo-0.1.0.tar.gz differ diff --git a/nvexpo/__init__.py b/nvexpo/__init__.py new file mode 100644 index 0000000..5720ac4 --- /dev/null +++ b/nvexpo/__init__.py @@ -0,0 +1,51 @@ +#!/bin/python + +import sys + +from nvexpo import nvexpo + + +def main() -> int: + args = sys.argv + if len(args) <= 1: + nvexpo.help() + return 0 + if len(args) == 2 and args[1] in ["--load"]: + nvexpo.load() + return 0 + + if args[1] in ["--unset"]: + nvexpo.unset_env(args[2:]) + return 0 + + if args[1] in ["init"]: + try: + nvexpo.init(args[2]) + except IndexError: + nvexpo.init() + return 0 + + raw_vars = args[1:] + if not all("=" in x for x in raw_vars): + nvexpo.help() + return 1 + + variables = {} + for raw_var in raw_vars: + try: + key, value = raw_var.split("=", 1) + except ValueError: + nvexpo.help() + return 1 + key = key.strip("=") + value = value.strip("=").strip("\"") + variables[key] = value + if not key or not value: + nvexpo.help() + return 1 + nvexpo.set_env(variables) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/nvexpo/__pycache__/__init__.cpython-311.pyc b/nvexpo/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..5cf4592 Binary files /dev/null and b/nvexpo/__pycache__/__init__.cpython-311.pyc differ diff --git a/nvexpo/__pycache__/nvexpo.cpython-311.pyc b/nvexpo/__pycache__/nvexpo.cpython-311.pyc new file mode 100644 index 0000000..c5147bb Binary files /dev/null and b/nvexpo/__pycache__/nvexpo.cpython-311.pyc differ diff --git a/nvexpo/nvexpo.py b/nvexpo/nvexpo.py new file mode 100644 index 0000000..c6f6b5c --- /dev/null +++ b/nvexpo/nvexpo.py @@ -0,0 +1,107 @@ +import os +import sys +from enum import Enum +from pathlib import Path +from typing import IO, Any, Dict, List + +ENV_VARS = Path.home() / ".nvexpo.env" + + +class Mode(Enum): + R = "r" + W = "w" + +class Cmd(Enum): + Set = "export" + Unset = "unset" + + +def _get_file(mode: Mode) -> IO[Any]: + return ENV_VARS.open(mode.value) + +def _get_saved_vars() -> Dict[str, str]: + output = {} + with _get_file(Mode.R) as file: + for line in file: + line = line.strip() + if not line: + continue + key, value = line.split("=", 1) + output[key] = value + return output + +def _save_vars(variables: Dict[str, str]): + new_variables = [f"{key}={value}" for key, value in variables.items()] + + with _get_file(Mode.W) as file: + file.write("\n".join(new_variables)) + + +def _print_bulk(attrs: List[str], cmd: Cmd): + for attr in attrs: + print(f"{cmd.value} {attr}") + +def _load(): + current_vars = _get_saved_vars() + attrs = [f"{key}={value}" for key, value in current_vars.items()] + _print_bulk(attrs, Cmd.Set) + + +def set_env(variables: Dict[str, str]): + current_vars = _get_saved_vars() + current_vars.update(variables) + _save_vars(current_vars) + _load() + + +def unset_env(variables: List[str]): + current_vars = _get_saved_vars() + for var in variables: + current_vars.pop(var, None) + _save_vars(current_vars) + _print_bulk(variables, Cmd.Unset) + + +def help(error: None | str = None): + msg = """ + nx: Non-Volatile Export + + Basic usage: + - Set a simple var + $ nx VAR1="hello world" + $ echo VAR1 + hello world + + - Unset the variable + $ nx --unset VAR1 + $ echo VAR1 + + + - Persist into bash sessions + $ bash + $ nx VAR1="hello world" + $ exit + $ bash + $ echo $VAR1 + hello world + """.strip() + msg = "\n".join(map(str.strip, msg.splitlines())) + print(msg, file=sys.stderr) + + +def init(shell: str | None = None): + if shell is None: + shell = "bash" + + if shell == "bash": + cmd = """ + function nx(){ + eval "$(poetry run nvexpo $@)" + } + """ + print(cmd) + _load() + + +if not os.path.exists(ENV_VARS): + _get_file(Mode.W).close() diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..82d68fd --- /dev/null +++ b/poetry.lock @@ -0,0 +1,111 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "mypy" +version = "1.6.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e5012e5cc2ac628177eaac0e83d622b2dd499e28253d4107a08ecc59ede3fc2c"}, + {file = "mypy-1.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d8fbb68711905f8912e5af474ca8b78d077447d8f3918997fecbf26943ff3cbb"}, + {file = "mypy-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a1ad938fee7d2d96ca666c77b7c494c3c5bd88dff792220e1afbebb2925b5e"}, + {file = "mypy-1.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b96ae2c1279d1065413965c607712006205a9ac541895004a1e0d4f281f2ff9f"}, + {file = "mypy-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:40b1844d2e8b232ed92e50a4bd11c48d2daa351f9deee6c194b83bf03e418b0c"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245"}, + {file = "mypy-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183"}, + {file = "mypy-1.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0"}, + {file = "mypy-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660"}, + {file = "mypy-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7"}, + {file = "mypy-1.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71"}, + {file = "mypy-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41697773aa0bf53ff917aa077e2cde7aa50254f28750f9b88884acea38a16169"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7274b0c57737bd3476d2229c6389b2ec9eefeb090bbaf77777e9d6b1b5a9d143"}, + {file = "mypy-1.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbaf4662e498c8c2e352da5f5bca5ab29d378895fa2d980630656178bd607c46"}, + {file = "mypy-1.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bb8ccb4724f7d8601938571bf3f24da0da791fe2db7be3d9e79849cb64e0ae85"}, + {file = "mypy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:68351911e85145f582b5aa6cd9ad666c8958bcae897a1bfda8f4940472463c45"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:49ae115da099dcc0922a7a895c1eec82c1518109ea5c162ed50e3b3594c71208"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b27958f8c76bed8edaa63da0739d76e4e9ad4ed325c814f9b3851425582a3cd"}, + {file = "mypy-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925cd6a3b7b55dfba252b7c4561892311c5358c6b5a601847015a1ad4eb7d332"}, + {file = "mypy-1.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8f57e6b6927a49550da3d122f0cb983d400f843a8a82e65b3b380d3d7259468f"}, + {file = "mypy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a43ef1c8ddfdb9575691720b6352761f3f53d85f1b57d7745701041053deff30"}, + {file = "mypy-1.6.1-py3-none-any.whl", hash = "sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1"}, + {file = "mypy-1.6.1.tar.gz", hash = "sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "ruff" +version = "0.1.3" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.3-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b46d43d51f7061652eeadb426a9e3caa1e0002470229ab2fc19de8a7b0766901"}, + {file = "ruff-0.1.3-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b8afeb9abd26b4029c72adc9921b8363374f4e7edb78385ffaa80278313a15f9"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca3cf365bf32e9ba7e6db3f48a4d3e2c446cd19ebee04f05338bc3910114528b"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4874c165f96c14a00590dcc727a04dca0cfd110334c24b039458c06cf78a672e"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eec2dd31eed114e48ea42dbffc443e9b7221976554a504767ceaee3dd38edeb8"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dc3ec4edb3b73f21b4aa51337e16674c752f1d76a4a543af56d7d04e97769613"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e3de9ed2e39160800281848ff4670e1698037ca039bda7b9274f849258d26ce"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c595193881922cc0556a90f3af99b1c5681f0c552e7a2a189956141d8666fe8"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f75e670d529aa2288cd00fc0e9b9287603d95e1536d7a7e0cafe00f75e0dd9d"}, + {file = "ruff-0.1.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:76dd49f6cd945d82d9d4a9a6622c54a994689d8d7b22fa1322983389b4892e20"}, + {file = "ruff-0.1.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:918b454bc4f8874a616f0d725590277c42949431ceb303950e87fef7a7d94cb3"}, + {file = "ruff-0.1.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d8859605e729cd5e53aa38275568dbbdb4fe882d2ea2714c5453b678dca83784"}, + {file = "ruff-0.1.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0b6c55f5ef8d9dd05b230bb6ab80bc4381ecb60ae56db0330f660ea240cb0d4a"}, + {file = "ruff-0.1.3-py3-none-win32.whl", hash = "sha256:3e7afcbdcfbe3399c34e0f6370c30f6e529193c731b885316c5a09c9e4317eef"}, + {file = "ruff-0.1.3-py3-none-win_amd64.whl", hash = "sha256:7a18df6638cec4a5bd75350639b2bb2a2366e01222825562c7346674bdceb7ea"}, + {file = "ruff-0.1.3-py3-none-win_arm64.whl", hash = "sha256:12fd53696c83a194a2db7f9a46337ce06445fb9aa7d25ea6f293cf75b21aca9f"}, + {file = "ruff-0.1.3.tar.gz", hash = "sha256:3ba6145369a151401d5db79f0a47d50e470384d0d89d0d6f7fab0b589ad07c34"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "e3514d4266e70488cfa20fc30eeb51f431b8ac9831665219b843d1cbf51de209" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8e114ba --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,51 @@ +[tool.poetry] +name = "nvexpo" +version = "0.1.0" +description = "" +authors = ["kirbylife "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.8" + + +[tool.poetry.scripts] +nvexpo = "nvexpo:main" + +[tool.poetry.group.dev.dependencies] +ruff = "^0.1.3" +mypy = "^1.6.1" + +[tool.poe.tasks] +format = "ruff format ." +linter = "ruff nvexpo" +typing = "mypy nvexpo" + + +[tool.ruff] +target-version = "py38" +line-length=120 +indent-width=4 + +[tool.ruff.lint] +select = ["ALL"] +ignore = [ + "EXE001", + "D100", + "D101", + "D103", + "D104", + "PLR0911", + "T201", + "PLR2004", + "FA102" +] +fixable = ["ALL"] + +[tool.ruff.format] +quote-style = "double" +indent-style = "space" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/test.env b/test.env new file mode 100644 index 0000000..2864150 --- /dev/null +++ b/test.env @@ -0,0 +1 @@ +HELLO=10 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29