├── default.nix ├── .gitignore ├── .envrc ├── GNUmakefile ├── pyproject.toml ├── config.nix ├── LICENSE ├── README.md ├── keyring_pass ├── __main__.py └── __init__.py ├── flake.nix ├── flake.lock └── poetry.lock /default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }@args: (import ./config.nix args).pkg 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.egg-info 3 | __pycache__ 4 | 5 | /build 6 | /dist 7 | !/.envrc 8 | /.devenv 9 | /.direnv -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | watch_file poetry.lock pyproject.toml config.nix default.nix 2 | 3 | if ! use flake . --show-trace --print-build-logs --impure; then 4 | echo "devenv could not be build. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2 5 | fi 6 | 7 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | SHELL := $(shell which bash) 2 | .SHELLFLAGS = -xeuEo pipefail -c 3 | .ONESHELL: 4 | 5 | .PHONY: clean test build publish 6 | 7 | clean: 8 | rm -rf build dist || true 9 | 10 | # see https://realpython.com/pypi-publish-python-package/#build-your-package 11 | build: clean 12 | poetry build 13 | 14 | test: 15 | python -m "keyring_pass.__init__" 16 | 17 | # see https://realpython.com/pypi-publish-python-package/#upload-your-package 18 | # poetry config http-basic.pypi __token__ pypi- 19 | publish: build 20 | poetry publish 21 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "keyring-pass" 3 | version = "0.9.3" 4 | description = "https://www.passwordstore.org/ backend for https://pypi.org/project/keyring/" 5 | authors = ["Krzysztof Nazarewski <3494992+nazarewk@users.noreply.github.com>"] 6 | homepage = "https://github.com/nazarewk/keyring_pass" 7 | repository = "https://github.com/nazarewk/keyring_pass" 8 | license = "MIT" 9 | readme = "README.md" 10 | keywords = [ 11 | "keyring", 12 | "pass", 13 | ] 14 | classifiers = [] 15 | packages = [{ include = "keyring_pass" }] 16 | 17 | [tool.poetry.dependencies] 18 | python = ">=3.7" # required by `jaraco.classes` 19 | keyring = ">=23.9.3" 20 | jaraco-classes = ">=3.2.3" 21 | 22 | [tool.poetry.plugins."keyring.backends"] 23 | pass = "keyring_pass" 24 | 25 | 26 | [build-system] 27 | requires = ["poetry-core"] 28 | build-backend = "poetry.core.masonry.api" 29 | -------------------------------------------------------------------------------- /config.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | let 3 | inherit (pkgs) lib; 4 | 5 | attrs = { 6 | python = pkgs.python311; 7 | projectDir = ./.; 8 | pyproject = ./pyproject.toml; 9 | poetrylock = ./poetry.lock; 10 | overrides = pkgs.poetry2nix.defaultPoetryOverrides.extend (final: prev: { 11 | # fido2 = prev.fido2.overridePythonAttrs (old: { buildInputs = (old.buildInputs or [ ]) ++ [ final.poetry ]; }); 12 | # yubikey-manager = prev.yubikey-manager.overridePythonAttrs (old: { buildInputs = (old.buildInputs or [ ]) ++ [ final.poetry ]; }); 13 | }); 14 | }; 15 | 16 | cfg = builtins.fromTOML (builtins.readFile attrs.pyproject); 17 | name = cfg.tool.poetry.name; 18 | pkg = pkgs.poetry2nix.mkPoetryApplication (attrs // { }); 19 | env = pkgs.poetry2nix.mkPoetryEnv (attrs // { 20 | editablePackageSources = { 21 | "${name}" = attrs.projectDir; 22 | }; 23 | }); 24 | in 25 | { 26 | inherit pkg env cfg; 27 | inherit (attrs) python; 28 | bin = "${pkg}/bin/${name}"; 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Krzysztof Nazarewski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # keyring_pass 2 | 3 | This is a [`pass`](https://www.passwordstore.org/) backend for [`keyring`](https://pypi.org/project/keyring/) 4 | 5 | Install with `pip install keyring-pass` and set the following content in 6 | your [`keyringrc.cfg`](https://pypi.org/project/keyring/#config-file-path) file: 7 | 8 | ```ini 9 | [backend] 10 | default-keyring = keyring_pass.PasswordStoreBackend 11 | ``` 12 | 13 | You can modify the default `python-keyring` prefix for `pass`, by: 14 | 15 | - adding following to `keyringrc.cfg`: 16 | 17 | ```ini 18 | [pass] 19 | key-prefix=alternative/prefix/path 20 | binary=gopass 21 | ``` 22 | 23 | - (for `keyring` version 23.0.0 or higher) setting environment variables: 24 | - `KEYRING_PROPERTY_PASS_KEY_PREFIX` 25 | - `KEYRING_PROPERTY_PASS_BINARY` 26 | 27 | - You can clear the path (start from root), by setting above to `.` or an empty value (just `key-prefix=` on the line). 28 | 29 | ## Test your setup 30 | 31 | You can check if your setup works end-to-end (creates, reads and deletes a key from password store). 32 | 33 | ```shell 34 | # warning: this will create and delete a key at `/test/asd` in your password store 35 | python -m keyring_pass 36 | ``` 37 | -------------------------------------------------------------------------------- /keyring_pass/__main__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import keyring 4 | 5 | from keyring_pass import PasswordStoreBackend 6 | svc = "test" 7 | user = "asd" 8 | pwd = "zxc" 9 | 10 | keyring.set_keyring(PasswordStoreBackend()) 11 | errors = [] 12 | print(f"testing with {svc=} {user=} {pwd=}") 13 | 14 | try: 15 | keyring.set_password(svc, user, pwd) 16 | returned = keyring.get_password(svc, user) 17 | credential = keyring.get_credential(svc, None) 18 | finally: 19 | keyring.delete_password(svc, user) 20 | 21 | if returned != pwd: 22 | errors.append(f"get_password(): {returned=} != {pwd=}") 23 | else: 24 | print(f"OK: get_password(): matches") 25 | 26 | if not credential: 27 | errors.append(f"get_credential() not found ({credential=})") 28 | else: 29 | print(f"OK: get_credential(): found") 30 | if credential.username != user: 31 | errors.append( 32 | f"get_credential(): {credential.username=} doesn't match {user=}" 33 | ) 34 | else: 35 | print(f"OK: get_credential(): username matches") 36 | 37 | if credential.password != pwd: 38 | errors.append( 39 | f"get_credential(): {credential.password=} doesn't match {pwd=}" 40 | ) 41 | else: 42 | print(f"OK: get_credential(): password matches") 43 | 44 | for err in errors: 45 | print(f"ERROR: {err}") 46 | if errors: 47 | sys.exit(1) 48 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Description for the project"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 | #devenv.url = "github:cachix/devenv/latest"; 7 | #devenv.url = "github:cachix/devenv/main"; 8 | # see https://github.com/cachix/devenv/pull/503 9 | devenv.url = "github:nazarewk/devenv/flake-parts-container-usage"; 10 | #devenv.url = "/home/kdn/dev/github.com/cachix/devenv"; 11 | nix2container.url = "github:nlewo/nix2container"; 12 | nix2container.inputs.nixpkgs.follows = "nixpkgs"; 13 | nix2container.inputs.flake-utils.follows = "flake-utils"; 14 | mk-shell-bin.url = "github:rrbutani/nix-mk-shell-bin"; 15 | flake-utils.url = "github:numtide/flake-utils"; 16 | 17 | #poetry2nix.url = "github:nazarewk/poetry2nix"; 18 | poetry2nix.url = "github:nix-community/poetry2nix"; 19 | poetry2nix.inputs.nixpkgs.follows = "nixpkgs"; 20 | poetry2nix.inputs.flake-utils.follows = "flake-utils"; 21 | }; 22 | 23 | outputs = inputs@{ self, nixpkgs, flake-parts, poetry2nix, ... }: flake-parts.lib.mkFlake { inherit inputs; } { 24 | imports = [ 25 | inputs.devenv.flakeModule 26 | ]; 27 | systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; 28 | 29 | flake = { 30 | # Nixpkgs overlay providing the application 31 | overlays.default = nixpkgs.lib.composeManyExtensions [ 32 | poetry2nix.overlay 33 | ]; 34 | }; 35 | 36 | perSystem = { config, self', inputs', system, ... }: 37 | let 38 | pkgs = import nixpkgs { 39 | inherit system; 40 | overlays = [ self.overlays.default ]; 41 | }; 42 | conf = import ./config.nix { inherit pkgs; }; 43 | in 44 | { 45 | packages.default = conf.pkg; 46 | devenv.shells.default = { 47 | name = "default"; 48 | 49 | languages.python.enable = true; 50 | languages.python.package = conf.python; 51 | languages.python.poetry.enable = true; 52 | languages.python.poetry.install.installRootPackage = true; 53 | 54 | # https://devenv.sh/reference/options/ 55 | packages = with pkgs; [ 56 | pass 57 | black 58 | ]; 59 | }; 60 | }; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /keyring_pass/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import configparser 3 | import os 4 | import re 5 | import shutil 6 | import subprocess 7 | import sys 8 | 9 | import keyring 10 | from jaraco.classes import properties 11 | from keyring import backend, credentials 12 | from keyring.util import platform_ as platform 13 | 14 | try: 15 | from functools import cache 16 | except ImportError: 17 | from functools import lru_cache 18 | 19 | cache = lru_cache(maxsize=None) 20 | 21 | 22 | def command(cmd, **kwargs) -> str: 23 | kwargs.setdefault("encoding", "utf8") 24 | kwargs.setdefault("stderr", sys.stderr) 25 | try: 26 | return subprocess.check_output(cmd, **kwargs) 27 | except subprocess.CalledProcessError as exc: 28 | pattern = "password store is empty" 29 | if pattern in exc.output: 30 | raise RuntimeError(exc.output) 31 | sys.stderr.write(exc.stdout) 32 | raise 33 | 34 | 35 | @cache 36 | def _load_config( 37 | keyring_cfg=os.path.join(platform.config_root(), "keyringrc.cfg"), 38 | ): 39 | cfg = {} 40 | if not os.path.exists(keyring_cfg): 41 | return cfg 42 | 43 | config = configparser.RawConfigParser() 44 | config.read(keyring_cfg) 45 | for attr, option in PasswordStoreBackend.INI_OPTIONS.items(): 46 | try: 47 | cfg[attr] = config.get("pass", option) 48 | except (configparser.NoSectionError, configparser.NoOptionError): 49 | pass 50 | return cfg 51 | 52 | 53 | class PasswordStoreBackend(backend.KeyringBackend): 54 | pass_key_prefix = "python-keyring" 55 | pass_binary = "pass" 56 | pass_exact_service = True 57 | 58 | INI_OPTIONS = { 59 | "pass_key_prefix": "key-prefix", 60 | "pass_binary": "binary", 61 | "pass_exact_service": "exact-service", 62 | } 63 | 64 | def __init__(self): 65 | for k, v in _load_config().items(): 66 | setattr(self, k, v) 67 | if isinstance(self.pass_exact_service, str): 68 | self.pass_exact_service = self.pass_exact_service.lower() == "true" 69 | self.pass_key_prefix = os.path.normpath(self.pass_key_prefix) 70 | super().__init__() 71 | 72 | @properties.classproperty 73 | def priority(cls): 74 | binary = _load_config().get("pass_binary", cls.pass_binary) 75 | if not shutil.which(binary): 76 | raise RuntimeError(f"`{binary}` executable is missing!") 77 | 78 | command([binary, "ls"]) 79 | return 1 80 | 81 | def get_key(self, service, username): 82 | service = os.path.normpath(service) 83 | path = ( 84 | os.path.join(self.pass_key_prefix, service) 85 | if self.pass_key_prefix 86 | else service 87 | ) 88 | if username: 89 | path = os.path.join(path, username) 90 | return path 91 | 92 | def set_password(self, servicename, username, password): 93 | password = password.splitlines()[0] 94 | inp = "%s\n" % password 95 | inp *= 2 96 | 97 | command( 98 | [ 99 | self.pass_binary, 100 | "insert", 101 | "--force", 102 | self.get_key(servicename, username), 103 | ], 104 | input=inp, 105 | ) 106 | 107 | def get_credential(self, servicename, username): 108 | if username: 109 | return credentials.SimpleCredential( 110 | username, 111 | self.get_password(servicename, username), 112 | ) 113 | try: 114 | servicename = os.path.normpath(servicename) 115 | service_key = self.get_key(servicename, None) 116 | output = command([self.pass_binary, "ls", service_key]) 117 | except subprocess.CalledProcessError as exc: 118 | if exc.returncode == 1: 119 | return None 120 | raise 121 | # Currently pass only has tree like structure output. 122 | # Internally it uses the command tree but does not pass 123 | # output formatter options (e.g., for json). 124 | lines = output.splitlines() 125 | lines = [re.sub(r"\x1B\[([0-9]+;)?[0-9]+m", "", line) for line in lines] 126 | 127 | # Assumption that output paths must contain leaves. 128 | # Services and users are entries in our keyring. Thus remove any 129 | # non-word char from the left. 130 | entries = [re.sub(r"^\W+", "", line) for line in lines] 131 | # Just in case: Remove empty entries and corresponding lines 132 | indents, entries = zip( 133 | *[ 134 | (len(line) - len(entry), entry) 135 | for line, entry in zip(lines, entries) 136 | if entry 137 | ] 138 | ) 139 | # The count of removed characters tells us how far elements are indented. 140 | # Elements with the same count are on the same level. 141 | # EOF tree is at indent 0 again. 142 | indents = list(indents) + [0] 143 | entries = list(entries) 144 | # Now to identify the user entries from service keys we must identify 145 | # which elements do not have further entries further down the structure. 146 | # This means that the next element is not indented any further. 147 | users_ids = [ 148 | i for i, j in enumerate(zip(indents[:-1], indents[1:])) if j[0] >= j[1] 149 | ] 150 | # A user with the least indent is closest to the specified service path. 151 | users_ids = sorted(users_ids, key=lambda i: indents[i]) 152 | 153 | # Parse hierarchy and get complete path 154 | if users_ids: 155 | idx = users_ids[0] 156 | username = entries[idx] 157 | # current level of the last added service key 158 | branch_indent = indents[idx] 159 | # last level that can be added 160 | # so stop there. 161 | top_indent = indents[1] 162 | paths = [] 163 | 164 | while branch_indent > top_indent: 165 | idx = idx - 1 166 | # higher up in the tree or same level 167 | indent = indents[idx] 168 | if indent < branch_indent: 169 | # less indented means new service key 170 | paths.insert(0, entries[idx]) 171 | branch_indent = indent 172 | 173 | found_service = os.path.join(servicename, *paths) if paths else servicename 174 | 175 | if (not self.pass_exact_service) or servicename == found_service: 176 | return credentials.SimpleCredential( 177 | username, self.get_password(found_service, username) 178 | ) 179 | return None 180 | 181 | def get_password(self, servicename, username): 182 | try: 183 | ret = command( 184 | [self.pass_binary, "show", self.get_key(servicename, username)] 185 | ) 186 | except subprocess.CalledProcessError as exc: 187 | if exc.returncode == 1: 188 | return None 189 | raise 190 | return ret.splitlines()[0] 191 | 192 | def delete_password(self, service, username): 193 | command([self.pass_binary, "rm", "--force", self.get_key(service, username)]) 194 | 195 | 196 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "devenv": { 4 | "inputs": { 5 | "flake-compat": "flake-compat", 6 | "nix": "nix", 7 | "nixpkgs": "nixpkgs", 8 | "pre-commit-hooks": "pre-commit-hooks" 9 | }, 10 | "locked": { 11 | "lastModified": 1686126528, 12 | "narHash": "sha256-03fzC/XVkaFzCJvWMPXLf8/VCN/V0Av8yN7WpZo79nU=", 13 | "owner": "nazarewk", 14 | "repo": "devenv", 15 | "rev": "8a0568cddfe46dd4d1b5dd7c85a25889b4c9c893", 16 | "type": "github" 17 | }, 18 | "original": { 19 | "owner": "nazarewk", 20 | "ref": "flake-parts-container-usage", 21 | "repo": "devenv", 22 | "type": "github" 23 | } 24 | }, 25 | "flake-compat": { 26 | "flake": false, 27 | "locked": { 28 | "lastModified": 1673956053, 29 | "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", 30 | "owner": "edolstra", 31 | "repo": "flake-compat", 32 | "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", 33 | "type": "github" 34 | }, 35 | "original": { 36 | "owner": "edolstra", 37 | "repo": "flake-compat", 38 | "type": "github" 39 | } 40 | }, 41 | "flake-parts": { 42 | "inputs": { 43 | "nixpkgs-lib": "nixpkgs-lib" 44 | }, 45 | "locked": { 46 | "lastModified": 1685662779, 47 | "narHash": "sha256-cKDDciXGpMEjP1n6HlzKinN0H+oLmNpgeCTzYnsA2po=", 48 | "owner": "hercules-ci", 49 | "repo": "flake-parts", 50 | "rev": "71fb97f0d875fd4de4994dfb849f2c75e17eb6c3", 51 | "type": "github" 52 | }, 53 | "original": { 54 | "id": "flake-parts", 55 | "type": "indirect" 56 | } 57 | }, 58 | "flake-utils": { 59 | "locked": { 60 | "lastModified": 1667395993, 61 | "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", 62 | "owner": "numtide", 63 | "repo": "flake-utils", 64 | "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", 65 | "type": "github" 66 | }, 67 | "original": { 68 | "owner": "numtide", 69 | "repo": "flake-utils", 70 | "type": "github" 71 | } 72 | }, 73 | "flake-utils_2": { 74 | "inputs": { 75 | "systems": "systems" 76 | }, 77 | "locked": { 78 | "lastModified": 1687171271, 79 | "narHash": "sha256-BJlq+ozK2B1sJDQXS3tzJM5a+oVZmi1q0FlBK/Xqv7M=", 80 | "owner": "numtide", 81 | "repo": "flake-utils", 82 | "rev": "abfb11bd1aec8ced1c9bb9adfe68018230f4fb3c", 83 | "type": "github" 84 | }, 85 | "original": { 86 | "owner": "numtide", 87 | "repo": "flake-utils", 88 | "type": "github" 89 | } 90 | }, 91 | "gitignore": { 92 | "inputs": { 93 | "nixpkgs": [ 94 | "devenv", 95 | "pre-commit-hooks", 96 | "nixpkgs" 97 | ] 98 | }, 99 | "locked": { 100 | "lastModified": 1660459072, 101 | "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", 102 | "owner": "hercules-ci", 103 | "repo": "gitignore.nix", 104 | "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", 105 | "type": "github" 106 | }, 107 | "original": { 108 | "owner": "hercules-ci", 109 | "repo": "gitignore.nix", 110 | "type": "github" 111 | } 112 | }, 113 | "lowdown-src": { 114 | "flake": false, 115 | "locked": { 116 | "lastModified": 1633514407, 117 | "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", 118 | "owner": "kristapsdz", 119 | "repo": "lowdown", 120 | "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", 121 | "type": "github" 122 | }, 123 | "original": { 124 | "owner": "kristapsdz", 125 | "repo": "lowdown", 126 | "type": "github" 127 | } 128 | }, 129 | "mk-shell-bin": { 130 | "locked": { 131 | "lastModified": 1677004959, 132 | "narHash": "sha256-/uEkr1UkJrh11vD02aqufCxtbF5YnhRTIKlx5kyvf+I=", 133 | "owner": "rrbutani", 134 | "repo": "nix-mk-shell-bin", 135 | "rev": "ff5d8bd4d68a347be5042e2f16caee391cd75887", 136 | "type": "github" 137 | }, 138 | "original": { 139 | "owner": "rrbutani", 140 | "repo": "nix-mk-shell-bin", 141 | "type": "github" 142 | } 143 | }, 144 | "nix": { 145 | "inputs": { 146 | "lowdown-src": "lowdown-src", 147 | "nixpkgs": [ 148 | "devenv", 149 | "nixpkgs" 150 | ], 151 | "nixpkgs-regression": "nixpkgs-regression" 152 | }, 153 | "locked": { 154 | "lastModified": 1676545802, 155 | "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", 156 | "owner": "domenkozar", 157 | "repo": "nix", 158 | "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", 159 | "type": "github" 160 | }, 161 | "original": { 162 | "owner": "domenkozar", 163 | "ref": "relaxed-flakes", 164 | "repo": "nix", 165 | "type": "github" 166 | } 167 | }, 168 | "nix2container": { 169 | "inputs": { 170 | "flake-utils": [ 171 | "flake-utils" 172 | ], 173 | "nixpkgs": [ 174 | "nixpkgs" 175 | ] 176 | }, 177 | "locked": { 178 | "lastModified": 1687467666, 179 | "narHash": "sha256-z9n7ATBXeDqz5a8+4HJ9fhU6KMyg7zZX0wrhLdVG7bQ=", 180 | "owner": "nlewo", 181 | "repo": "nix2container", 182 | "rev": "56e249151911e3d3928b578f5b6c01b16f55c308", 183 | "type": "github" 184 | }, 185 | "original": { 186 | "owner": "nlewo", 187 | "repo": "nix2container", 188 | "type": "github" 189 | } 190 | }, 191 | "nixpkgs": { 192 | "locked": { 193 | "lastModified": 1678875422, 194 | "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", 195 | "owner": "NixOS", 196 | "repo": "nixpkgs", 197 | "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", 198 | "type": "github" 199 | }, 200 | "original": { 201 | "owner": "NixOS", 202 | "ref": "nixpkgs-unstable", 203 | "repo": "nixpkgs", 204 | "type": "github" 205 | } 206 | }, 207 | "nixpkgs-lib": { 208 | "locked": { 209 | "dir": "lib", 210 | "lastModified": 1685564631, 211 | "narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=", 212 | "owner": "NixOS", 213 | "repo": "nixpkgs", 214 | "rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a", 215 | "type": "github" 216 | }, 217 | "original": { 218 | "dir": "lib", 219 | "owner": "NixOS", 220 | "ref": "nixos-unstable", 221 | "repo": "nixpkgs", 222 | "type": "github" 223 | } 224 | }, 225 | "nixpkgs-regression": { 226 | "locked": { 227 | "lastModified": 1643052045, 228 | "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", 229 | "owner": "NixOS", 230 | "repo": "nixpkgs", 231 | "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", 232 | "type": "github" 233 | }, 234 | "original": { 235 | "owner": "NixOS", 236 | "repo": "nixpkgs", 237 | "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", 238 | "type": "github" 239 | } 240 | }, 241 | "nixpkgs-stable": { 242 | "locked": { 243 | "lastModified": 1678872516, 244 | "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", 245 | "owner": "NixOS", 246 | "repo": "nixpkgs", 247 | "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", 248 | "type": "github" 249 | }, 250 | "original": { 251 | "owner": "NixOS", 252 | "ref": "nixos-22.11", 253 | "repo": "nixpkgs", 254 | "type": "github" 255 | } 256 | }, 257 | "nixpkgs_2": { 258 | "locked": { 259 | "lastModified": 1687412861, 260 | "narHash": "sha256-Z/g0wbL68C+mSGerYS2quv9FXQ1RRP082cAC0Bh4vcs=", 261 | "owner": "NixOS", 262 | "repo": "nixpkgs", 263 | "rev": "e603dc5f061ca1d8a19b3ede6a8cf9c9fcba6cdc", 264 | "type": "github" 265 | }, 266 | "original": { 267 | "owner": "NixOS", 268 | "ref": "nixos-unstable", 269 | "repo": "nixpkgs", 270 | "type": "github" 271 | } 272 | }, 273 | "poetry2nix": { 274 | "inputs": { 275 | "flake-utils": [ 276 | "flake-utils" 277 | ], 278 | "nixpkgs": [ 279 | "nixpkgs" 280 | ] 281 | }, 282 | "locked": { 283 | "lastModified": 1687314785, 284 | "narHash": "sha256-8LSbjAFFfh6X/DcZt9QJARqv+JRd/pHU4Kgkhrccazc=", 285 | "owner": "nix-community", 286 | "repo": "poetry2nix", 287 | "rev": "4f91d45e39cf64b642c6d2725c7bd50d6fcb544b", 288 | "type": "github" 289 | }, 290 | "original": { 291 | "owner": "nix-community", 292 | "repo": "poetry2nix", 293 | "type": "github" 294 | } 295 | }, 296 | "pre-commit-hooks": { 297 | "inputs": { 298 | "flake-compat": [ 299 | "devenv", 300 | "flake-compat" 301 | ], 302 | "flake-utils": "flake-utils", 303 | "gitignore": "gitignore", 304 | "nixpkgs": [ 305 | "devenv", 306 | "nixpkgs" 307 | ], 308 | "nixpkgs-stable": "nixpkgs-stable" 309 | }, 310 | "locked": { 311 | "lastModified": 1682596858, 312 | "narHash": "sha256-Hf9XVpqaGqe/4oDGr30W8HlsWvJXtMsEPHDqHZA6dDg=", 313 | "owner": "cachix", 314 | "repo": "pre-commit-hooks.nix", 315 | "rev": "fb58866e20af98779017134319b5663b8215d912", 316 | "type": "github" 317 | }, 318 | "original": { 319 | "owner": "cachix", 320 | "repo": "pre-commit-hooks.nix", 321 | "type": "github" 322 | } 323 | }, 324 | "root": { 325 | "inputs": { 326 | "devenv": "devenv", 327 | "flake-parts": "flake-parts", 328 | "flake-utils": "flake-utils_2", 329 | "mk-shell-bin": "mk-shell-bin", 330 | "nix2container": "nix2container", 331 | "nixpkgs": "nixpkgs_2", 332 | "poetry2nix": "poetry2nix" 333 | } 334 | }, 335 | "systems": { 336 | "locked": { 337 | "lastModified": 1681028828, 338 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 339 | "owner": "nix-systems", 340 | "repo": "default", 341 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 342 | "type": "github" 343 | }, 344 | "original": { 345 | "owner": "nix-systems", 346 | "repo": "default", 347 | "type": "github" 348 | } 349 | } 350 | }, 351 | "root": "root", 352 | "version": 7 353 | } 354 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "cffi" 5 | version = "1.15.1" 6 | description = "Foreign Function Interface for Python calling C code." 7 | optional = false 8 | python-versions = "*" 9 | files = [ 10 | {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, 11 | {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, 12 | {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, 13 | {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, 14 | {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, 15 | {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, 16 | {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, 17 | {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, 18 | {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, 19 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, 20 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, 21 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, 22 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, 23 | {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, 24 | {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, 25 | {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, 26 | {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, 27 | {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, 28 | {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, 29 | {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, 30 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, 31 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, 32 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, 33 | {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, 34 | {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, 35 | {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, 36 | {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, 37 | {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, 38 | {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, 39 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, 40 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, 41 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, 42 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, 43 | {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, 44 | {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, 45 | {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, 46 | {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, 47 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, 48 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, 49 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, 50 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, 51 | {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, 52 | {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, 53 | {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, 54 | {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, 55 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, 56 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, 57 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, 58 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, 59 | {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, 60 | {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, 61 | {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, 62 | {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, 63 | {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, 64 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, 65 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, 66 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, 67 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, 68 | {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, 69 | {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, 70 | {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, 71 | {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, 72 | {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, 73 | {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, 74 | ] 75 | 76 | [package.dependencies] 77 | pycparser = "*" 78 | 79 | [[package]] 80 | name = "cryptography" 81 | version = "43.0.1" 82 | description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." 83 | optional = false 84 | python-versions = ">=3.7" 85 | files = [ 86 | {file = "cryptography-43.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d"}, 87 | {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062"}, 88 | {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962"}, 89 | {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277"}, 90 | {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a"}, 91 | {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042"}, 92 | {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494"}, 93 | {file = "cryptography-43.0.1-cp37-abi3-win32.whl", hash = "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2"}, 94 | {file = "cryptography-43.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d"}, 95 | {file = "cryptography-43.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d"}, 96 | {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806"}, 97 | {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85"}, 98 | {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c"}, 99 | {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1"}, 100 | {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa"}, 101 | {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4"}, 102 | {file = "cryptography-43.0.1-cp39-abi3-win32.whl", hash = "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47"}, 103 | {file = "cryptography-43.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb"}, 104 | {file = "cryptography-43.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034"}, 105 | {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d"}, 106 | {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289"}, 107 | {file = "cryptography-43.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84"}, 108 | {file = "cryptography-43.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365"}, 109 | {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96"}, 110 | {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172"}, 111 | {file = "cryptography-43.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2"}, 112 | {file = "cryptography-43.0.1.tar.gz", hash = "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d"}, 113 | ] 114 | 115 | [package.dependencies] 116 | cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} 117 | 118 | [package.extras] 119 | docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] 120 | docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] 121 | nox = ["nox"] 122 | pep8test = ["check-sdist", "click", "mypy", "ruff"] 123 | sdist = ["build"] 124 | ssh = ["bcrypt (>=3.1.5)"] 125 | test = ["certifi", "cryptography-vectors (==43.0.1)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] 126 | test-randomorder = ["pytest-randomly"] 127 | 128 | [[package]] 129 | name = "importlib-metadata" 130 | version = "6.7.0" 131 | description = "Read metadata from Python packages" 132 | optional = false 133 | python-versions = ">=3.7" 134 | files = [ 135 | {file = "importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5"}, 136 | {file = "importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4"}, 137 | ] 138 | 139 | [package.dependencies] 140 | typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} 141 | zipp = ">=0.5" 142 | 143 | [package.extras] 144 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 145 | perf = ["ipython"] 146 | testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] 147 | 148 | [[package]] 149 | name = "importlib-resources" 150 | version = "5.12.0" 151 | description = "Read resources from Python packages" 152 | optional = false 153 | python-versions = ">=3.7" 154 | files = [ 155 | {file = "importlib_resources-5.12.0-py3-none-any.whl", hash = "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a"}, 156 | {file = "importlib_resources-5.12.0.tar.gz", hash = "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6"}, 157 | ] 158 | 159 | [package.dependencies] 160 | zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} 161 | 162 | [package.extras] 163 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 164 | testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] 165 | 166 | [[package]] 167 | name = "jaraco-classes" 168 | version = "3.2.3" 169 | description = "Utility functions for Python class constructs" 170 | optional = false 171 | python-versions = ">=3.7" 172 | files = [ 173 | {file = "jaraco.classes-3.2.3-py3-none-any.whl", hash = "sha256:2353de3288bc6b82120752201c6b1c1a14b058267fa424ed5ce5984e3b922158"}, 174 | {file = "jaraco.classes-3.2.3.tar.gz", hash = "sha256:89559fa5c1d3c34eff6f631ad80bb21f378dbcbb35dd161fd2c6b93f5be2f98a"}, 175 | ] 176 | 177 | [package.dependencies] 178 | more-itertools = "*" 179 | 180 | [package.extras] 181 | docs = ["jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] 182 | testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] 183 | 184 | [[package]] 185 | name = "jeepney" 186 | version = "0.8.0" 187 | description = "Low-level, pure Python DBus protocol wrapper." 188 | optional = false 189 | python-versions = ">=3.7" 190 | files = [ 191 | {file = "jeepney-0.8.0-py3-none-any.whl", hash = "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"}, 192 | {file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"}, 193 | ] 194 | 195 | [package.extras] 196 | test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] 197 | trio = ["async_generator", "trio"] 198 | 199 | [[package]] 200 | name = "keyring" 201 | version = "24.1.1" 202 | description = "Store and access your passwords safely." 203 | optional = false 204 | python-versions = ">=3.7" 205 | files = [ 206 | {file = "keyring-24.1.1-py3-none-any.whl", hash = "sha256:bc402c5e501053098bcbd149c4ddbf8e36c6809e572c2d098d4961e88d4c270d"}, 207 | {file = "keyring-24.1.1.tar.gz", hash = "sha256:3d44a48fa9a254f6c72879d7c88604831ebdaac6ecb0b214308b02953502c510"}, 208 | ] 209 | 210 | [package.dependencies] 211 | importlib-metadata = {version = ">=4.11.4", markers = "python_version < \"3.12\""} 212 | importlib-resources = {version = "*", markers = "python_version < \"3.9\""} 213 | "jaraco.classes" = "*" 214 | jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""} 215 | pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} 216 | SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} 217 | 218 | [package.extras] 219 | completion = ["shtab"] 220 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 221 | testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] 222 | 223 | [[package]] 224 | name = "more-itertools" 225 | version = "9.1.0" 226 | description = "More routines for operating on iterables, beyond itertools" 227 | optional = false 228 | python-versions = ">=3.7" 229 | files = [ 230 | {file = "more-itertools-9.1.0.tar.gz", hash = "sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d"}, 231 | {file = "more_itertools-9.1.0-py3-none-any.whl", hash = "sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3"}, 232 | ] 233 | 234 | [[package]] 235 | name = "pycparser" 236 | version = "2.21" 237 | description = "C parser in Python" 238 | optional = false 239 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 240 | files = [ 241 | {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, 242 | {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, 243 | ] 244 | 245 | [[package]] 246 | name = "pywin32-ctypes" 247 | version = "0.2.2" 248 | description = "A (partial) reimplementation of pywin32 using ctypes/cffi" 249 | optional = false 250 | python-versions = ">=3.6" 251 | files = [ 252 | {file = "pywin32-ctypes-0.2.2.tar.gz", hash = "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60"}, 253 | {file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"}, 254 | ] 255 | 256 | [[package]] 257 | name = "secretstorage" 258 | version = "3.3.3" 259 | description = "Python bindings to FreeDesktop.org Secret Service API" 260 | optional = false 261 | python-versions = ">=3.6" 262 | files = [ 263 | {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"}, 264 | {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"}, 265 | ] 266 | 267 | [package.dependencies] 268 | cryptography = ">=2.0" 269 | jeepney = ">=0.6" 270 | 271 | [[package]] 272 | name = "typing-extensions" 273 | version = "4.7.1" 274 | description = "Backported and Experimental Type Hints for Python 3.7+" 275 | optional = false 276 | python-versions = ">=3.7" 277 | files = [ 278 | {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, 279 | {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, 280 | ] 281 | 282 | [[package]] 283 | name = "zipp" 284 | version = "3.15.0" 285 | description = "Backport of pathlib-compatible object wrapper for zip files" 286 | optional = false 287 | python-versions = ">=3.7" 288 | files = [ 289 | {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, 290 | {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, 291 | ] 292 | 293 | [package.extras] 294 | docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 295 | testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] 296 | 297 | [metadata] 298 | lock-version = "2.0" 299 | python-versions = ">=3.7" 300 | content-hash = "c984fd132a3012afed1cfbd2b26dc8c1621a4707694418ce083ab185dd58c398" 301 | --------------------------------------------------------------------------------