From fd816f609acc244dab2d39828ce7df82421f22ef Mon Sep 17 00:00:00 2001 From: Devon Stewart Date: Mon, 11 Dec 2023 13:11:57 -0800 Subject: [PATCH 1/8] Actually import urllib.parse to be forward compatible --- src/replit/database/database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/replit/database/database.py b/src/replit/database/database.py index 2df75734..1eee5b3b 100644 --- a/src/replit/database/database.py +++ b/src/replit/database/database.py @@ -13,7 +13,7 @@ Tuple, Union, ) -import urllib +import urllib.parse import aiohttp from aiohttp_retry import ExponentialRetry, RetryClient # type: ignore From 2792c06ce1d799aa74625d911b692013eb1c04aa Mon Sep 17 00:00:00 2001 From: Devon Stewart Date: Mon, 11 Dec 2023 12:33:00 -0800 Subject: [PATCH 2/8] Close session after allocation --- tests/test_database.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_database.py b/tests/test_database.py index 2e8d5f95..9a8c738e 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -39,6 +39,7 @@ async def asyncTearDown(self) -> None: """Nuke whatever the test added.""" for k in await self.db.keys(): await self.db.delete(k) + await self.db.sess.close() async def test_get_set_delete(self) -> None: """Test that we can get, set, and delete a key.""" From e2b8ccf35a6a10f5a9905c53e38411cbf7f31291 Mon Sep 17 00:00:00 2001 From: Devon Stewart Date: Mon, 11 Dec 2023 14:02:15 -0800 Subject: [PATCH 3/8] Bumping semaphore runner version --- .semaphore/semaphore.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 6e824fe8..7539e1e1 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -3,7 +3,7 @@ name: replit-py agent: machine: type: e1-standard-2 - os_image: ubuntu1804 + os_image: ubuntu2004 blocks: - name: Lint and test run: From 758d012e59e5de1e96feda2344f618df8f1338ef Mon Sep 17 00:00:00 2001 From: Devon Stewart Date: Mon, 11 Dec 2023 14:04:32 -0800 Subject: [PATCH 4/8] Include pyproject.toml and tests in inputs to trigger CI --- .semaphore/semaphore.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 7539e1e1..b0901722 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -7,7 +7,7 @@ agent: blocks: - name: Lint and test run: - when: "change_in('/src')" + when: "change_in(['/src', '/pyproject.toml', '/tests'])" task: secrets: - name: replit-database From 9629339cc3e4afde8a9f7b9b75f13a6379ea9e4a Mon Sep 17 00:00:00 2001 From: Devon Stewart Date: Mon, 11 Dec 2023 14:24:51 -0800 Subject: [PATCH 5/8] Adding types-requests to placate mypy --- poetry.lock | 16 +++++++++++++++- pyproject.toml | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 9ec277bc..0095de50 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1844,6 +1844,20 @@ files = [ {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, ] +[[package]] +name = "types-requests" +version = "2.31.0.10" +description = "Typing stubs for requests" +optional = false +python-versions = ">=3.7" +files = [ + {file = "types-requests-2.31.0.10.tar.gz", hash = "sha256:dc5852a76f1eaf60eafa81a2e50aefa3d1f015c34cf0cba130930866b1b22a92"}, + {file = "types_requests-2.31.0.10-py3-none-any.whl", hash = "sha256:b32b9a86beffa876c0c3ac99a4cd3b8b51e973fb8e3bd4e0a6bb32c7efad80fc"}, +] + +[package.dependencies] +urllib3 = ">=2" + [[package]] name = "typing-extensions" version = "4.9.0" @@ -2009,4 +2023,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0" -content-hash = "2e8b5285c7a72eb12236ac7139486cb8653d7678f5e06c464e1c5fcbf5abb0f6" +content-hash = "0f5735e248b6911612b4e92420eee86f8a9eb60da3c0a62b9d5ea988b3c975d2" diff --git a/pyproject.toml b/pyproject.toml index 7cabf03a..25013f8b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ flake8-annotations = ">=2.3.0" flake8-docstrings = ">=1.5.0" mypy = ">=1.5.0" coverage = ">=5.2.1" +types-requests = "^2.31.0.10" [tool.poetry.group.docs.dependencies] Sphinx = ">=7.0.1" From 98d3926bd5dacdbe9207d051350b727c0ea69bd8 Mon Sep 17 00:00:00 2001 From: Devon Stewart Date: Mon, 11 Dec 2023 14:31:15 -0800 Subject: [PATCH 6/8] abc.MutableMapping requires keys to be a KeysView KeysView defers __iter__ to Database.__iter__, which is an `iter(self.prefix(""))`. --- src/replit/database/database.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/replit/database/database.py b/src/replit/database/database.py index 1eee5b3b..6599344f 100644 --- a/src/replit/database/database.py +++ b/src/replit/database/database.py @@ -3,7 +3,6 @@ from collections import abc import json from typing import ( - AbstractSet, Any, Callable, Dict, @@ -597,7 +596,7 @@ def prefix(self, prefix: str) -> Tuple[str, ...]: else: return tuple(urllib.parse.unquote(k) for k in r.text.split("\n")) - def keys(self) -> AbstractSet[str]: + def keys(self) -> abc.KeysView[str]: """Returns all of the keys in the database. Returns: @@ -611,7 +610,7 @@ def keys(self) -> AbstractSet[str]: # type db.keys() in an interactive prompt. # TODO: Return a set from prefix since keys are guaranteed unique - return set(self.prefix("")) + return abc.KeysView(self) def dumps(self, val: Any) -> str: """JSON encodes a value that can be a special DB object.""" From e0d8eae04463346a4da50fc542bd8f627575b982 Mon Sep 17 00:00:00 2001 From: Devon Stewart Date: Mon, 11 Dec 2023 14:38:33 -0800 Subject: [PATCH 7/8] Suppress the db_url from Database repr --- src/replit/database/database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/replit/database/database.py b/src/replit/database/database.py index 6599344f..f4e63399 100644 --- a/src/replit/database/database.py +++ b/src/replit/database/database.py @@ -622,7 +622,7 @@ def __repr__(self) -> str: Returns: A string representation of the database object. """ - return f"<{self.__class__.__name__}(db_url={self.db_url!r})>" + return f"<{self.__class__.__name__}(db_url=...)>" def close(self) -> None: """Closes the database client connection.""" From 4fa0fb79f7b26d0df9b1834498844a580309b350 Mon Sep 17 00:00:00 2001 From: Devon Stewart Date: Mon, 11 Dec 2023 14:43:36 -0800 Subject: [PATCH 8/8] Placate flake8 --- src/replit/__main__.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/replit/__main__.py b/src/replit/__main__.py index 66d38363..1aa17136 100644 --- a/src/replit/__main__.py +++ b/src/replit/__main__.py @@ -36,13 +36,19 @@ def cli() -> None: @click.argument("prefix") def find_matches(prefix: str) -> None: """List all keys that match the given prefix.""" + if database is None: + click.echo( + failure("Database connection not available. Ensure REPLIT_DB_URL is set!") + ) + return + matches = list(database.prefix(prefix)) if matches: - click.echo(success(f"Matches found for '{prefix}':\n")) + click.echo(success(f"Matches found for {prefix!r}:\n")) click.echo("\n".join(matches)) else: - click.echo(failure(f"No matches found for '{prefix}'")) + click.echo(failure(f"No matches found for {prefix!r}")) @cli.command(name="set") @@ -51,7 +57,7 @@ def find_matches(prefix: str) -> None: def set_value(key: str, val: str) -> None: """Add a given key-value pair to the DB.""" database[key] = val - click.echo(success(f"DB[{key}] was successfully set to '{val}'")) + click.echo(success(f"DB[{key!r}] was successfully set to {val!r}")) @cli.command(name="del") @@ -61,10 +67,10 @@ def del_value(key: str) -> None: try: del database[key] except KeyError: - click.echo(failure(f"The key '{key}' was not found in the DB.")) + click.echo(failure(f"The key {key!r} was not found in the DB.")) else: del database[key] - click.echo(success(f"db['{key}'] was successfully deleted.")) + click.echo(success(f"db[{key!r}] was successfully deleted.")) @cli.command(name="nuke") @@ -98,7 +104,7 @@ def list_all(file_path: str) -> None: json.dump(binds, f) - click.echo(success(f"Output successfully dumped to '{file_path}'")) + click.echo(success(f"Output successfully dumped to {file_path!r}")) if __name__ == "__main__":