From e203fe7c7c19f91a67c0782e46b46d9bb9b80ac8 Mon Sep 17 00:00:00 2001 From: Lingling <55448354+linglp@users.noreply.github.com> Date: Mon, 28 Sep 2026 17:39:05 -0400 Subject: [PATCH 01/15] comment out test (#1460) --- .../models/async/test_agent_async.py | 184 +++++++++--------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/tests/integration/synapseclient/models/async/test_agent_async.py b/tests/integration/synapseclient/models/async/test_agent_async.py index 355087d2b..6d2e0872b 100644 --- a/tests/integration/synapseclient/models/async/test_agent_async.py +++ b/tests/integration/synapseclient/models/async/test_agent_async.py @@ -49,29 +49,29 @@ def init(self, syn: Synapse) -> None: else: self.AGENT_REGISTRATION_ID = "29" - async def test_send_job_and_wait_async_with_post_exchange_args(self) -> None: - # GIVEN an AgentPrompt with a valid concrete type, prompt, and enable_trace - test_prompt = AgentPrompt( - concrete_type=AGENT_CHAT_REQUEST, - prompt="hello", - enable_trace=True, - ) - # AND the ID of an existing agent session - test_session = await AgentSession( - agent_registration_id=self.AGENT_REGISTRATION_ID - ).start_async(synapse_client=self.syn) - test_prompt.session_id = test_session.id - # WHEN I send the job and wait for it to complete - await within_deadline( - test_prompt.send_job_and_wait_async( - post_exchange_args={"newer_than": 0}, - timeout=AGENT_PROMPT_TIMEOUT_SEC, - synapse_client=self.syn, - ) - ) - # THEN I expect the AgentPrompt to be updated with the response and trace - assert test_prompt.response is not None - assert test_prompt.trace is not None + # async def test_send_job_and_wait_async_with_post_exchange_args(self) -> None: + # # GIVEN an AgentPrompt with a valid concrete type, prompt, and enable_trace + # test_prompt = AgentPrompt( + # concrete_type=AGENT_CHAT_REQUEST, + # prompt="hello", + # enable_trace=True, + # ) + # # AND the ID of an existing agent session + # test_session = await AgentSession( + # agent_registration_id=self.AGENT_REGISTRATION_ID + # ).start_async(synapse_client=self.syn) + # test_prompt.session_id = test_session.id + # # WHEN I send the job and wait for it to complete + # await within_deadline( + # test_prompt.send_job_and_wait_async( + # post_exchange_args={"newer_than": 0}, + # timeout=AGENT_PROMPT_TIMEOUT_SEC, + # synapse_client=self.syn, + # ) + # ) + # # THEN I expect the AgentPrompt to be updated with the response and trace + # assert test_prompt.response is not None + # assert test_prompt.trace is not None class TestAgentSession: @@ -137,25 +137,25 @@ async def test_update(self) -> None: == AgentSessionAccessLevel.READ_YOUR_PRIVATE_DATA ) - async def test_prompt(self) -> None: - # GIVEN an agent session with a valid agent registration id - agent_session = AgentSession(agent_registration_id=self.AGENT_REGISTRATION_ID) - # WHEN I start a session - await agent_session.start_async(synapse_client=self.syn) - # THEN I expect to be able to prompt the agent - await within_deadline( - agent_session.prompt_async( - prompt="hello", - enable_trace=True, - timeout=AGENT_PROMPT_TIMEOUT_SEC, - synapse_client=self.syn, - ) - ) - # AND I expect the chat history to be updated with the prompt and response - assert len(agent_session.chat_history) == 1 - assert agent_session.chat_history[0].prompt == "hello" - assert agent_session.chat_history[0].response is not None - assert agent_session.chat_history[0].trace is not None + # async def test_prompt(self) -> None: + # # GIVEN an agent session with a valid agent registration id + # agent_session = AgentSession(agent_registration_id=self.AGENT_REGISTRATION_ID) + # # WHEN I start a session + # await agent_session.start_async(synapse_client=self.syn) + # # THEN I expect to be able to prompt the agent + # await within_deadline( + # agent_session.prompt_async( + # prompt="hello", + # enable_trace=True, + # timeout=AGENT_PROMPT_TIMEOUT_SEC, + # synapse_client=self.syn, + # ) + # ) + # # AND I expect the chat history to be updated with the prompt and response + # assert len(agent_session.chat_history) == 1 + # assert agent_session.chat_history[0].prompt == "hello" + # assert agent_session.chat_history[0].response is not None + # assert agent_session.chat_history[0].trace is not None class TestAgent: @@ -229,53 +229,53 @@ async def test_get_session(self) -> None: # AND I expect those sessions to be the same assert existing_session == agent.current_session - async def test_prompt_with_session(self) -> None: - # GIVEN an Agent with a valid agent registration id - agent = await Agent(registration_id=self.AGENT_REGISTRATION_ID).get_async( - synapse_client=self.syn - ) - # AND a session started separately - session = await AgentSession( - agent_registration_id=self.AGENT_REGISTRATION_ID - ).start_async(synapse_client=self.syn) - # WHEN I prompt the agent with a session - await within_deadline( - agent.prompt_async( - prompt="hello", - enable_trace=True, - session=session, - timeout=AGENT_PROMPT_TIMEOUT_SEC, - synapse_client=self.syn, - ) - ) - test_session = agent.sessions[session.id] - # THEN I expect the chat history to be updated with the prompt and response - assert len(test_session.chat_history) == 1 - assert test_session.chat_history[0].prompt == "hello" - assert test_session.chat_history[0].response is not None - assert test_session.chat_history[0].trace is not None - # AND I expect the current session to be the session provided - assert agent.current_session.id == session.id - - async def test_prompt_no_session(self) -> None: - # GIVEN an Agent with a valid agent registration id - agent = await Agent(registration_id=self.AGENT_REGISTRATION_ID).get_async( - synapse_client=self.syn - ) - # WHEN I prompt the agent without a current session set - # and no session provided - await within_deadline( - agent.prompt_async( - prompt="hello", - enable_trace=True, - timeout=AGENT_PROMPT_TIMEOUT_SEC, - synapse_client=self.syn, - ) - ) - # THEN I expect a new session to be started and set as the current session - assert agent.current_session is not None - # AND I expect the chat history to be updated with the prompt and response - assert len(agent.current_session.chat_history) == 1 - assert agent.current_session.chat_history[0].prompt == "hello" - assert agent.current_session.chat_history[0].response is not None - assert agent.current_session.chat_history[0].trace is not None + # async def test_prompt_with_session(self) -> None: + # # GIVEN an Agent with a valid agent registration id + # agent = await Agent(registration_id=self.AGENT_REGISTRATION_ID).get_async( + # synapse_client=self.syn + # ) + # # AND a session started separately + # session = await AgentSession( + # agent_registration_id=self.AGENT_REGISTRATION_ID + # ).start_async(synapse_client=self.syn) + # # WHEN I prompt the agent with a session + # await within_deadline( + # agent.prompt_async( + # prompt="hello", + # enable_trace=True, + # session=session, + # timeout=AGENT_PROMPT_TIMEOUT_SEC, + # synapse_client=self.syn, + # ) + # ) + # test_session = agent.sessions[session.id] + # # THEN I expect the chat history to be updated with the prompt and response + # assert len(test_session.chat_history) == 1 + # assert test_session.chat_history[0].prompt == "hello" + # assert test_session.chat_history[0].response is not None + # assert test_session.chat_history[0].trace is not None + # # AND I expect the current session to be the session provided + # assert agent.current_session.id == session.id + + # async def test_prompt_no_session(self) -> None: + # # GIVEN an Agent with a valid agent registration id + # agent = await Agent(registration_id=self.AGENT_REGISTRATION_ID).get_async( + # synapse_client=self.syn + # ) + # # WHEN I prompt the agent without a current session set + # # and no session provided + # await within_deadline( + # agent.prompt_async( + # prompt="hello", + # enable_trace=True, + # timeout=AGENT_PROMPT_TIMEOUT_SEC, + # synapse_client=self.syn, + # ) + # ) + # # THEN I expect a new session to be started and set as the current session + # assert agent.current_session is not None + # # AND I expect the chat history to be updated with the prompt and response + # assert len(agent.current_session.chat_history) == 1 + # assert agent.current_session.chat_history[0].prompt == "hello" + # assert agent.current_session.chat_history[0].response is not None + # assert agent.current_session.chat_history[0].trace is not None From 9d06b67801d051305f8914adf9ccda773fc8a99b Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Thu, 1 Oct 2026 09:26:02 -0700 Subject: [PATCH 02/15] V4.14.0 into develop (#1462) * update version v4.14.0 Co-Authored-By: Claude Opus 5.5 * update release notes v4.14.0 Co-Authored-By: Claude Opus 5.5 * [SYNPY- 1922] Fix Wki.copy issue (#1459) * renamed method and redid docstring to be more descriptive * fix issue when copying wikis with empty markdowns * added bug fix to nws.md --------- Co-authored-by: Claude Opus 5.5 --- docs/news.md | 74 +++++++++++++++++++ synapseclient/models/wiki.py | 33 ++++++--- synapseclient/synapsePythonClient | 2 +- .../models/async/unit_test_wiki_async.py | 62 +++++++++++++--- 4 files changed, 148 insertions(+), 23 deletions(-) diff --git a/docs/news.md b/docs/news.md index f5c13a536..79f3efe4d 100644 --- a/docs/news.md +++ b/docs/news.md @@ -9,6 +9,80 @@ detailing some of the changes. the 4.x.x versions hidden behind optional feature flags or different import paths. Any breaking changes will not be included until v5.0. +## 4.14.0 + +## Highlights + +- New `SearchIndex` entity and search-management APIs let you build and query full-text search indexes on Synapse data. A new tutorial shows how to use them. +- Curation tasks can now run compute tasks. +- Curator improvements: a high-level function to create grids, per-row validation in grid sessions, grid session synchronization, custom column order, and shared grid authorization. +- New `WikiPage.copy()` method replaces the legacy `synapseutils.copyWiki()`. +- Many legacy classes and functions now show deprecation warnings with migration guidance, to prepare for v5.0.0. +- Uploads and downloads are more reliable: better retries, reuse of pre-signed URLs, and file name casing is kept on Windows. +- Fixes for table upserts with multiple primary keys and with column names that contain spaces or special characters. + +## Features + +- [SYNPY-1869] Added the SearchIndex entity and search-management APIs; renamed SchemaOrganization to Organization (the old name is kept as a deprecated alias) by @BryanFauble in #1422 +- [SYNPY-1896] Added SearchIndex to the operations layer (store/get/delete) by @BryanFauble in #1445 +- [SYNPY-1895] Added support for compute tasks on curation tasks by @andrewelamb in #1438 +- [SYNPY-1851] Added a high-level function to create grids by @andrewelamb in #1423 +- [SYNPY-1880] Added per-row validation to the Grid data class, with documentation for in-session validation by @linglp in #1428, #1437 and @thomasyu888 in #1430 +- [SYNPY-1894] Added synchronization of an active grid session by @linglp in #1440 +- [SYNPY-1840] Added the ability to set column order when you create file-based and record-based tasks by @andrewelamb in #1443 +- [SYNPY-1849] Added the ability to set the grid authorization mode on a CurationTask by @andrewelamb in #1392 +- [SYNPY-1864] Added the return_entities parameter to create_file_based_metadata_task by @andrewelamb in #1411 +- [SYNPY-1857] Upsert keys are now the first columns when Curator creates RecordSets by @andrewelamb in #1409 +- [SYNPY-1859] The name column is now first when Curator creates entity views by @andrewelamb in #1410 +- [SYNPY-1875] Added WikiPage.copy() and deprecated synapseutils.copyWiki() by @andrewelamb in #1434 +- [SYNPY-1486] All progress bars now go through a factory that obeys silent mode by @BryanFauble in #1426 +- [SYNPY-1861] submission_instructions_message and submission_receipt_message are now optional on Evaluation by @jaymedina in #1401 +- [SYNPY-1883] Date values are now converted to epoch milliseconds during data upload by @danlu1 in #1429 +- Multi-threaded downloads now reuse the pre-signed URL by @BryanFauble in #1407 +- Added Team.delete_invitation(), Team docstring examples, and a complete mkdocs reference for Team by @linglp in #1457 + +## Bug Fixes + +- [SYNPY-1918] Fixed bugs in the conversion of CSV data models to JSON Schema by @andrewelamb in #1451 +- [SYNPY-1912] Fixed upsert_rows reporting Table update responses incorrectly by @andrewelamb in #1446 +- [SYNPY-1885] Fixed an IndexError in upsert_rows with multiple primary keys by @andrewelamb in #1421 +- Fixed upserts when a Synapse column name contains spaces or special characters by @andrewelamb in #1454 +- [SYNPY-1908] Multipart upload part retries now catch connection exceptions by @BryanFauble in #1436 +- [SYNSD-2567] Fixed an httpx.ResponseNotRead crash in the download chunk retry path by @BryanFauble in #1413 +- [SYNPY-1882] File name casing is now kept during upload and download by @danlu1 in #1431 +- [SYNPY-1708] None values no longer become string annotations by @andrewelamb in #1417 +- [SYNPY-1844] Merging dataclasses with nested dataclasses is now recursive, so changes to nested fields are no longer lost by @andrewelamb in #1412 +- [SYNPY-1863] SubmissionStatus now deep-copies annotations, so it can detect changes to submission_annotations by @jaymedina in #1414 +- [SYNPY-1922] WikiPage.copy() no longer fails when a wiki page has empty markdown by @andrewelamb +- Added the missing EXECUTING and IN_REVIEW values to the TaskState enum by @andrewelamb in #1432 +- Fixed the incorrect type hints on create_file_based_metadata_task by @andrewelamb in #1415 + +## Tech Debt + +- [SYNPY-1745] Added deprecation warnings and migration guidance to legacy classes and methods, to prepare for v5.0.0 by @andrewelamb in #1418 +- [SYNPY-1872] Deprecated the synapseutils migrate functions by @andrewelamb in #1427 +- [SYNPY-1871] Moved functions from annotations.py to the modules that use them by @andrewelamb in #1424 +- [SYNPY-1870] Rewrote test_caching.py so that it does not use deprecated legacy code by @andrewelamb in #1425 +- [SYNPY-1906] Fixed security vulnerabilities in dependencies and updated pytest-xdist for pytest 9.0.3 by @linglp in #1441, #1442 +- Updated cryptography to 49.0.0 by @andrewelamb in #1416 +- [SYNPY-1829, SYNPY-1856, SYNPY-1858] Re-enabled a skipped test and fixed flaky integration tests by @linglp in #1393 +- [SYNPY-1905] Fixed an intermittent integration test failure by @andrewelamb in #1448 +- [SYNPY-1892] Reduced the number of parallel integration tests on the Synapse dev stack by @BryanFauble in #1450 +- Changed a unit test to write to a temp path, not to the local directory, by @andrewelamb in #1449 +- Added compliance-config.json by @allaway in #1405 + +## Documentation + +- [SYNPY-1893] Added a SearchIndex tutorial by @thomasyu888 in #1447 +- Added an architecture diagram to the README by @allaway in #1404 +- Made the README easier to read (WCAG 3.1.5 target) by @allaway in #1406 +- Updated the documentation after PLFM-9831 by @linglp in #1452 +- Updated the pip install instructions by @andrewelamb in #1453 +- Made it clear that get_invalid_validation only returns results from direct children by @andrewelamb in #1455 +- Fixed broken code fences in the wiki docstring examples by @BryanFauble in #1456 + +Full Changelog: https://github.com/Sage-Bionetworks/synapsePythonClient/compare/v4.13.0...v4.14.0 + ## 4.13.0 ## Highlights diff --git a/synapseclient/models/wiki.py b/synapseclient/models/wiki.py index 19742fb10..729d445af 100644 --- a/synapseclient/models/wiki.py +++ b/synapseclient/models/wiki.py @@ -723,16 +723,27 @@ def _should_gzip_file(file_path: str) -> bool: ) @otel_trace_method( - method_to_trace_name=lambda self, **kwargs: f"Get the markdown file handle: {self.owner_id}" + method_to_trace_name=lambda self, **kwargs: f"Upload the markdown file handle: {self.owner_id}" ) - async def _get_markdown_file_handle(self, synapse_client: Synapse) -> "WikiPage": - """Get the markdown file handle from the synapse client. + async def _upload_markdown_file_handle(self, synapse_client: Synapse) -> "WikiPage": + """Upload the markdown of this wiki page to Synapse as a gzipped file and set + markdown_file_handle_id to the ID of the new file handle. + + If markdown is None, no upload occurs and this object is not changed. + If markdown is an empty string, an empty gzipped file is uploaded, + because Synapse requires a markdown file handle for each wiki page. + + The local gzipped file is deleted after the upload, also if the upload + fails. If markdown is a path to a .gz file, that file is deleted. + Arguments: - synapse_client: The Synapse client to use for cache access. + synapse_client: The Synapse client to use for the cache directory, + the upload, and logging. + Returns: - A WikiPage with the updated markdown file handle id. + This WikiPage object, with markdown_file_handle_id set. """ - if not self.markdown: + if self.markdown is None: return self else: file_path = self._to_gzip_file( @@ -892,7 +903,7 @@ async def store_async( # get the markdown file handle and attachment file handles if the wiki action is valid if wiki_action: # Update self with the returned WikiPage objects that have file handle IDs set - self = await self._get_markdown_file_handle(synapse_client=client) + self = await self._upload_markdown_file_handle(synapse_client=client) self = await self._get_attachment_file_handles(synapse_client=client) if wiki_action == "create_root_wiki_page": @@ -1707,7 +1718,7 @@ async def copy_async( ) for new_wiki_id in wiki_id_map.values(): new_wiki = new_wikis[new_wiki_id] - new_wiki = await new_wiki._get_markdown_file_handle( + new_wiki = await new_wiki._upload_markdown_file_handle( synapse_client=client ) wiki_data = await put_wiki_page( @@ -1789,7 +1800,7 @@ async def _copy_wiki_pages( parent_id=wiki_id_map[wiki_header["parentId"]], attachment_file_handle_ids=new_file_handle_ids, ) - new_wiki = await new_wiki._get_markdown_file_handle( + new_wiki = await new_wiki._upload_markdown_file_handle( synapse_client=synapse_client ) wiki_data = await post_wiki_page( @@ -1805,7 +1816,7 @@ async def _copy_wiki_pages( destination_wiki_page.markdown = markdown destination_wiki_page.attachment_file_handle_ids = new_file_handle_ids destination_wiki_page = ( - await destination_wiki_page._get_markdown_file_handle( + await destination_wiki_page._upload_markdown_file_handle( synapse_client=synapse_client ) ) @@ -1824,7 +1835,7 @@ async def _copy_wiki_pages( parent_id=destination_sub_page_id, attachment_file_handle_ids=new_file_handle_ids, ) - new_wiki = await new_wiki._get_markdown_file_handle( + new_wiki = await new_wiki._upload_markdown_file_handle( synapse_client=synapse_client ) wiki_data = await post_wiki_page( diff --git a/synapseclient/synapsePythonClient b/synapseclient/synapsePythonClient index 3209defcf..d914c4735 100644 --- a/synapseclient/synapsePythonClient +++ b/synapseclient/synapsePythonClient @@ -1,6 +1,6 @@ { "client": "synapsePythonClient", - "latestVersion": "4.13.0", + "latestVersion": "4.14.0", "blacklist": [ "0.0.0", "0.4.1", diff --git a/tests/unit/synapseclient/models/async/unit_test_wiki_async.py b/tests/unit/synapseclient/models/async/unit_test_wiki_async.py index a844dffee..d3f09cc88 100644 --- a/tests/unit/synapseclient/models/async/unit_test_wiki_async.py +++ b/tests/unit/synapseclient/models/async/unit_test_wiki_async.py @@ -678,7 +678,7 @@ def test_should_gzip_file_with_invalid_content(self) -> None: with pytest.raises(AttributeError): WikiPage._should_gzip_file(123) - async def test_get_markdown_file_handle_success_with_markdown(self) -> WikiPage: + async def test_upload_markdown_file_handle_success_with_markdown(self) -> WikiPage: with ( patch( "synapseclient.models.wiki.WikiPage._to_gzip_file", @@ -693,8 +693,8 @@ async def test_get_markdown_file_handle_success_with_markdown(self) -> WikiPage: patch("os.path.exists", return_value=True), patch("os.remove") as mock_remove, ): - # WHEN I call `_get_markdown_file_handle` - results = await self.wiki_page._get_markdown_file_handle( + # WHEN I call `_upload_markdown_file_handle` + results = await self.wiki_page._upload_markdown_file_handle( synapse_client=self.syn ) @@ -721,7 +721,7 @@ async def test_get_markdown_file_handle_success_with_markdown(self) -> WikiPage: expected_results.markdown_file_handle_id = "handle1" assert results == expected_results - async def test_get_markdown_file_handle_no_markdown(self) -> WikiPage: + async def test_upload_markdown_file_handle_no_markdown(self) -> WikiPage: # GIVEN a WikiPage with no markdown wiki_page = WikiPage( id="wiki1", @@ -729,13 +729,53 @@ async def test_get_markdown_file_handle_no_markdown(self) -> WikiPage: attachments=["test_1.txt", "test_2.txt"], ) with patch.object(self.syn.logger, "info") as mock_logger: - # WHEN I call `_get_markdown_file_handle` - results = await wiki_page._get_markdown_file_handle(synapse_client=self.syn) + # WHEN I call `_upload_markdown_file_handle` + results = await wiki_page._upload_markdown_file_handle( + synapse_client=self.syn + ) # THEN the result should be the same WikiPage assert mock_logger.call_count == 0 assert results == wiki_page + async def test_upload_markdown_file_handle_empty_markdown(self) -> WikiPage: + # GIVEN a WikiPage with empty markdown + wiki_page = WikiPage( + owner_id="syn123", + id="wiki1", + title="Test Wiki Page", + markdown="", + ) + with ( + patch( + "synapseclient.models.wiki.WikiPage._to_gzip_file", + return_value=("test.txt.gz"), + ) as mock_to_gzip_file, + patch( + "synapseclient.models.wiki.upload_file_handle", + return_value={"id": "handle1"}, + ) as mock_upload, + patch("os.path.exists", return_value=True), + patch("os.remove"), + ): + # WHEN I call `_upload_markdown_file_handle` + results = await wiki_page._upload_markdown_file_handle( + synapse_client=self.syn + ) + + # THEN the empty markdown should be gzipped and uploaded, because + # Synapse requires a markdown file handle for every wiki page + mock_to_gzip_file.assert_called_once_with( + wiki_content="", synapse_client=self.syn + ) + mock_upload.assert_called_once_with( + syn=self.syn, + parent_entity_id="syn123", + path="test.txt.gz", + ) + # AND the markdown file handle ID should be set + assert results.markdown_file_handle_id == "handle1" + async def test_get_attachment_file_handles_success_multiple_attachments( self, ) -> WikiPage: @@ -1113,7 +1153,7 @@ async def test_store_async_new_root_wiki_success(self) -> None: return_value="create_root_wiki_page", ), patch( - "synapseclient.models.wiki.WikiPage._get_markdown_file_handle", + "synapseclient.models.wiki.WikiPage._upload_markdown_file_handle", return_value=mock_wiki_with_markdown, ), patch( @@ -1205,7 +1245,7 @@ async def test_store_async_update_existing_wiki_success(self) -> None: return_value="update_existing_wiki_page", ), patch( - "synapseclient.models.wiki.WikiPage._get_markdown_file_handle", + "synapseclient.models.wiki.WikiPage._upload_markdown_file_handle", return_value=mock_wiki_with_markdown, ), patch( @@ -1293,7 +1333,7 @@ async def test_store_async_create_sub_wiki_success(self) -> None: return_value="create_sub_wiki_page", ), patch( - "synapseclient.models.wiki.WikiPage._get_markdown_file_handle", + "synapseclient.models.wiki.WikiPage._upload_markdown_file_handle", return_value=mock_wiki_with_markdown, ), patch( @@ -2580,7 +2620,7 @@ async def generator(): ) as mock_entity_ids, patch.object( WikiPage, - "_get_markdown_file_handle", + "_upload_markdown_file_handle", autospec=True, side_effect=lambda self, *args, **kwargs: self, ), @@ -3364,7 +3404,7 @@ def fake_put(**kwargs): ), patch.object( WikiPage, - "_get_markdown_file_handle", + "_upload_markdown_file_handle", autospec=True, side_effect=fake_get_fh, ), From 195dc9134450d574d5fe6c948746597c794f2cc1 Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Thu, 1 Oct 2026 13:13:23 -0700 Subject: [PATCH 03/15] remove support for python 3.10 (#1464) --- .github/workflows/build.yml | 20 +++++----- CLAUDE.md | 6 +-- CONTRIBUTING.md | 10 ++--- README.md | 4 +- docs/tutorials/reticulate.md | 2 +- pylintrc | 2 +- pyproject.toml | 2 +- setup.cfg | 3 +- synapseclient/models/dataset.py | 4 +- synapseclient/models/entityview.py | 4 +- synapseclient/models/materializedview.py | 4 +- .../models/mixins/asynchronous_job.py | 3 +- .../models/mixins/storable_container.py | 3 +- .../models/mixins/table_components.py | 3 +- .../models/protocols/search_index_protocol.py | 4 +- .../protocols/search_management_protocol.py | 4 +- .../protocols/storable_container_protocol.py | 4 +- .../models/protocols/table_protocol.py | 4 +- synapseclient/models/search_index.py | 4 +- synapseclient/models/search_management.py | 14 +++++-- synapseclient/models/submission.py | 4 +- synapseclient/models/submission_status.py | 4 +- synapseclient/models/submissionview.py | 4 +- synapseclient/models/table.py | 4 +- synapseclient/models/table_components.py | 4 +- synapseclient/models/virtualtable.py | 4 +- .../unit_test_synapseutils_describe.py | 39 ++++++------------- 27 files changed, 64 insertions(+), 103 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d5fafbbb0..381ce013d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,7 +55,7 @@ jobs: # if changing the below change the run-integration-tests versions and the check-deploy versions # Make sure that we are running the integration tests on the first and last versions of the matrix - python: ['3.10', '3.11', '3.12', '3.13', '3.14'] + python: ['3.11', '3.12', '3.13', '3.14'] runs-on: ${{ matrix.os }} @@ -84,7 +84,7 @@ jobs: path: | ${{ steps.get-dependencies.outputs.site_packages_loc }} ${{ steps.get-dependencies.outputs.site_bin_dir }} - key: ${{ runner.os }}-${{ matrix.python }}-build-${{ env.cache-name }}-${{ hashFiles('setup.py', 'setup.cfg') }}-v33 + key: ${{ runner.os }}-${{ matrix.python }}-build-${{ env.cache-name }}-${{ hashFiles('setup.py', 'setup.cfg') }}-v34 - name: Install py-dependencies if: steps.cache-dependencies.outputs.cache-hit != 'true' @@ -109,7 +109,7 @@ jobs: pytest -sv --cov-append --cov=. --cov-report xml tests/unit - name: Check for Secret availability id: secret-check - if: ${{ contains(fromJSON('["3.10"]'), matrix.python) || contains(fromJSON('["3.14"]'), matrix.python) }} + if: ${{ contains(fromJSON('["3.11"]'), matrix.python) || contains(fromJSON('["3.14"]'), matrix.python) }} # perform secret check & put boolean result as an output shell: bash run: | @@ -126,7 +126,7 @@ jobs: fi - name: Download Failed Tests from Previous Attempt - if: ${{ github.run_attempt > 1 && (contains(fromJSON('["3.10"]'), matrix.python) || contains(fromJSON('["3.14"]'), matrix.python)) && steps.secret-check.outputs.secrets_available == 'true'}} + if: ${{ github.run_attempt > 1 && (contains(fromJSON('["3.11"]'), matrix.python) || contains(fromJSON('["3.14"]'), matrix.python)) && steps.secret-check.outputs.secrets_available == 'true'}} uses: actions/download-artifact@v4 with: name: failed-tests-${{ matrix.os }}-${{ matrix.python }} @@ -142,23 +142,23 @@ jobs: shell: bash # keep versions consistent with the first and last from the strategy matrix - if: ${{ (contains(fromJSON('["3.10"]'), matrix.python) || contains(fromJSON('["3.14"]'), matrix.python)) && steps.secret-check.outputs.secrets_available == 'true' && github.event_name != 'release'}} + if: ${{ (contains(fromJSON('["3.11"]'), matrix.python) || contains(fromJSON('["3.14"]'), matrix.python)) && steps.secret-check.outputs.secrets_available == 'true' && github.event_name != 'release'}} run: | # Set SYNAPSE_PROFILE based on OS and Python version if [ "${{ startsWith(matrix.os, 'ubuntu') }}" == "true" ]; then - if [ "${{ matrix.python }}" == "3.10" ]; then + if [ "${{ matrix.python }}" == "3.11" ]; then export SYNAPSE_PROFILE="TestUbuntuMinimumPython" elif [ "${{ matrix.python }}" == "3.14" ]; then export SYNAPSE_PROFILE="TestUbuntuMaximumPython" fi elif [ "${{ startsWith(matrix.os, 'windows') }}" == "true" ]; then - if [ "${{ matrix.python }}" == "3.10" ]; then + if [ "${{ matrix.python }}" == "3.11" ]; then export SYNAPSE_PROFILE="TestWindowsMinimumPython" elif [ "${{ matrix.python }}" == "3.14" ]; then export SYNAPSE_PROFILE="TestWindowsMaximumPython" fi elif [ "${{ startsWith(matrix.os, 'macos') }}" == "true" ]; then - if [ "${{ matrix.python }}" == "3.10" ]; then + if [ "${{ matrix.python }}" == "3.11" ]; then export SYNAPSE_PROFILE="TestMacosMinimumPython" elif [ "${{ matrix.python }}" == "3.14" ]; then export SYNAPSE_PROFILE="TestMacosMaximumPython" @@ -365,7 +365,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.11' - name: set-release-env shell: bash @@ -502,7 +502,7 @@ jobs: os: [ubuntu-24.04, macos-15-intel, windows-2022] # python versions should be consistent with the strategy matrix and the runs-integration-tests versions - python: ['3.10', '3.11', '3.12', '3.13', '3.14'] + python: ['3.11', '3.12', '3.13', '3.14'] runs-on: ${{ matrix.os }} diff --git a/CLAUDE.md b/CLAUDE.md index 514776837..3155b0df9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,4 @@ - + ## Project @@ -6,7 +6,7 @@ Synapse Python Client — official Python SDK and CLI for Synapse (synapse.org), ## Stack -- Python 3.10–3.14 (`setup.cfg`: `python_requires = >=3.10, <3.15`) +- Python 3.11–3.14 (`setup.cfg`: `python_requires = >=3.11, <3.15`) - HTTP: httpx (async), requests (sync/legacy) - Models: stdlib dataclasses (NOT Pydantic) - Tests: pytest 9.0.3, pytest-asyncio, pytest-socket, pytest-xdist @@ -125,7 +125,7 @@ For type annotations referencing pandas types, use `DATA_FRAME_TYPE` and `SERIES - Integration tests use `--reruns 3` for flaky retries and `-n 4 --dist loadscope` for parallelism - Integration fixtures create per-worker Synapse projects; use `schedule_for_cleanup()` for teardown - Auth env vars: `SYNAPSE_AUTH_TOKEN` (bearer token), `SYNAPSE_PROFILE` (config file profile, default: `"default"`), `SYNAPSE_TOKEN_AWS_SSM_PARAMETER_NAME` (AWS SSM path) -- CI runs integration tests only on Python 3.10 and 3.14 (oldest + newest) to limit Synapse server load +- CI runs integration tests only on Python 3.11 and 3.14 (oldest + newest) to limit Synapse server load ## Maintenance diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6f09a69e7..06ecb2736 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -93,7 +93,7 @@ copied to forks). #### Installing the Python Client in a virtual environment with pipenv Perform the following one-time steps to set up your local environment. -1. This package uses Python, if you have not already, please install [pyenv](https://github.com/pyenv/pyenv#installation) to manage your Python versions. Versions supported by this package are all versions >=3.10 and <=3.14. If you do not install `pyenv` make sure that Python and `pip` are installed correctly and have been added to your PATH by running `python3 --version` and `pip3 --version`. If your installation was successful, your terminal will return the versions of Python and `pip` that you installed. **Note**: If you have `pyenv` it will install a specific version of Python for you. +1. This package uses Python, if you have not already, please install [pyenv](https://github.com/pyenv/pyenv#installation) to manage your Python versions. Versions supported by this package are all versions >=3.11 and <=3.14. If you do not install `pyenv` make sure that Python and `pip` are installed correctly and have been added to your PATH by running `python3 --version` and `pip3 --version`. If your installation was successful, your terminal will return the versions of Python and `pip` that you installed. **Note**: If you have `pyenv` it will install a specific version of Python for you. 2. Install `pipenv` by running `pip install pipenv`. - If you already have `pipenv` installed, ensure that the version is >=2023.9.8 to avoid compatibility issues. @@ -276,7 +276,7 @@ When adding support for a new Python version (e.g., adding Python 3.15), update **Code configuration files:** 1. **`setup.cfg`**: - Add the new version to the `classifiers` list under `[metadata]` (e.g., `Programming Language :: Python :: 3.15`) - - Update the `python_requires` constraint under `[options]` to include the new version (e.g., `>=3.10, <3.16`) + - Update the `python_requires` constraint under `[options]` to include the new version (e.g., `>=3.11, <3.16`) 2. **`pyproject.toml`**: - Update the `target-version` list in the `[tool.black]` section to include the new version if needed @@ -296,12 +296,12 @@ When adding support for a new Python version (e.g., adding Python 3.15), update #### Dropping an old Python version -When dropping support for an old Python version (e.g., removing Python 3.10), update the following: +When dropping support for an old Python version (e.g., removing Python 3.11), update the following: **Code configuration files:** 1. **`setup.cfg`**: - Remove the old version from the `classifiers` list under `[metadata]` - - Update the `python_requires` constraint under `[options]` to reflect the new minimum version (e.g., `>=3.11, <3.15`) + - Update the `python_requires` constraint under `[options]` to reflect the new minimum version (e.g., `>=3.12, <3.15`) 2. **`pyproject.toml`**: - Update the `target-version` list in the `[tool.black]` section to remove the old version @@ -312,7 +312,7 @@ When dropping support for an old Python version (e.g., removing Python 3.10), up **CI/CD configuration files:** 1. **`.github/workflows/build.yml`**: - Remove the old version from the `unit-tests` and `integration-tests` job matrices - - Update the cache key version (e.g., increment `v28` to `v29`) to invalidate old caches + - Update the cache key version (e.g., increment `v34` to `v35`) to invalidate old caches **Documentation:** - Update the README.md and any getting started documentation to reflect the new supported Python version range diff --git a/README.md b/README.md index b6358bfd9..de9d91023 100644 --- a/README.md +++ b/README.md @@ -78,9 +78,9 @@ flowchart TD Installation ------------ -We test the client on Python 3.10, 3.11, 3.12, 3.13, and 3.14. It runs on Mac OS X, Linux, and Windows. +We test the client on Python 3.11, 3.12, 3.13, and 3.14. It runs on Mac OS X, Linux, and Windows. -**Version 3.0 and later needs Python 3.10 or higher.** +**Version 3.0 and later needs Python 3.10 or higher. Version 4.15.0 and later needs Python 3.11 or higher.** ### Install using pip diff --git a/docs/tutorials/reticulate.md b/docs/tutorials/reticulate.md index 6940a5e06..c74d4aa22 100644 --- a/docs/tutorials/reticulate.md +++ b/docs/tutorials/reticulate.md @@ -35,7 +35,7 @@ install.packages("reticulate") The Python synapseclient can be installed either directly into the Python installation you intend to use with reticulate or from within R using the reticulate library. -synapseclient has the same requirements and dependencies when installed for use with reticulate as it does in other usage. In particular note that synapseclient requires a Python version of 3.10 or greater. +synapseclient has the same requirements and dependencies when installed for use with reticulate as it does in other usage. In particular note that synapseclient requires a Python version of 3.11 or greater. #### Installing into Python diff --git a/pylintrc b/pylintrc index 8e007b74c..70a7c7627 100644 --- a/pylintrc +++ b/pylintrc @@ -93,7 +93,7 @@ prefer-stubs=no # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.10 +py-version=3.11 # Discover python modules and packages in the file system subtree. recursive=no diff --git a/pyproject.toml b/pyproject.toml index 8a66e87f2..3908cf4ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.black] line-length = 88 -target-version = ['py39'] +target-version = ['py311'] include = '\.pyi?$' [tool.ruff] diff --git a/setup.cfg b/setup.cfg index 178eaa202..d91a6c786 100644 --- a/setup.cfg +++ b/setup.cfg @@ -22,7 +22,6 @@ platforms = any classifiers = Development Status :: 5 - Production/Stable Programming Language :: Python - Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 Programming Language :: Python :: 3.13 @@ -42,7 +41,7 @@ classifiers = zip_safe = False include_package_data = True packages = find: -python_requires = >=3.10, <3.15 +python_requires = >=3.11, <3.15 install_requires = requests>=2.34.0,<3.0 urllib3>=2.6.3 diff --git a/synapseclient/models/dataset.py b/synapseclient/models/dataset.py index 1ab8150fa..cfdbc4563 100644 --- a/synapseclient/models/dataset.py +++ b/synapseclient/models/dataset.py @@ -3,9 +3,7 @@ from copy import deepcopy from dataclasses import dataclass, field from datetime import date, datetime -from typing import TYPE_CHECKING, Dict, List, Optional, Protocol, Union - -from typing_extensions import Self +from typing import TYPE_CHECKING, Dict, List, Optional, Protocol, Self, Union from synapseclient import Synapse from synapseclient.api.table_services import ViewEntityType, ViewTypeMask diff --git a/synapseclient/models/entityview.py b/synapseclient/models/entityview.py index d435e5eda..bd6bd2263 100644 --- a/synapseclient/models/entityview.py +++ b/synapseclient/models/entityview.py @@ -3,9 +3,7 @@ from copy import deepcopy from dataclasses import dataclass, field from datetime import date, datetime -from typing import Any, Dict, List, Optional, Protocol, Set, Union - -from typing_extensions import Self +from typing import Any, Dict, List, Optional, Protocol, Self, Set, Union from synapseclient import Synapse from synapseclient.api import ViewTypeMask diff --git a/synapseclient/models/materializedview.py b/synapseclient/models/materializedview.py index 862b37f38..2c22fed7a 100644 --- a/synapseclient/models/materializedview.py +++ b/synapseclient/models/materializedview.py @@ -2,9 +2,7 @@ from copy import deepcopy from dataclasses import dataclass, field, replace from datetime import date, datetime -from typing import Dict, List, Optional, Protocol, Union - -from typing_extensions import Self +from typing import Dict, List, Optional, Protocol, Self, Union from synapseclient import Synapse from synapseclient.core.async_utils import async_to_sync diff --git a/synapseclient/models/mixins/asynchronous_job.py b/synapseclient/models/mixins/asynchronous_job.py index 078dd823a..2cd0372b4 100644 --- a/synapseclient/models/mixins/asynchronous_job.py +++ b/synapseclient/models/mixins/asynchronous_job.py @@ -4,11 +4,10 @@ from dataclasses import dataclass from enum import Enum from string import Formatter -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Self from urllib.parse import quote from tqdm.contrib.logging import logging_redirect_tqdm -from typing_extensions import Self from synapseclient import Synapse from synapseclient.core.constants.concrete_types import ( diff --git a/synapseclient/models/mixins/storable_container.py b/synapseclient/models/mixins/storable_container.py index 39f35af13..834c5ac89 100644 --- a/synapseclient/models/mixins/storable_container.py +++ b/synapseclient/models/mixins/storable_container.py @@ -10,12 +10,11 @@ List, NoReturn, Optional, + Self, Tuple, Union, ) -from typing_extensions import Self - from synapseclient import Synapse from synapseclient.api import get_entity_id_bundle2 from synapseclient.api.entity_services import EntityHeader, get_children diff --git a/synapseclient/models/mixins/table_components.py b/synapseclient/models/mixins/table_components.py index d71282cf4..e23af514c 100644 --- a/synapseclient/models/mixins/table_components.py +++ b/synapseclient/models/mixins/table_components.py @@ -11,11 +11,10 @@ from dataclasses import dataclass, field from datetime import date, datetime from io import BytesIO -from typing import Any, Dict, List, Optional, Protocol, Tuple, Union +from typing import Any, Dict, List, Optional, Protocol, Self, Tuple, Union from tqdm import tqdm from tqdm.contrib.logging import logging_redirect_tqdm -from typing_extensions import Self from synapseclient import Synapse from synapseclient.api import ( diff --git a/synapseclient/models/protocols/search_index_protocol.py b/synapseclient/models/protocols/search_index_protocol.py index 1485c8dc7..e5dd19607 100644 --- a/synapseclient/models/protocols/search_index_protocol.py +++ b/synapseclient/models/protocols/search_index_protocol.py @@ -1,9 +1,7 @@ """Protocol for the specific methods of this class that have synchronous counterparts generated at runtime.""" -from typing import TYPE_CHECKING, List, Optional, Protocol - -from typing_extensions import Self +from typing import TYPE_CHECKING, List, Optional, Protocol, Self from synapseclient import Synapse from synapseclient.models.search_dsl import Query, SourceFilter diff --git a/synapseclient/models/protocols/search_management_protocol.py b/synapseclient/models/protocols/search_management_protocol.py index 11d185b7f..3cb0e4faa 100644 --- a/synapseclient/models/protocols/search_management_protocol.py +++ b/synapseclient/models/protocols/search_management_protocol.py @@ -1,9 +1,7 @@ """Protocol for the specific methods of this class that have synchronous counterparts generated at runtime.""" -from typing import TYPE_CHECKING, Optional, Protocol - -from typing_extensions import Self +from typing import TYPE_CHECKING, Optional, Protocol, Self if TYPE_CHECKING: from synapseclient import Synapse diff --git a/synapseclient/models/protocols/storable_container_protocol.py b/synapseclient/models/protocols/storable_container_protocol.py index 79d50c788..7b706a2c2 100644 --- a/synapseclient/models/protocols/storable_container_protocol.py +++ b/synapseclient/models/protocols/storable_container_protocol.py @@ -2,9 +2,7 @@ generated at runtime.""" import asyncio -from typing import TYPE_CHECKING, List, Literal, Optional, Protocol - -from typing_extensions import Self +from typing import TYPE_CHECKING, List, Literal, Optional, Protocol, Self from synapseclient import Synapse from synapseclient.core.constants.method_flags import COLLISION_OVERWRITE_LOCAL diff --git a/synapseclient/models/protocols/table_protocol.py b/synapseclient/models/protocols/table_protocol.py index f50de66b0..be6eb579a 100644 --- a/synapseclient/models/protocols/table_protocol.py +++ b/synapseclient/models/protocols/table_protocol.py @@ -1,9 +1,7 @@ """Protocol for the specific methods of this class that have synchronous counterparts generated at runtime.""" -from typing import Generator, Optional, Protocol - -from typing_extensions import Self +from typing import Generator, Optional, Protocol, Self from synapseclient import Synapse diff --git a/synapseclient/models/search_index.py b/synapseclient/models/search_index.py index 6aa3cdb19..aaf573002 100644 --- a/synapseclient/models/search_index.py +++ b/synapseclient/models/search_index.py @@ -8,9 +8,7 @@ from copy import deepcopy from dataclasses import dataclass, field, replace from datetime import date, datetime -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union - -from typing_extensions import Self +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Self, Union from synapseclient import Synapse from synapseclient.core.async_utils import async_to_sync, otel_trace_method diff --git a/synapseclient/models/search_management.py b/synapseclient/models/search_management.py index 1ec6c7e19..2bfa23efe 100644 --- a/synapseclient/models/search_management.py +++ b/synapseclient/models/search_management.py @@ -24,9 +24,17 @@ from dataclasses import dataclass, field from enum import Enum -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Protocol, Union - -from typing_extensions import Self +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Dict, + List, + Optional, + Protocol, + Self, + Union, +) from synapseclient.api import ( bind_search_config_to_entity, diff --git a/synapseclient/models/submission.py b/synapseclient/models/submission.py index 94e7215f6..49480102c 100644 --- a/synapseclient/models/submission.py +++ b/synapseclient/models/submission.py @@ -1,7 +1,5 @@ from dataclasses import dataclass, field -from typing import AsyncGenerator, Generator, Optional, Protocol, Union - -from typing_extensions import Self +from typing import AsyncGenerator, Generator, Optional, Protocol, Self, Union from synapseclient import Synapse from synapseclient.api import evaluation_services diff --git a/synapseclient/models/submission_status.py b/synapseclient/models/submission_status.py index 08712461d..d7dfee176 100644 --- a/synapseclient/models/submission_status.py +++ b/synapseclient/models/submission_status.py @@ -3,9 +3,7 @@ from copy import deepcopy from dataclasses import dataclass, field, replace from datetime import date, datetime -from typing import Any, Optional, Protocol, Union - -from typing_extensions import Self +from typing import Any, Optional, Protocol, Self, Union from synapseclient import Synapse from synapseclient.api import evaluation_services diff --git a/synapseclient/models/submissionview.py b/synapseclient/models/submissionview.py index 4647f489d..4b44dedee 100644 --- a/synapseclient/models/submissionview.py +++ b/synapseclient/models/submissionview.py @@ -3,9 +3,7 @@ from copy import deepcopy from dataclasses import dataclass, field from datetime import date, datetime -from typing import Dict, List, Optional, Protocol, Union - -from typing_extensions import Self +from typing import Dict, List, Optional, Protocol, Self, Union from synapseclient import Synapse from synapseclient.api.table_services import ViewEntityType diff --git a/synapseclient/models/table.py b/synapseclient/models/table.py index 46c18593e..41d21720c 100644 --- a/synapseclient/models/table.py +++ b/synapseclient/models/table.py @@ -3,9 +3,7 @@ from copy import deepcopy from dataclasses import dataclass, field from datetime import date, datetime -from typing import Any, Dict, List, Optional, Protocol, Union - -from typing_extensions import Self +from typing import Any, Dict, List, Optional, Protocol, Self, Union from synapseclient import Synapse from synapseclient import Table as Synapse_Table diff --git a/synapseclient/models/table_components.py b/synapseclient/models/table_components.py index 110390feb..825b7318d 100644 --- a/synapseclient/models/table_components.py +++ b/synapseclient/models/table_components.py @@ -3,9 +3,7 @@ from abc import ABC, abstractmethod from dataclasses import dataclass, field, replace from enum import Enum -from typing import TYPE_CHECKING, Any, AsyncGenerator, Dict, List, Optional, Union - -from typing_extensions import Self +from typing import TYPE_CHECKING, Any, AsyncGenerator, Dict, List, Optional, Self, Union from synapseclient import Column as Synapse_Column from synapseclient.core.async_utils import async_to_sync, skip_async_to_sync diff --git a/synapseclient/models/virtualtable.py b/synapseclient/models/virtualtable.py index 5858b4aa0..c95d9815d 100644 --- a/synapseclient/models/virtualtable.py +++ b/synapseclient/models/virtualtable.py @@ -3,9 +3,7 @@ from copy import deepcopy from dataclasses import dataclass, field, replace from datetime import date, datetime -from typing import Any, Dict, List, Optional, Protocol, Union - -from typing_extensions import Self +from typing import Any, Dict, List, Optional, Protocol, Self, Union from synapseclient import Synapse from synapseclient.core.async_utils import async_to_sync diff --git a/tests/unit/synapseutils/unit_test_synapseutils_describe.py b/tests/unit/synapseutils/unit_test_synapseutils_describe.py index 29318929a..260e1f390 100644 --- a/tests/unit/synapseutils/unit_test_synapseutils_describe.py +++ b/tests/unit/synapseutils/unit_test_synapseutils_describe.py @@ -1,4 +1,3 @@ -import sys import tempfile from unittest.mock import Mock, patch @@ -122,32 +121,18 @@ class TestDescribe: ], } ) - if sys.version_info < (3, 7, 0): - expected_results = { - "gene": {"dtype": "object", "mode": "CD44"}, - "score": {"dtype": "int64", "mode": 1, "min": 1, "max": 2, "mean": 1.4}, - "related": {}, - "presence_in_ad_brain": { - "dtype": "bool", - "mode": False, - "min": False, - "max": True, - "mean": 0.5, - }, - } - else: - expected_results = { - "gene": {"dtype": "object", "mode": "CD44"}, - "score": {"dtype": "int64", "mode": 1, "min": 1, "max": 2, "mean": 1.4}, - "related": {"dtype": "object", "mode": ["CD44"]}, - "presence_in_ad_brain": { - "dtype": "bool", - "mode": False, - "min": False, - "max": True, - "mean": 0.5, - }, - } + expected_results = { + "gene": {"dtype": "object", "mode": "CD44"}, + "score": {"dtype": "int64", "mode": 1, "min": 1, "max": 2, "mean": 1.4}, + "related": {"dtype": "object", "mode": ["CD44"]}, + "presence_in_ad_brain": { + "dtype": "bool", + "mode": False, + "min": False, + "max": True, + "mean": 0.5, + }, + } def test_describe_with_mixed_series(self, syn: synapseclient.Synapse): result = _describe_wrapper(df=self.df_mixed, syn=syn) From 49076169743af04f1978a96cec6a7dbc20d26a5d Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Thu, 1 Oct 2026 13:24:26 -0700 Subject: [PATCH 04/15] added missing grid field (#1465) --- synapseclient/models/curation.py | 22 +++++++++++++++ .../models/async/test_grid_async.py | 27 +++++++++++++++++++ .../models/async/unit_test_curation_async.py | 12 +++++++++ 3 files changed, 61 insertions(+) diff --git a/synapseclient/models/curation.py b/synapseclient/models/curation.py index 54ee59c3c..b8db5e105 100644 --- a/synapseclient/models/curation.py +++ b/synapseclient/models/curation.py @@ -3350,6 +3350,9 @@ def fill_grid_session_from_response(self, grid_session: "Grid") -> "Grid": grid_session.last_replica_id_service = data.get("lastReplicaIdService", None) grid_session.grid_json_schema_id = data.get("gridJsonSchema$Id", None) grid_session.source_entity_id = data.get("sourceEntityId", None) + grid_session.source_entity_version_number = data.get( + "sourceEntityVersionNumber", None + ) owner_principal_id = data.get("ownerPrincipalId") grid_session.owner_principal_id = ( int(owner_principal_id) if owner_principal_id is not None else None @@ -4530,6 +4533,8 @@ class GridSession: last_replica_id_service: The last replica ID issued to a service grid_json_schema_id: The $id of the JSON schema used for model validation source_entity_id: The synId of the table/view/csv that this grid was cloned from + source_entity_version_number: The version number of the source entity + that this grid was cloned from """ session_id: Optional[str] = None @@ -4559,6 +4564,9 @@ class GridSession: source_entity_id: Optional[str] = None """The synId of the table/view/csv that this grid was cloned from""" + source_entity_version_number: Optional[int] = None + """The version number of the source entity that this grid was cloned from""" + def fill_from_dict(self, synapse_response: Dict[str, Any]) -> "GridSession": """ Converts a response from the REST API into this dataclass. @@ -4580,6 +4588,9 @@ def fill_from_dict(self, synapse_response: Dict[str, Any]) -> "GridSession": ) self.grid_json_schema_id = synapse_response.get("gridJsonSchema$Id", None) self.source_entity_id = synapse_response.get("sourceEntityId", None) + self.source_entity_version_number = synapse_response.get( + "sourceEntityVersionNumber", None + ) return self @@ -5343,6 +5354,8 @@ class Grid(EnumCoercionMixin, GridSynchronousProtocol): last_replica_id_service: The last replica ID issued to a service grid_json_schema_id: The $id of the JSON schema used for model validation source_entity_id: The synId of the table/view/csv that this grid was cloned from + source_entity_version_number: The version number of the source entity + that this grid was cloned from record_set_version_number: The version number of the exported record set validation_summary_statistics: Summary statistics for validation results @@ -5450,6 +5463,9 @@ class Grid(EnumCoercionMixin, GridSynchronousProtocol): source_entity_id: Optional[str] = None """The synId of the table/view/csv that this grid was cloned from""" + source_entity_version_number: Optional[int] = None + """The version number of the source entity that this grid was cloned from""" + record_set_version_number: Optional[int] = None """The version number of the exported record set""" @@ -5540,6 +5556,9 @@ async def main(): self.last_replica_id_service = existing_session.last_replica_id_service self.grid_json_schema_id = existing_session.grid_json_schema_id self.source_entity_id = existing_session.source_entity_id + self.source_entity_version_number = ( + existing_session.source_entity_version_number + ) return self # No existing session found, create a new one @@ -5695,6 +5714,9 @@ def fill_from_dict(self, synapse_response: Dict[str, Any]) -> "Grid": ) self.grid_json_schema_id = synapse_response.get("gridJsonSchema$Id", None) self.source_entity_id = synapse_response.get("sourceEntityId", None) + self.source_entity_version_number = synapse_response.get( + "sourceEntityVersionNumber", None + ) owner_principal_id = synapse_response.get("ownerPrincipalId") self.owner_principal_id = ( int(owner_principal_id) if owner_principal_id is not None else None diff --git a/tests/integration/synapseclient/models/async/test_grid_async.py b/tests/integration/synapseclient/models/async/test_grid_async.py index 0f787dc7f..7321f3035 100644 --- a/tests/integration/synapseclient/models/async/test_grid_async.py +++ b/tests/integration/synapseclient/models/async/test_grid_async.py @@ -135,6 +135,10 @@ async def test_create_and_list_grid_sessions_async( assert created_grid.started_on is not None assert created_grid.etag is not None assert created_grid.source_entity_id == record_set_fixture.id + assert ( + created_grid.source_entity_version_number + == record_set_fixture.version_number + ) # WHEN: Listing grid sessions sessions = [] @@ -156,6 +160,10 @@ async def test_create_and_list_grid_sessions_async( ) assert our_session.started_by == created_grid.started_by assert our_session.source_entity_id == record_set_fixture.id + assert ( + our_session.source_entity_version_number + == record_set_fixture.version_number + ) async def test_get_grid_session_async(self, record_set_fixture: RecordSet) -> None: # GIVEN: A grid session created from a record set @@ -176,6 +184,10 @@ async def test_get_grid_session_async(self, record_set_fixture: RecordSet) -> No assert fetched_grid.started_on == created_grid.started_on assert fetched_grid.etag == created_grid.etag assert fetched_grid.source_entity_id == record_set_fixture.id + assert ( + fetched_grid.source_entity_version_number + == record_set_fixture.version_number + ) async def test_create_grid_session_with_authorization_mode_async( self, record_set_fixture: RecordSet @@ -198,6 +210,10 @@ async def test_create_grid_session_with_authorization_mode_async( assert created_grid is grid assert created_grid.session_id is not None assert created_grid.source_entity_id == record_set_fixture.id + assert ( + created_grid.source_entity_version_number + == record_set_fixture.version_number + ) assert created_grid.authorization_mode == AuthorizationMode.SOURCE_BENEFACTOR async def test_create_grid_session_and_reuse_session_async( @@ -231,6 +247,10 @@ async def test_create_grid_session_and_reuse_session_async( assert created_grid2.started_by == created_grid1.started_by assert created_grid2.started_on == created_grid1.started_on assert created_grid2.source_entity_id == record_set_fixture.id + assert ( + created_grid2.source_entity_version_number + == record_set_fixture.version_number + ) async def test_create_grid_session_validation_error_async(self) -> None: # GIVEN: A Grid instance with no record_set_id or initial_query @@ -328,6 +348,9 @@ async def file_indexed() -> bool: # THEN: The session ID is unchanged assert synced_grid.session_id == created_grid.session_id assert synced_grid.source_entity_id == ev.id + # AND the server currently omits the version for an EntityView source; + # update this assert if the server starts returning one + assert synced_grid.source_entity_version_number is None # AND: The downloaded CSV reflects the newly uploaded file dest = tempfile.mkdtemp() @@ -359,6 +382,10 @@ async def test_synchronize_grid_recordset_async( # THEN: The session ID is unchanged and the source entity is still the RecordSet assert synced_grid.session_id == created_grid.session_id assert synced_grid.source_entity_id == record_set_fixture.id + assert ( + synced_grid.source_entity_version_number + == record_set_fixture.version_number + ) async def test_import_csv_to_grid_session_async( self, diff --git a/tests/unit/synapseclient/models/async/unit_test_curation_async.py b/tests/unit/synapseclient/models/async/unit_test_curation_async.py index 095391e89..588f02925 100644 --- a/tests/unit/synapseclient/models/async/unit_test_curation_async.py +++ b/tests/unit/synapseclient/models/async/unit_test_curation_async.py @@ -97,6 +97,7 @@ RECORD_SET_ID = "syn3456789" SESSION_ID = "session-abc-123" SOURCE_ENTITY_ID = "syn5555555" +SOURCE_ENTITY_VERSION_NUMBER = 13 GRID_ETAG = "grid-etag-456" STARTED_BY = "user-1" STARTED_ON = "2024-03-01T00:00:00.000Z" @@ -167,6 +168,7 @@ def _get_grid_session_response(): "lastReplicaIdService": -5, "gridJsonSchema$Id": "my-schema-id", "sourceEntityId": SOURCE_ENTITY_ID, + "sourceEntityVersionNumber": SOURCE_ENTITY_VERSION_NUMBER, # The server returns ownerPrincipalId as a string; the client coerces to int. "ownerPrincipalId": str(OWNER_PRINCIPAL_ID), "authorizationMode": "SESSION_OWNER", @@ -2807,6 +2809,7 @@ def test_fill_from_dict(self) -> None: assert grid.last_replica_id_service == -5 assert grid.grid_json_schema_id == "my-schema-id" assert grid.source_entity_id == SOURCE_ENTITY_ID + assert grid.source_entity_version_number == SOURCE_ENTITY_VERSION_NUMBER # AND the owner principal id is coerced from the response string to an int assert grid.owner_principal_id == OWNER_PRINCIPAL_ID assert isinstance(grid.owner_principal_id, int) @@ -2838,6 +2841,7 @@ async def test_create_async_with_record_set_id(self) -> None: assert result.started_by == STARTED_BY assert result.started_on == STARTED_ON assert result.source_entity_id == SOURCE_ENTITY_ID + assert result.source_entity_version_number == SOURCE_ENTITY_VERSION_NUMBER assert result.authorization_mode == AuthorizationMode.SESSION_OWNER async def test_create_async_forwards_authorization_mode_to_request(self) -> None: @@ -2900,6 +2904,7 @@ async def mock_list_async(*args, **kwargs): assert result.session_id == SESSION_ID assert result.started_by == STARTED_BY assert result.source_entity_id == SOURCE_ENTITY_ID + assert result.source_entity_version_number == SOURCE_ENTITY_VERSION_NUMBER async def test_create_async_attach_to_previous_no_existing(self) -> None: # GIVEN a Grid with a record_set_id @@ -2935,6 +2940,7 @@ async def mock_list_async(*args, **kwargs): # THEN a new grid session should be created assert result.session_id == SESSION_ID + assert result.source_entity_version_number == SOURCE_ENTITY_VERSION_NUMBER async def test_export_to_record_set_async(self) -> None: # GIVEN a Grid with a session_id @@ -3013,6 +3019,7 @@ async def test_list_async(self) -> None: "lastReplicaIdService": -10, "gridJsonSchema$Id": None, "sourceEntityId": "syn6666666", + "sourceEntityVersionNumber": 2, } async def mock_list(*args, **kwargs): @@ -3032,8 +3039,12 @@ async def mock_list(*args, **kwargs): assert len(results) == 2 assert results[0].session_id == SESSION_ID assert results[0].source_entity_id == SOURCE_ENTITY_ID + assert ( + results[0].source_entity_version_number == SOURCE_ENTITY_VERSION_NUMBER + ) assert results[1].session_id == "session-xyz-999" assert results[1].source_entity_id == "syn6666666" + assert results[1].source_entity_version_number == 2 async def test_list_async_with_source_id(self) -> None: # GIVEN mock API responses filtered by source_id @@ -3244,6 +3255,7 @@ def test_fill_grid_session_from_response(self) -> None: assert grid.started_by == STARTED_BY assert grid.etag == GRID_ETAG assert grid.source_entity_id == SOURCE_ENTITY_ID + assert grid.source_entity_version_number == SOURCE_ENTITY_VERSION_NUMBER # AND the owner principal id is coerced from the response string to an int assert grid.owner_principal_id == OWNER_PRINCIPAL_ID assert isinstance(grid.owner_principal_id, int) From 38c119ddbf6c0a2f1334153e30041efb40698abc Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Thu, 1 Oct 2026 14:21:19 -0700 Subject: [PATCH 05/15] [SYNPY-1795] JSONSchema now saves version info when storing (#1463) * JSONSchema now saves version info when storing * update operatiosn JSONSchema test --- .../experimental/mixins/base_json_schema.md | 1 + .../extensions/curator/schema_management.py | 4 +- synapseclient/models/mixins/__init__.py | 2 + synapseclient/models/mixins/json_schema.py | 19 +- synapseclient/models/organization.py | 61 ++++- .../models/async/test_organization_async.py | 36 ++- .../test_factory_operations_store_async.py | 4 +- .../async/unit_test_organization_async.py | 247 +++++++++++++++--- 8 files changed, 324 insertions(+), 50 deletions(-) diff --git a/docs/reference/experimental/mixins/base_json_schema.md b/docs/reference/experimental/mixins/base_json_schema.md index 32997938f..1aeaab2f8 100644 --- a/docs/reference/experimental/mixins/base_json_schema.md +++ b/docs/reference/experimental/mixins/base_json_schema.md @@ -7,3 +7,4 @@ ::: synapseclient.models.mixins.JSONSchemaDerivedKeys ::: synapseclient.models.mixins.ValidationException ::: synapseclient.models.mixins.CausingException +::: synapseclient.models.mixins.JSONSchemaVersionInfo diff --git a/synapseclient/extensions/curator/schema_management.py b/synapseclient/extensions/curator/schema_management.py index cf51e71a7..f7c8b19a1 100644 --- a/synapseclient/extensions/curator/schema_management.py +++ b/synapseclient/extensions/curator/schema_management.py @@ -63,7 +63,7 @@ def register_jsonschema( synapse_client=syn ) print(f"Registered schema URI: {json_schema.uri}") - print(f"Schema version: {json_schema.version}") + print(f"Schema version: {json_schema.last_stored_version_info.semantic_version}") ``` """ return wrap_async_to_sync( @@ -125,7 +125,7 @@ async def register_jsonschema_async( synapse_client=syn )) print(f"Registered schema URI: {json_schema.uri}") - print(f"Schema version: {json_schema.version}") + print(f"Schema version: {json_schema.last_stored_version_info.semantic_version}") ``` """ from synapseclient import Synapse diff --git a/synapseclient/models/mixins/__init__.py b/synapseclient/models/mixins/__init__.py index f20e4dbb8..7378f6ae5 100644 --- a/synapseclient/models/mixins/__init__.py +++ b/synapseclient/models/mixins/__init__.py @@ -18,6 +18,7 @@ JSONSchemaDerivedKeys, JSONSchemaValidation, JSONSchemaValidationStatistics, + JSONSchemaVersionInfo, ValidationException, ) from synapseclient.models.mixins.storable_container import StorableContainer @@ -39,6 +40,7 @@ "InvalidJSONSchemaValidation", "JSONSchemaDerivedKeys", "JSONSchemaValidationStatistics", + "JSONSchemaVersionInfo", "ValidationException", "CausingException", "FormGroup", diff --git a/synapseclient/models/mixins/json_schema.py b/synapseclient/models/mixins/json_schema.py index ac6caecc5..5c4d9899d 100644 --- a/synapseclient/models/mixins/json_schema.py +++ b/synapseclient/models/mixins/json_schema.py @@ -23,6 +23,8 @@ @dataclass class JSONSchemaVersionInfo: + """Information about one version of a JSON schema that is registered in Synapse.""" + organization_id: str """The unique identifier for the organization.""" @@ -41,8 +43,11 @@ class JSONSchemaVersionInfo: version_id: str """The unique identifier for the schema version.""" - semantic_version: str - """The semantic version of the schema.""" + semantic_version: Optional[str] + """ + The semantic version of the schema. This is None when the version was stored + without a semantic version. + """ json_sha256_hex: str """The SHA-256 hash of the schema in hexadecimal format.""" @@ -55,8 +60,14 @@ class JSONSchemaVersionInfo: @property def json_schema_uri(self) -> str: - """The JSON schema URI constructed from organization name, schema name, and semantic version.""" - return f"{self.organization_name}-{self.schema_name}-{self.semantic_version}" + """ + The JSON schema URI constructed from organization name, schema name, and + semantic version. The semantic version is not included when it is None. + """ + base = f"{self.organization_name}-{self.schema_name}" + if self.semantic_version is None: + return base + return f"{base}-{self.semantic_version}" @dataclass diff --git a/synapseclient/models/organization.py b/synapseclient/models/organization.py index e8ca28eb7..cc3fb9c2e 100644 --- a/synapseclient/models/organization.py +++ b/synapseclient/models/organization.py @@ -637,13 +637,16 @@ def store( Arguments: schema_body: The body of the JSONSchema to store version: The version of the JSONSchema body to store - dry_run: Whether or not to do a dry-run + dry_run: Whether or not to do a dry-run. A dry run does not store a + version and does not change this instance. synapse_client: If not passed in and caching was not disabled by `Synapse.allow_client_caching(False)` this will use the last created instance from the Synapse class constructor Returns: - Itself + Itself. After a store that is not a dry run, organization_id, id and + uri identify the stored schema, and last_stored_version_info holds + the JSONSchemaVersionInfo of the new version. Example: Store a JSON Schema in Synapse   @@ -811,6 +814,10 @@ class JSONSchema(JSONSchemaProtocol): created_on: The date this schema was created created_by: The ID of the user that created this schema uri: The schema identifier in format: - + last_stored_version_info: The JSONSchemaVersionInfo of the version that the + most recent store call on this instance created. This is None until + store is called. It is not guaranteed to be the latest version in + Synapse, and get does not set it. """ name: Optional[str] = None @@ -819,7 +826,7 @@ class JSONSchema(JSONSchemaProtocol): organization_name: Optional[str] = None """The name of the organization the schema belongs to""" - organization_id: Optional[int] = None + organization_id: Optional[str] = None """The id of the organization the schema belongs to""" id: Optional[str] = None @@ -834,6 +841,15 @@ class JSONSchema(JSONSchemaProtocol): uri: Optional[str] = field(init=False) """The schema identifier in format: -""" + last_stored_version_info: Optional[JSONSchemaVersionInfo] = field( + default=None, init=False, compare=False + ) + """ + The JSONSchemaVersionInfo of the version that the most recent store call on + this instance created. This is None until store is called. It is not + guaranteed to be the latest version in Synapse, and get does not set it. + """ + def __post_init__(self) -> None: if self.name: _check_schema_name(self.name) @@ -922,13 +938,16 @@ async def store_async( Arguments: schema_body: The body of the JSONSchema to store version: The version of the JSONSchema body to store - dry_run: Whether or not to do a dry-run + dry_run: Whether or not to do a dry-run. A dry run does not store a + version and does not change this instance. synapse_client: If not passed in and caching was not disabled by `Synapse.allow_client_caching(False)` this will use the last created instance from the Synapse class constructor Returns: - Itself + Itself. After a store that is not a dry run, organization_id, id and + uri identify the stored schema, and last_stored_version_info holds + the JSONSchemaVersionInfo of the new version. Example: Store a JSON Schema in Synapse   @@ -961,6 +980,29 @@ async def store_schema(): asyncio.run(store_schema()) ``` + + Example: Get the version info after a store +   + Store a version of a JSON Schema, then print the version ID and the + semantic version that Synapse created. + ```python + from synapseclient.models import JSONSchema + from synapseclient import Synapse + import asyncio + + async def store_schema(): + + syn = Synapse() + syn.login() + + schema = JSONSchema(organization_name="my.org", name="test.schema") + schema_body = {"type": "object"} + await schema.store_async(schema_body=schema_body, version="0.0.1") + print(schema.last_stored_version_info.version_id) + print(schema.last_stored_version_info.semantic_version) + + asyncio.run(store_schema()) + ``` """ if not self.name: raise ValueError("JSONSchema must have a name") @@ -980,10 +1022,15 @@ async def store_schema(): completed_request: CreateSchemaRequest = await request.send_job_and_wait_async( synapse_client=synapse_client ) + # A dry run does not store a version, so do not change the instance + if dry_run: + return self + new_version_info = completed_request.new_version_info self.organization_id = new_version_info.organization_id - self.created_by = new_version_info.created_by - self.created_on = new_version_info.created_on + self.id = new_version_info.schema_id + self.uri = f"{self.organization_name}-{self.name}" + self.last_stored_version_info = new_version_info return self async def delete_async( diff --git a/tests/integration/synapseclient/models/async/test_organization_async.py b/tests/integration/synapseclient/models/async/test_organization_async.py index 97356c9fd..3f890700e 100644 --- a/tests/integration/synapseclient/models/async/test_organization_async.py +++ b/tests/integration/synapseclient/models/async/test_organization_async.py @@ -220,16 +220,20 @@ async def test_store_and_get(self, json_schema: JSONSchema) -> None: assert not json_schema.id assert not json_schema.created_by assert not json_schema.created_on + assert json_schema.last_stored_version_info is None # WHEN the object is stored - # THEN the Synapse metadata is filled out, minus id (which is not part of the response) - await json_schema.store_async({}, synapse_client=self.syn) + # THEN the identity fields and the stored version info are filled out + await json_schema.store_async({}, version="0.0.1", synapse_client=self.syn) assert json_schema.name assert json_schema.organization_name assert json_schema.uri assert json_schema.organization_id - assert json_schema.created_by - assert json_schema.created_on - assert not json_schema.id + assert json_schema.id + assert json_schema.last_stored_version_info.version_id + assert json_schema.last_stored_version_info.semantic_version == "0.0.1" + # AND created_by and created_on are not set from the version + assert json_schema.created_by is None + assert json_schema.created_on is None # AND it should be getable by future instances using the same name js2 = JSONSchema(json_schema.name, json_schema.organization_name) await js2.get_async(synapse_client=self.syn) @@ -241,6 +245,26 @@ async def test_store_and_get(self, json_schema: JSONSchema) -> None: assert js2.created_by assert js2.created_on + async def test_store_dry_run(self, json_schema: JSONSchema) -> None: + # GIVEN a schema that hasn't been created in Synapse + # WHEN the schema is stored with dry_run=True + result = await json_schema.store_async( + schema_body={}, version="0.0.1", dry_run=True, synapse_client=self.syn + ) + # THEN the same instance is returned + assert result is json_schema + # AND the instance does not change + assert json_schema.last_stored_version_info is None + assert json_schema.organization_id is None + assert json_schema.id is None + assert json_schema.created_by is None + assert json_schema.created_on is None + # AND no versions exist in Synapse + versions = [] + async for item in json_schema.get_versions_async(synapse_client=self.syn): + versions.append(item) + assert len(versions) == 0 + async def test_delete(self, organization_with_schema: Organization) -> None: # GIVEN an organization with 3 schema schemas: list[JSONSchema] = [] @@ -265,6 +289,7 @@ async def test_delete_version(self, json_schema: JSONSchema) -> None: await json_schema.store_async( schema_body={}, version="0.0.1", synapse_client=self.syn ) + assert json_schema.last_stored_version_info.semantic_version == "0.0.1" # THEN that schema should have one version js_versions: list[JSONSchemaVersionInfo] = [] async for item in json_schema.get_versions_async(synapse_client=self.syn): @@ -274,6 +299,7 @@ async def test_delete_version(self, json_schema: JSONSchema) -> None: await json_schema.store_async( schema_body={}, version="0.0.2", synapse_client=self.syn ) + assert json_schema.last_stored_version_info.semantic_version == "0.0.2" # THEN that schema should have two versions js_versions = [] async for item in json_schema.get_versions_async(synapse_client=self.syn): diff --git a/tests/integration/synapseclient/operations/async/test_factory_operations_store_async.py b/tests/integration/synapseclient/operations/async/test_factory_operations_store_async.py index 4ef7b24fb..bff2f614a 100644 --- a/tests/integration/synapseclient/operations/async/test_factory_operations_store_async.py +++ b/tests/integration/synapseclient/operations/async/test_factory_operations_store_async.py @@ -893,7 +893,9 @@ async def test_store_async_json_schema_basic(self) -> None: ) # THEN the JSON schema is created - assert stored_schema.created_on is not None + assert stored_schema.id is not None + assert stored_schema.last_stored_version_info is not None + assert stored_schema.last_stored_version_info.semantic_version == "1.0.0" assert stored_schema.organization_name == stored_org.name assert stored_schema.name == "TestSchema" diff --git a/tests/unit/synapseclient/models/async/unit_test_organization_async.py b/tests/unit/synapseclient/models/async/unit_test_organization_async.py index be883caf6..253ecffb9 100644 --- a/tests/unit/synapseclient/models/async/unit_test_organization_async.py +++ b/tests/unit/synapseclient/models/async/unit_test_organization_async.py @@ -1,5 +1,6 @@ """Unit tests for the Organization and JSONSchema models.""" +import dataclasses from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -21,7 +22,6 @@ SCHEMA_NAME = "mytest.schemaname" SCHEMA_ID = "5001" SCHEMA_URI = f"{ORG_NAME}-{SCHEMA_NAME}" -ORG_ID_INT = 1075 VERSION = "1.0.0" VERSION_ID = "9001" JSON_SHA_HEX = "abc123sha256" @@ -55,7 +55,7 @@ def _get_organization_response(**overrides): def _get_json_schema_list_response(**overrides): """Return a mock JSON schema list item response.""" response = { - "organizationId": ORG_ID_INT, + "organizationId": ORG_ID, "organizationName": ORG_NAME, "schemaId": SCHEMA_ID, "schemaName": SCHEMA_NAME, @@ -69,7 +69,7 @@ def _get_json_schema_list_response(**overrides): def _get_schema_version_response(semantic_version=VERSION, **overrides): """Return a mock JSON schema version info response.""" response = { - "organizationId": ORG_ID_INT, + "organizationId": ORG_ID, "organizationName": ORG_NAME, "schemaId": SCHEMA_ID, "$id": f"{ORG_NAME}-{SCHEMA_NAME}-{semantic_version}", @@ -84,6 +84,24 @@ def _get_schema_version_response(semantic_version=VERSION, **overrides): return response +def _get_version_info(**overrides) -> JSONSchemaVersionInfo: + """Return a JSONSchemaVersionInfo for store responses.""" + values = { + "organization_id": ORG_ID, + "organization_name": ORG_NAME, + "schema_id": SCHEMA_ID, + "id": f"{ORG_NAME}-{SCHEMA_NAME}", + "schema_name": SCHEMA_NAME, + "version_id": VERSION_ID, + "semantic_version": VERSION, + "json_sha256_hex": JSON_SHA_HEX, + "created_on": CREATED_ON, + "created_by": CREATED_BY, + } + values.update(overrides) + return JSONSchemaVersionInfo(**values) + + def _get_acl_response(): """Return a mock ACL response.""" return { @@ -477,7 +495,7 @@ def test_fill_from_dict(self) -> None: schema.fill_from_dict(response) # THEN all fields should be populated - assert schema.organization_id == ORG_ID_INT + assert schema.organization_id == ORG_ID assert schema.organization_name == ORG_NAME assert schema.id == SCHEMA_ID assert schema.name == SCHEMA_NAME @@ -558,7 +576,7 @@ async def test_store_async_with_schema_body(self) -> None: schema = JSONSchema(name=SCHEMA_NAME, organization_name=ORG_NAME) mock_version_info = JSONSchemaVersionInfo( - organization_id=ORG_ID_INT, + organization_id=ORG_ID, organization_name=ORG_NAME, schema_id=SCHEMA_ID, id=f"{ORG_NAME}-{SCHEMA_NAME}", @@ -586,17 +604,24 @@ async def test_store_async_with_schema_body(self) -> None: synapse_client=self.syn, ) - # THEN the result should have updated fields from the version info - assert result.organization_id == ORG_ID_INT - assert result.created_by == CREATED_BY - assert result.created_on == CREATED_ON + # THEN the result should have updated identity fields from the version info + assert result.organization_id == ORG_ID + assert result.id == SCHEMA_ID + assert result.uri == SCHEMA_URI + + # AND created_by and created_on should not be set from the version info + assert result.created_by is None + assert result.created_on is None + + # AND last_stored_version_info should be the new version info + assert result.last_stored_version_info is mock_version_info async def test_store_async_with_version(self) -> None: # GIVEN a JSONSchema with name and organization_name schema = JSONSchema(name=SCHEMA_NAME, organization_name=ORG_NAME) mock_version_info = JSONSchemaVersionInfo( - organization_id=ORG_ID_INT, + organization_id=ORG_ID, organization_name=ORG_NAME, schema_id=SCHEMA_ID, id=f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}", @@ -626,27 +651,38 @@ async def test_store_async_with_version(self) -> None: ) # THEN the result should be populated - assert result.organization_id == ORG_ID_INT + assert result.organization_id == ORG_ID - async def test_store_async_dry_run(self) -> None: - # GIVEN a JSONSchema with name and organization_name - schema = JSONSchema(name=SCHEMA_NAME, organization_name=ORG_NAME) + # AND last_stored_version_info should have the stored version + assert result.last_stored_version_info.semantic_version == VERSION - mock_version_info = JSONSchemaVersionInfo( - organization_id=ORG_ID_INT, - organization_name=ORG_NAME, - schema_id=SCHEMA_ID, - id=f"{ORG_NAME}-{SCHEMA_NAME}", - schema_name=SCHEMA_NAME, - version_id=VERSION_ID, - semantic_version=VERSION, - json_sha256_hex=JSON_SHA_HEX, - created_on=CREATED_ON, - created_by=CREATED_BY, + @pytest.mark.parametrize( + "filled_from_get", + [False, True], + ids=["new_schema", "schema_filled_from_get"], + ) + async def test_store_async_dry_run(self, filled_from_get: bool) -> None: + # GIVEN a JSONSchema + if filled_from_get: + # filled from a get response, with a prior last_stored_version_info + schema = JSONSchema() + schema.fill_from_dict(_get_json_schema_list_response()) + schema.last_stored_version_info = _get_version_info(version_id="1111") + else: + # with only name and organization_name + schema = JSONSchema(name=SCHEMA_NAME, organization_name=ORG_NAME) + values_before = dataclasses.asdict(schema) + + # AND the dry run response has different values + dry_run_version_info = _get_version_info( + organization_id="9999", + schema_id="9999", + version_id="2222", + created_on="2025-06-06T00:00:00.000Z", + created_by="999999", ) - mock_completed_request = MagicMock() - mock_completed_request.new_version_info = mock_version_info + mock_completed_request.new_version_info = dry_run_version_info # WHEN I call store_async with dry_run=True with patch.object( @@ -662,8 +698,129 @@ async def test_store_async_dry_run(self) -> None: synapse_client=self.syn, ) - # THEN send_job_and_wait_async should be called - mock_send.assert_called_once() + # THEN send_job_and_wait_async should be called + mock_send.assert_called_once() + + # AND the same instance should be returned + assert result is schema + + # AND no attributes should change + assert dataclasses.asdict(schema) == values_before + + async def test_store_async_after_get_updates_identity_keeps_created_values( + self, + ) -> None: + # GIVEN a JSONSchema filled from a get response + schema = JSONSchema() + schema.fill_from_dict(_get_json_schema_list_response()) + + # AND the organization_name is changed to a different organization + new_org_name = "mytest.otherorganization" + new_org_id = "2075" + new_schema_id = "6001" + schema.organization_name = new_org_name + + # AND the new version has different identity and created values + new_created_on = "2025-06-06T00:00:00.000Z" + new_created_by = "999999" + new_version_info = _get_version_info( + organization_id=new_org_id, + organization_name=new_org_name, + schema_id=new_schema_id, + id=f"{new_org_name}-{SCHEMA_NAME}", + created_on=new_created_on, + created_by=new_created_by, + ) + mock_completed_request = MagicMock() + mock_completed_request.new_version_info = new_version_info + + # WHEN I call store_async + with patch.object( + CreateSchemaRequest, + "send_job_and_wait_async", + new_callable=AsyncMock, + return_value=mock_completed_request, + ): + self.syn.repoEndpoint = REPO_ENDPOINT + await schema.store_async( + schema_body=SCHEMA_BODY.copy(), + synapse_client=self.syn, + ) + + # THEN the identity fields should match the new organization + assert schema.organization_id == new_org_id + assert schema.id == new_schema_id + assert schema.uri == f"{new_org_name}-{SCHEMA_NAME}" + + # AND created_on and created_by should keep the values from get + assert schema.created_on == CREATED_ON + assert schema.created_by == CREATED_BY + + # AND the version values should be in last_stored_version_info + assert schema.last_stored_version_info is new_version_info + assert schema.last_stored_version_info.created_on == new_created_on + assert schema.last_stored_version_info.created_by == new_created_by + + async def test_store_async_second_store_replaces_version_info(self) -> None: + # GIVEN a JSONSchema with name and organization_name + schema = JSONSchema(name=SCHEMA_NAME, organization_name=ORG_NAME) + + first_version_info = _get_version_info( + version_id="1111", semantic_version="0.0.1" + ) + second_version_info = _get_version_info( + version_id="2222", semantic_version="0.0.2" + ) + first_request = MagicMock() + first_request.new_version_info = first_version_info + second_request = MagicMock() + second_request.new_version_info = second_version_info + + # WHEN I call store_async two times + with patch.object( + CreateSchemaRequest, + "send_job_and_wait_async", + new_callable=AsyncMock, + side_effect=[first_request, second_request], + ): + self.syn.repoEndpoint = REPO_ENDPOINT + await schema.store_async( + schema_body=SCHEMA_BODY.copy(), + version="0.0.1", + synapse_client=self.syn, + ) + assert schema.last_stored_version_info is first_version_info + + await schema.store_async( + schema_body=SCHEMA_BODY.copy(), + version="0.0.2", + synapse_client=self.syn, + ) + + # THEN last_stored_version_info should be the second version info + assert schema.last_stored_version_info is second_version_info + assert schema.last_stored_version_info.semantic_version == "0.0.2" + + def test_last_stored_version_info_field_definition(self) -> None: + # GIVEN a new JSONSchema + schema1 = JSONSchema(name=SCHEMA_NAME, organization_name=ORG_NAME) + + # THEN last_stored_version_info should default to None + assert schema1.last_stored_version_info is None + + # AND passing last_stored_version_info to the constructor should raise TypeError + version_info = _get_version_info() + with pytest.raises(TypeError): + JSONSchema( + name=SCHEMA_NAME, + organization_name=ORG_NAME, + last_stored_version_info=version_info, + ) + + # AND two schemas that differ only in last_stored_version_info are equal + schema2 = JSONSchema(name=SCHEMA_NAME, organization_name=ORG_NAME) + schema1.last_stored_version_info = version_info + assert schema1 == schema2 async def test_store_async_without_name_raises(self) -> None: # GIVEN a JSONSchema without a name @@ -687,6 +844,10 @@ async def test_get_async(self) -> None: # GIVEN a JSONSchema with name and organization_name schema = JSONSchema(name=SCHEMA_NAME, organization_name=ORG_NAME) + # AND last_stored_version_info from a prior store + prior_version_info = _get_version_info() + schema.last_stored_version_info = prior_version_info + schema_response = _get_json_schema_list_response() async def mock_list(*args, **kwargs): @@ -711,6 +872,9 @@ async def mock_list(*args, **kwargs): assert result.organization_name == ORG_NAME assert result.id == SCHEMA_ID + # AND last_stored_version_info should not change + assert result.last_stored_version_info is prior_version_info + async def test_get_async_schema_not_found_raises(self) -> None: # GIVEN a JSONSchema with a name that does not exist in the org schema = JSONSchema(name="nonexistent.schema", organization_name=ORG_NAME) @@ -841,7 +1005,7 @@ async def test_get_versions_async_filters_non_semantic(self) -> None: # One version has a semantic version, one does not version_with_semantic = _get_schema_version_response(semantic_version="1.0.0") version_without_semantic = { - "organizationId": ORG_ID_INT, + "organizationId": ORG_ID, "organizationName": ORG_NAME, "schemaId": SCHEMA_ID, "$id": f"{ORG_NAME}-{SCHEMA_NAME}", @@ -934,6 +1098,27 @@ async def test_get_body_async_without_org_name_raises(self) -> None: await schema.get_body_async(synapse_client=self.syn) +class TestJSONSchemaVersionInfo: + """Tests for the JSONSchemaVersionInfo dataclass.""" + + @pytest.mark.parametrize( + "semantic_version, expected_uri", + [ + (VERSION, f"{ORG_NAME}-{SCHEMA_NAME}-{VERSION}"), + (None, f"{ORG_NAME}-{SCHEMA_NAME}"), + ], + ids=["with_semantic_version", "without_semantic_version"], + ) + def test_json_schema_uri( + self, semantic_version: str | None, expected_uri: str + ) -> None: + # GIVEN a JSONSchemaVersionInfo with or without a semantic version + version_info = _get_version_info(semantic_version=semantic_version) + + # THEN json_schema_uri should include the semantic version only when it is set + assert version_info.json_schema_uri == expected_uri + + class TestCreateSchemaRequest: """Tests for the CreateSchemaRequest helper dataclass.""" @@ -1010,6 +1195,6 @@ def test_fill_from_dict(self) -> None: # THEN the new_version_info should be populated assert request.new_version_info is not None - assert request.new_version_info.organization_id == ORG_ID_INT + assert request.new_version_info.organization_id == ORG_ID assert request.new_version_info.semantic_version == VERSION assert request.schema == {"$id": "validated", "type": "object"} From e5f3fa2e96bded691eb57ffe9d7980b9a9ad7e23 Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Fri, 2 Oct 2026 10:02:19 -0700 Subject: [PATCH 06/15] fixed security issues by updating packages (#1466) --- Pipfile.lock | 1918 ++++++++++++++++++++++++++++---------------------- setup.cfg | 2 +- 2 files changed, 1082 insertions(+), 838 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 0e6ae40a4..b38f178bc 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -18,11 +18,11 @@ "default": { "anyio": { "hashes": [ - "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", - "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f" + "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101", + "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94" ], "markers": "python_version >= '3.10'", - "version": "==4.14.2" + "version": "==4.15.1" }, "async-lru": { "hashes": [ @@ -151,159 +151,251 @@ "sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4", "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264" ], - "markers": "python_version >= '3.10'", + "markers": "platform_python_implementation != 'PyPy'", "version": "==2.1.1" }, "charset-normalizer": { "hashes": [ - "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380", - "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62", - "sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c", - "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226", - "sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5", - "sha256:0fa1aec2d32bcc03c8fa0f6f1712caad1adc38509f31142112e5c9daf5b9c833", - "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b", - "sha256:16d10d789dd9bcca1173c95af82c58433122564b7bc39385124be735a35cbe99", - "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501", - "sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec", - "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698", - "sha256:231ddcbb35e2ff8973e1365db41fe0572662893b99a05deb183b68ad4c0c8bd4", - "sha256:253a4a220747e8b5faf57ec320c4f5efb0cef05f647420bf267143ec15dba10a", - "sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3", - "sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2", - "sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a", - "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e", - "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4", - "sha256:375b83ed0aecfce76c16d198fbc21f3b11b337d68662bea0a995046682a11419", - "sha256:3c09a49d6cde137258beb3d551994a2927fd35ad5cf96aed573f61bbd67c5f84", - "sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da", - "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519", - "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe", - "sha256:432786d3561e69aeeae6c7e8648964ce0ad05736120135601f87ac26b9c83381", - "sha256:43b9e366a31fdd1c87d0eb08f579b4a82b723ea54338f040d6b4e518a026ea29", - "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614", - "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0", - "sha256:476743fe6dfe14a2da12e3ac79125dc84a3b2cf8094369a47a1529b0cd8549fe", - "sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29", - "sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0", - "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917", - "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9", - "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32", - "sha256:58150c9f9b9a552505912d182ccdf26f6396fb6094816ceebcbb20eecabaed94", - "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63", - "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd", - "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198", - "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde", - "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012", - "sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1", - "sha256:65a7ff3f705e57d392f7261b6d0550fe137c3019477431f1c355e0db0a7d3e15", - "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b", - "sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993", - "sha256:68ce9f4d6b26d5ccbf7fd4459bf75f74a0a146677ebba80597df60cbdb20e6f4", - "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5", - "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8", - "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35", - "sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642", - "sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2", - "sha256:79580094b00d1789d1f93ea55bc43cb2f611910c72235b7657f3482ddcc1b22d", - "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9", - "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c", - "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33", - "sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db", - "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf", - "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9", - "sha256:8c041122946b7ba21bb32c45b1aa57b1be35527690aeb3c5c234521085632eee", - "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84", - "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44", - "sha256:920079c3f7456fa213e0829ed2073aaa727fd39d889ead5b4f35d0de5460d04f", - "sha256:93d59d504b230e83c7a843251681959a0b6a9cd76f6e146ce1b8a80eb8739af9", - "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9", - "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177", - "sha256:9bb41182d93ea91f60b4bc8fbf4c820c69ef8a12ab2d917f3f1834f1acad07e8", - "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b", - "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39", - "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41", - "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0", - "sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616", - "sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d", - "sha256:ad41ba96094304aa090f5a30cb6e4fb3b3f1c264c523394b4c39bbacc4dc92ba", - "sha256:b5314963fce9b0b12743891de876e724997864ee22aa496f903f426c7e2fa5b2", - "sha256:bcf74c1df76758a395bf0af608c04c82257523f55c9868b334f06270d0f2112b", - "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9", - "sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b", - "sha256:c1225416b463483160e4af85d5fc3a9690ccb53fd4b1865a6437825f5ede3209", - "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48", - "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046", - "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632", - "sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a", - "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2", - "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1", - "sha256:ddf4af30b417d9fe16481e9b81c27ab2a7cde1ff7ba3e85653b02db7d145dc7b", - "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990", - "sha256:df7276909358e5635ae203673ab7e509ddd224225a8d6b0790bf13eb2bde1cc5", - "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b", - "sha256:e9701d0049d92c16703a42771b98d560b95248949f23f8cf7b4eddd201814fb9", - "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534", - "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81", - "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a", - "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d", - "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf", - "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115" + "sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e", + "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", + "sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5", + "sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56", + "sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26", + "sha256:0891b9d3903c5571c03771ca669a4b0ec5618ca722a5c957d3d29cd4e5062848", + "sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718", + "sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93", + "sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640", + "sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3", + "sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875", + "sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e", + "sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275", + "sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204", + "sha256:15bb4005af6320d259dc7593ca84a38d7fe06a421dbcf7b910ae23979101e787", + "sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234", + "sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3", + "sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98", + "sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3", + "sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187", + "sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d", + "sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f", + "sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7", + "sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011", + "sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f", + "sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869", + "sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1", + "sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d", + "sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847", + "sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320", + "sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9", + "sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93", + "sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd", + "sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00", + "sha256:2cc961b171b3f3440f410489ab3573e86aea8736134ebbb40ea1338b7f0831bc", + "sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0", + "sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09", + "sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac", + "sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621", + "sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c", + "sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8", + "sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a", + "sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51", + "sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0", + "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", + "sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa", + "sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6", + "sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649", + "sha256:3ddacd27458c45bdacd6bd6db644bfb730efbf9e830310186e3045c9c5be8fb2", + "sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229", + "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", + "sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd", + "sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115", + "sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9", + "sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c", + "sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c", + "sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab", + "sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253", + "sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995", + "sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438", + "sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0", + "sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be", + "sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b", + "sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7", + "sha256:55ea99acb17b9325618de155a0cd6a2e8f5d10be008113e1d433bbb58db543b2", + "sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a", + "sha256:588461c2e8384d309bd63e5826019b6977bc66d629b99ac8737bb795d7b2cb5a", + "sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a", + "sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c", + "sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5", + "sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37", + "sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e", + "sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4", + "sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800", + "sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055", + "sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e", + "sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5", + "sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c", + "sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b", + "sha256:68eb192d85ab8e5f6ec69c2bc6ac0179fbf04a5ac1569d12fbef74883fe102d0", + "sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80", + "sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a", + "sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4", + "sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2", + "sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58", + "sha256:75a3ceed0724d625d64b86ca20aba182e4df462e04c2414fc941c0f523f06aac", + "sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc", + "sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639", + "sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf", + "sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d", + "sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f", + "sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c", + "sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc", + "sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4", + "sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253", + "sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade", + "sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858", + "sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26", + "sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96", + "sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8", + "sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249", + "sha256:8b2bfab86aa71ae13aa41a6a26aab338e0db2b8bc75434b05aea89e011ff35a4", + "sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13", + "sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1", + "sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03", + "sha256:93223adc95033dd47133a46ccfc316a0139176fd79085762e27202ec56018f03", + "sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e", + "sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364", + "sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4", + "sha256:9bde855991b7e362c146535e3136a50bfaffc0487d38b33ca7e5edefc6e23849", + "sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0", + "sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a", + "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", + "sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3", + "sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21", + "sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3", + "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", + "sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413", + "sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21", + "sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346", + "sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429", + "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", + "sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45", + "sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f", + "sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c", + "sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d", + "sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad", + "sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400", + "sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb", + "sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c", + "sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc", + "sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c", + "sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74", + "sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf", + "sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604", + "sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f", + "sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105", + "sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a", + "sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d", + "sha256:d4a7319f304a774bed22115bc891618e45f85065ab44ea6acd07d274e750519a", + "sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1", + "sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5", + "sha256:d913de495d90407cd859d263bee2e5d1a4ed3eb6573c04e70d9ec619a7cbed7f", + "sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e", + "sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709", + "sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874", + "sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5", + "sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc", + "sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95", + "sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd", + "sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0", + "sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d", + "sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3", + "sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c", + "sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3", + "sha256:e80e6c2f55656b4824d72065abb4ddd6a525c74bd78a0aab5d9fc2cf4fb5af50", + "sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491", + "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", + "sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5", + "sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655", + "sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288", + "sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd", + "sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084", + "sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d", + "sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4", + "sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915", + "sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1", + "sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd", + "sha256:fc14a032f813bf5fe624d991960ea83e9715adc27e4c1830a2361eb1d02ac341", + "sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424", + "sha256:fd1fbe0f116b6e55da77aca2c6ddcddcfac2186cbf78bdebf40fc156efca389d", + "sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f" ], "markers": "python_version >= '3.7'", - "version": "==3.4.9" + "version": "==3.5.2" }, "cryptography": { "hashes": [ - "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03", - "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7", - "sha256:07479a1cb08219ab719147e742e76090c9c773321959bb94946fffdd397a6437", - "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987", - "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025", - "sha256:11b74db56cdbe3cdee6e3f6982ecb70334fa10dce99ed58bf7894aaaa3b2a037", - "sha256:12b9c6996425c76ea6c457ace4f3073e715b8c545add07cd1a8f3a4f90691269", - "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105", - "sha256:19736989797678c6af1e55cd49055cdbcb55d8f6b5583ac5335f933aba9101dc", - "sha256:1b4a266766514614f8aa60416e71f2fc6e575d36e7bdc90f644fadb2f4b75b95", - "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b", - "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47", - "sha256:3f5735ffe4996d28b809371756219f5354864902a3b9e7c0b9ee87041209fc9c", - "sha256:49e7d93abdbd2990caced757e5fade25302f719c3c8fb6e6fff2dde98999fc41", - "sha256:5e34edd123674534acd70147f0ca331eaa2c74e6325fb2028c886aa26ba0b68c", - "sha256:62598a8a57f815db4c6259a4e97d857dab56697e7de8e8ab02352ab74da1995d", - "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7", - "sha256:6ba6a53445bd3cfa809ef3ef5f1589aa6ba08784a1d962bf47d0940e871dab1c", - "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708", - "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef", - "sha256:80b63928fa35083b33966ce1efb70e5b9607181e49dcd1c22c8c005e319f667f", - "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f", - "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a", - "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f", - "sha256:8eb5e1172eb569ea8a872796576e6a67c276351728b6455d5beb01242b027c6a", - "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a", - "sha256:910d11e1a385c654bf738bf3e6b8e6ed5de0f5610fcae2be9e5b398d8081d20e", - "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3", - "sha256:9aa87839c383bdbab6ef865787a1fb877af8dd03464c4400322726feaaadfc6d", - "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3", - "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f", - "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae", - "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30", - "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9", - "sha256:c99c003e088647b8a5b7c145d6f78c335f6348332b62e142d411c4b63d1460b9", - "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07", - "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba", - "sha256:d58c3db7cd6eed54e6c06744db55456b65ebd7492ddeae9c1e93cfca7aa857d3", - "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f", - "sha256:df2a58a472f332225671c35b0a830208b86d004f82baa8530fa3782c85646533", - "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5", - "sha256:ecfed7367f965a0328cfbdd70da860f15441f002f613185668c6e6ebf5a0ac11", - "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9", - "sha256:f59e38625469987d7ef6d495323c55e7db6c212eaf6112267e0d3b565a2e9c9f", - "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169", - "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645" + "sha256:0ddc924c04591c2811ca024d62ecad4f7f6f08af8939c211438f48a16bd23602", + "sha256:0ec5f09541743261e66e291b4a0cbf0fb2997aeaab6d9e9c740b9dba1b58d1c2", + "sha256:0ecbc5652bdb6fc9eaf89a7d196e20941adfe812f43bc4ca05d9150496821047", + "sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c", + "sha256:1ba34f04897fcdaa73f74145c25f3ec146fbd56593853e88adc2e811303c5f42", + "sha256:241449bf940a5d27309bd317e6f9a2af6932113818bb2b8f5c59ddc7ef16da18", + "sha256:25784ce8b9621c90c643efb9e1e2162ab3b0224cae446ad5e70e7fcb1ce18b51", + "sha256:3dc4fd8058cea1644971207d530e1a03a184a805ffc8ebdddf0599d78a331b81", + "sha256:4061c0079120205fb760c58acab6443e217307dcf05e3702cf970e0689972856", + "sha256:4a20ce1e5cb4284a86692fdcba7cb8754185c6b2e5c56fcef3751cf451d3cdc2", + "sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de", + "sha256:58a0c478eeca76fe5e07993c5a0703def34a6dc6a0cda4f5564639b33112ffe7", + "sha256:58ddb5a8e3179d12f19e4ea34d2d32e9d63a4baa142c875c1eb59f41b7243acd", + "sha256:630ebfea3bf689d075f82316324ff7433dc447fe6bc1bfc76524b74b4a9567d2", + "sha256:6f8700550aa1474a91e5dc07049c46f98b423b5b1ddd0483e0b51362eeeaf5be", + "sha256:78198641e5be9521beea5aa782bb551a58068d10e6eb04c9c680c1b69f2e7d45", + "sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0", + "sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e", + "sha256:7afa5a6602a9f29af1f3a2965f831bae7c9d5d597b7cbb716d41ab3b7d89879c", + "sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5", + "sha256:7b75de3c8b3be1cdb1052747c929440c3eea46c1bc2cb8a6e3a48388e9b7b452", + "sha256:7c6d0330c472d96f6a6afe24d80dfdf15176c33096f0a4397ae4c60f3dd3be48", + "sha256:828d49b0ff5a0e3975865571c5d91dbbdd0d38d8289b249a163e9425413a5e05", + "sha256:84f964e537f916e2cc85199e5a88742e964939b575ac8598b3f9d6cc416cdaf1", + "sha256:85d0d9a31b9098e98534226d5686b47264b95e62ce459dc2e62fdfc809f9fe93", + "sha256:87e9ce85beb6b328ba370cc6e6aea483c92617b4c95b1d33a49297eb662bfb04", + "sha256:8c71ba2cd31fc93748c38e1b613200ff1c2665cbfd5341fe3a61cfde35a1430e", + "sha256:92e665960f25fcdc73725b9cec7a3824f279ba97a98653afe9ffac2e43668f67", + "sha256:94e5e9f108ee10471288214d3d233fbfbb492840a8457eb85178d643ddeb32c7", + "sha256:9c8402a82ea0dc4ceeab793db05f0fafa8ca139ca34fcde5df0f596103c74107", + "sha256:9dab55f57c74c3cad24c323bacbbd04be4705ba6eb0d92e920b1fc4837ed5079", + "sha256:a582ab2ae1d34f67112cadc86702774c9ea4374df6bca6afe672817203c99134", + "sha256:a6557e5f38e065ca9fbdaf7cfc7435ecb1d113aa81a022d1b51921ee7432e227", + "sha256:a9f7355e6fab51f6c369b86fb7571cffa05edee2c2121e0380a37fb9ac1cd5c1", + "sha256:ab50ee449bf968271e820086f10a33d101dd060370abc10bcd22279be2656539", + "sha256:ac9ed99d81760c62fe89d5f0815cdfa1ba9a35141cf30f1c2d044f04b4803d2e", + "sha256:b13478603dcd0a2479ff8e87e2c19a7d525734686fe3c49542472293a204212d", + "sha256:c423ab384a46c4dff7217b2ea5ba2e11cffdeab6441acd04cf65a369caf0366c", + "sha256:c5e67125c7dca78d199ec4e116aa93dbb83494808ecbb8211a2cb09b1bf41dbd", + "sha256:c71be1cbfa5cd9a41ee452acf1eccd82b2c05950358b106ec8ceb83411d1a020", + "sha256:cbc8738fd8526d80f35cb3a40d41f41a2e7030bb3b18b09a6778ef63d291c2fd", + "sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94", + "sha256:d370b8d1dfcdf7130178137f6fbee6140774a1acc6cacefc4b42643ec11d0a3a", + "sha256:d38cdff612d06fa6a32840d5e1b1f7a27cee4a349aa9085d94a67789d6bfd408", + "sha256:d8947001be83df1394050758ce0e745dd74fb134eef0a4b5124208dfc3a68c37", + "sha256:deb9fde5c60e437ee4821bc9bc39ff31b42135c27e1dc61ef0a629389c1de62e", + "sha256:dfe9763530994147d9af1def057a5b9658b00e8f8fe8743d144d1e0911c2e454", + "sha256:e105ab60406787da31fccc883fc0f733af1efd78f0136a4599692c4083a73d0c", + "sha256:e275096ea1e60cc595cda2836fd4a6c725d1125108b868be17f53684d164e2cc", + "sha256:edc3342adf8f697fc5f59c887a304356f147b397809440ed64e2fa6af2f50f37", + "sha256:ee247f5c245c9a2fe7c8e2214e295918838e44e00a45a6718451e4004219e767", + "sha256:eef4c2f3423810b3070ab391f85436d2f8bbfcb286ac15cbc73190b3563b1f1a", + "sha256:f21e8a22c8605750c7af886bab299a363721264061b4ac0a30efb73cfd58efc5", + "sha256:f265528741e048bce55c3463ed721fb0aa45a5888d8add8cfeccb3035451bbdc", + "sha256:f2f9bd7f90c64fe89253f0a2c05e3c4856072660429ce8831b4235bf29403a67", + "sha256:f785f6161f202ab04d8ca194158968798e480ca058943907972da5f12e2881e8", + "sha256:f9f6143a8c75945eb960d9eb98905a441394abfa24afaae239d514ffb2586480", + "sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb", + "sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b" ], "markers": "python_version >= '3.9' and python_full_version not in '3.9.0, 3.9.1'", - "version": "==50.0.0" + "version": "==50.0.2" }, "deprecated": { "hashes": [ @@ -315,11 +407,11 @@ }, "googleapis-common-protos": { "hashes": [ - "sha256:28a1934bcd33b9c9da66ac301a0a4227e3367f095a17d0375cb98f0a09d93b79", - "sha256:d3042c6c5a2d4e67113104d6b6818b59b6bd92a197f2a91508e801fe815cf071" + "sha256:c7a866fc34ed29a3b10af627a4b9b1dc2433313ca6e959f0ae4feb132047ed72", + "sha256:d7285525c23039db98f2463e6d5a4f9b958b94d497f03a844ece3259c4e72d5d" ], "markers": "python_version >= '3.10'", - "version": "==1.75.1" + "version": "==1.75.5" }, "h11": { "hashes": [ @@ -347,11 +439,11 @@ }, "idna": { "hashes": [ - "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", - "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848" + "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", + "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c" ], "markers": "python_version >= '3.9'", - "version": "==3.18" + "version": "==3.20" }, "nest-asyncio": { "hashes": [ @@ -363,99 +455,118 @@ }, "opentelemetry-api": { "hashes": [ - "sha256:67647e5e9566edcf421166fdf022b3537f818635daa852b289e34604dc6fb33a", - "sha256:94b98c893a91b88657eaac1e3ba89618cdb85be6918196705354f34728b2cdef" + "sha256:711ede81773c8025c2c03dac0450bc89f3d30aea6eabcc815c570d4e35a963f7", + "sha256:80e068aba7cd56c8b58512d6a36f8d25cb1dfaa0c0a4cc1c938ccf9f362d9cb3" + ], + "markers": "python_version >= '3.10'", + "version": "==1.45.0" + }, + "opentelemetry-exporter-http-transport": { + "extras": [ + "urllib3" + ], + "hashes": [ + "sha256:2c229b6593eaa22c86d9b8a15843dc23b406dbda00fb138339189aab07923b4e", + "sha256:c82689928a11505a2a0a26a04afe0ce06d270d3db984bc16c1a80ffa902db00e" + ], + "markers": "python_version >= '3.10'", + "version": "==0.66b0" + }, + "opentelemetry-exporter-otlp-common": { + "hashes": [ + "sha256:35d24c867310f4713a9738b0202b6bade77955418fccb9e2f7eea01b76263916", + "sha256:362268ec6aa705e183776ff938539df1e8ce45bc5509d242538b1d40c26fe6a6" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==0.66b0" }, "opentelemetry-exporter-otlp-proto-common": { "hashes": [ - "sha256:9a9fe61bba73d802904bc989f1d6b4a7b1ee40f06c40e98d6f85af65aaebb694", - "sha256:dc87a5a5bc58f149a56d1547e4691588fa12994cdc3bc039a694ccb3375862ac" + "sha256:36495115a0c6a7aa946cfda9d59b6ed4e917b6ab0f75cdaf66bc1b176ec1be1f", + "sha256:7e1410ae6d3ed301f7a74bec96467d519d3f37e52f9d95b309ae125e5a1af863" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==1.45.0" }, "opentelemetry-exporter-otlp-proto-http": { "hashes": [ - "sha256:838592fce774c1c8bb7b9a0a7facbfa82e17be5a8a4e94cef10cb84ae026bae3", - "sha256:c633d7270ad6b57cd4cfbe8b0007a9e2e7c0cb50bd6c50fe2a7b245f721a09d8" + "sha256:2f35496d96809f946f41b8805e6b93aec6c9b71b5fd759b75b6af4c084d992ae", + "sha256:74385f99266dafdefff41f3da4b76f6dba79d237a9d4487e6ff1ee653c74a0a3" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==1.45.0" }, "opentelemetry-instrumentation": { "hashes": [ - "sha256:071d9d9eced9bd6460444ec3b0c77229870ed05a881c22c84fdede58e4eed09b", - "sha256:ea967a72b9939b5fcfdad572753b4306c59dcb99e3f382d95dae04286805e137" + "sha256:0b32e2fcfec1e4bd48511a3b77ce32bfb1c16dcd5479396b21f9086a4b06c0c9", + "sha256:316715ed7b33a12530c0ae3e8d4cdf26d70e1aad358d7ba256e5dea2d4ceed71" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-instrumentation-httpx": { "hashes": [ - "sha256:400f1b78afa4ee2332b5debe58e1ed1b317913d58812c952576be76660aeadb1", - "sha256:4627aa9c6bb99bf4462c8b565b0ef6aeb9ffad95c6c92868be1ef7895de112ee" + "sha256:2735d1868749ca04ce47a3802b0b809e3a00c05a65140e05bac5700e74410539", + "sha256:c89297975f54d67692d3c29e9e33a1bdac47710031cc3ed0d83a0c9765336981" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-instrumentation-requests": { "hashes": [ - "sha256:1d601548f89236d5ab373c7208a2e1e162a8d6462b5b972f9ad8fb0ed82d7438", - "sha256:91688ec0d4d1fed75ea8d026ef2c66274ed9868c22b6be211ef85d832d16f957" + "sha256:053dde08fbc1d223058e33d477cf81e2bdcbe7af3893787283339b2b557d4b7a", + "sha256:2f9df08bf99f5da4bcfda70735492b4364bfcc5bd3f48232658e936f97ee1a22" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-instrumentation-threading": { "hashes": [ - "sha256:aefd23eb16c5e7a7c6c6eacdcb6c6f269ed8ed3a1b458bf5dd555b878bf58937", - "sha256:d8a1a1f35418a32769d469ef2d7e8401935e097a8553abcfba833da9c74736ce" + "sha256:4aaf38b96b47a04319b8d96bee4f1daa04e0d6c697525595746aeb61618c002d", + "sha256:4c1c9adf42b83b6f44ca4bb99799e066ccfb1869c2029bc73d862c40a8ef932e" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-instrumentation-urllib": { "hashes": [ - "sha256:8e7d1ada475296136815763bdabe683460969d09d93752c4f11ef0175598151c", - "sha256:df1b79e50d6d59f4248acc659bbed0ada8ccc8a028ee915d3fdeaf9140672b87" + "sha256:3eb6d2b9b28bb51188d77092a58eac2ab04852d244acb51333bdf42b0e933c68", + "sha256:a919d8014dcf0065ad42ce5c78dd158c76c7342929f451d726462f7ffa68e367" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-proto": { "hashes": [ - "sha256:898b155a0e1557afd867478fb6158e8122a46329ca0bb8dc53cc55e98f017f56", - "sha256:c547a79c2f8c0c515d31509154682e5921c7cfd5ca67b70e1f9266e2c3e103f3" + "sha256:96ee414f24bc3f61ea8e17dc56b4348d4049d73db3eb17c6b3edf75b5b403300", + "sha256:9731566359d7b8e1ee1e149d8e4ad6865bab965e657ad3387ec2784d16927666" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==1.45.0" }, "opentelemetry-sdk": { "hashes": [ - "sha256:cebe7f65dc12f26ead75c6064de12fd2a9052e5060c0272d402cfa203aae123b", - "sha256:df081c4c6bcfdb1211e3e86140376792643128a25f8d72d1d27675936e7e96ad" + "sha256:20caa5130505e386c67c3da1c76e446c842698ced54c76c6148679539aa97972", + "sha256:5dc634c946546f61b757c5b1781f9fd1a10e96ffaf7357c797e508fe9c57e75e" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==1.45.0" }, "opentelemetry-semantic-conventions": { "hashes": [ - "sha256:1cacde7b0ad306f84c5ef08c3dbe1bbaf20165bba6f8bff43b670e555a086bcb", - "sha256:f9b2b81e9d5b64f11bc952075e7e9c7fb0aab075c7fd1c46d597f1b919852d60" + "sha256:175b19dd98c4473f4f43a2b1df59186fd7b4a48cd3f77cbe03438b6d6fda230a", + "sha256:97a77dce484c54861e7eeff7651fd8a806dd3c30e501dc316730215ec36890e6" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-util-http": { "hashes": [ - "sha256:7553b606f963097cb190536dc30556cce85090692e471a422fff30ca29b04348", - "sha256:84f82d826978bba416ab453460ff6a7391cdc3534c93a786595e4068680016b7" + "sha256:7f5e581e94f023b30995f700e41ce319cec82bd542ff1c1c7c9b56d6b10bb687", + "sha256:a2d53859630abe8e5abcc4f867c5a809bb95873033573b1a67f6ef43b57a8627" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "packaging": { "hashes": [ @@ -467,17 +578,17 @@ }, "protobuf": { "hashes": [ - "sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799", - "sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87", - "sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6", - "sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30", - "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9", - "sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4", - "sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4", - "sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a" + "sha256:497d0463ff3316681da6c0b9e8d06cb465d61abce00b613ab42226175644d1bb", + "sha256:89f23aa53c24553a2416fd4fd1ec06f74fa42b14b546d8883128813f775bbfd2", + "sha256:912c1221170e16c08d1f086762f563dd61ff83c18b5fa6652952dfaded66f728", + "sha256:a300819d441e078a5608c0d3c709796bb548136058fda017ae51d425b44fd353", + "sha256:bdb3a345d48db958e6ce1f18e508beb0cc981d64f24088427549c866cd039f1e", + "sha256:cbc70b17ee27e28894c7fee8bb04be1abead49e936bc70eb60052531eee2079e", + "sha256:e11e1f0180583a2af89db6a2ecd9e8dc40aa6d2988ca175bfd0e6d12ea72d74e", + "sha256:f4fee11ec330d238b34a05c9b675f693c20415d1c5bd7d5320cc2f8a798eb9cf" ], "markers": "python_version >= '3.10'", - "version": "==7.35.1" + "version": "==7.36.2" }, "psutil": { "hashes": [ @@ -511,7 +622,7 @@ "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992" ], - "markers": "python_version >= '3.10'", + "markers": "implementation_name != 'PyPy'", "version": "==3.0" }, "requests": { @@ -536,11 +647,11 @@ }, "tqdm": { "hashes": [ - "sha256:55b0b0dbd97462d06ebee91e4dac24ed4d4702be82b24f07e6c1d27e08cea220", - "sha256:7f585706bfddbdebf89daac705b2dfcc16890130727d3197ca62c732b4310953" + "sha256:c293e525e6fef9c20e8728fd4612df02a0aa31bb5fe91ecd93e123b1b7bffa73", + "sha256:cefd0eca11b2a37a3aee776544d4f4ae913f02688135b5556b8788dfa474afc4" ], "markers": "python_version >= '3.8'", - "version": "==4.70.0" + "version": "==4.70.1" }, "typing-extensions": { "hashes": [ @@ -552,117 +663,128 @@ }, "urllib3": { "hashes": [ - "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", - "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" + "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", + "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63" ], "markers": "python_version >= '3.10'", - "version": "==2.7.0" + "version": "==2.8.0" }, "wrapt": { "hashes": [ - "sha256:0a45ffae742ce91a16e11cb6c7cd71e7f9994f3cbd283b962ab093f5c6dcf525", - "sha256:0bb2797048db0956348cb3058c33bc4184614f13231389cfbccc16a5d32780a7", - "sha256:0d3fb71e65b001adfc42684522eeccd9c21d8ba679945abc993439567b66e59f", - "sha256:0db083387d6e75ec0be8173ecbf0e811cf60bae1cc75a815feb104167ea10d4d", - "sha256:10461884b3014fbfc8eb7d09a93c5f246363e6711d9d881f95eb8c27fdef049f", - "sha256:1236fa25173ca964c97422470482e9011b9e3c7ed0d75798b40b3da3b0e0e760", - "sha256:141ed6211286a9660d8d6702de598b43f0934b4f0eda16393f100a80f501d945", - "sha256:1598becd30f8f2777d18564064eb4f4dbe1ab0e05a8f09786d0ef505ac782bf3", - "sha256:195b1842b4122fb54e3cd3dd5b2b4aa49302a5a61da901df0481f5c97aedde84", - "sha256:1d6159c9b2fefec02314e1332dbbbfaf960e369dfd26bcf7f8b258b5732065b3", - "sha256:22cc5c0a717bd4da87018ae0bffd4c19c6fb679d3ff357216ba566ab26c76cab", - "sha256:242b60c21e30866e6a2fa606c612b47c553fa60c0eaeeeb7797fb842ac0ce609", - "sha256:24da48596326ef8e448cfa837b454f638713d3531262375f00e5a9681682fc07", - "sha256:261f53870cd4fb2bf38f9f972c56c728fd224cb7c65721307de59d9e7e6741ae", - "sha256:2935d5454b3f179a29b12cf390ee47246740ba2c3a7545b1b46ba31a5f2a4a0b", - "sha256:2e49885a62ec4ee854d1b9e6371fda6afd219917225752abf729a3f36d4df9a5", - "sha256:379f670f45b7bb8993edd9f6fc36c6cc65edb81cffa0b504be34acb0303fff0a", - "sha256:3873c3c5ca9f4ef91f693602eca19d1f1e7c410338df82a4ff11d826b5896a8f", - "sha256:392158c9a7f2ab1b8699418bfc0fe6f83548788c418b27d7bf2019ad3405cebb", - "sha256:39febbee6d77301d31da6996b152ce52452da7c7ef72aba10c2fa976dff9c295", - "sha256:3d1c2c1b808600d2ea808e6360910a60ed5f409a4011655e10f9164ba0a414a6", - "sha256:3da470536bf9645143323dd41b32db55c6f4304ad382094c1a1da8a92061e10d", - "sha256:418f54bb09d1762db02c7009b4051149893af3153a87f92d70356703c11eea02", - "sha256:42869085687f0aefd57c0f636c3f9354f8ffb321a8ba9cb52d19beb796e561c5", - "sha256:45c9279b373d15649dfa2c2077cb3408ea1a6d3125afbdab9d6b809a66f68e14", - "sha256:4fa0df3bff4e7ce45759f33fd39335fe2f60477bb9ecf7b8aa41e7d07ee36a23", - "sha256:50f416b74d092bb9f41b424e90dd457f365f7ba4b11de62a23679769a21bd85c", - "sha256:51a7a4181c1295774812271fbcd7c909df372bc25579d4ed9eb875caaf0ae86f", - "sha256:54ca1d5573f69b5fe1d74f1f65799c68015e82f685efec9fd8cfa40a094c44d0", - "sha256:5ab559e1b2551d23d54db2a0001c6d73bad022a254639561c5f6c382a9d6c2fe", - "sha256:5ba1e5e08ddc46130e9682b2c249f2d1dd39bda9106ed4bd401b7519f18f41bd", - "sha256:5d221a6e6ddd302b8397433184e96b59f259f50024b854db1c411a881586b6b8", - "sha256:6208f302f110295d64b22a7ac96500c791bf492dce4366e622e4912b077c9687", - "sha256:626b69db2021aa01671ec7bbc9740e558522bd44c18cf2ce69bf3d666a014109", - "sha256:628f3ba8ec793a5b10a6cd8c6c6b7b55eb552abd1f3bd301336acb74c7a82dfe", - "sha256:629d73378082c00a8173031f9fb30a3ac6abbc894a5bfdfae71fabc60642d501", - "sha256:646d20d413ffcd1b0a2f700076e2d0252d872dcb7754860a73e45a59ea883614", - "sha256:67bfe2485f50368c3fcd2275fc1fd100e350d601e0058921a7c82678a465aeab", - "sha256:681a2d0eefd721998f90642762b8e75c2159ec531b20ad5e437245ea7b06a107", - "sha256:69e477046f2237ef0bc6547544ee73008dc764ca26eff44f09e976d221b34d5d", - "sha256:6db604ef0c67bdb2042ecdfd7b7f037cf09733557ca42360d1018285634f7b98", - "sha256:729126e667da34d251b8ebf8a45ef0c5ddadc21542b3d6e1abf4259ece6508df", - "sha256:73d0b10b64620a2cf4bc3d31775c4d9527e309a5549e4379e3bf71e8d2dc193e", - "sha256:7ebb274aba688b043429eb1500ff8a76ce0cb8ac0812ca3e301f06247b8722b3", - "sha256:8159ec0b0cb7608175eb150de94c19e34f4d47ac655f5ca9baf45df6b688ffd3", - "sha256:816877aa749253149f9ecfd2635d4d948ecfa338e1a0311d187b1acb1bb8a3eb", - "sha256:85de890ff968196e92dd1ae73a9fb8970495e7650a457b1c9ef0ac3dd550bce2", - "sha256:8f8a1c6472675956cece9a8f403f43c3594f1681319eed2dd56f60877397c636", - "sha256:9045917809c63fdf7abe3a2ceaed3d670b8ee4500ddd9291192d30aeb34467c5", - "sha256:932dced0a7b2950ed58a3325536a1dcb7b58e7330af54e8552d2e566b5328b99", - "sha256:93513bec052c6cd987f9f580c3df068c8bc4ebae6543736be3ca7ec5959cafcd", - "sha256:9790ea25190a4e0fe4cdf4eeb868e9d75f8a024a70a5b6bf9c348a3a2b72e731", - "sha256:9f5d2aec29dfc76c37e23897dee92766a3fd4f3bff3ae7fc9c6b4bf37d8c1360", - "sha256:a65e8db2b4e90c2e7ade931086351c98ef420bf7a94ee08c95ac8a3cbbc43579", - "sha256:a6b5984cd65dd639546f0eb4b8eacf1c31cb2fe9fb5c27bffe240987cdb2cf84", - "sha256:a6e19531ae33c508cea7d84a7edfda01fa86e51b8d1a93a77712c55e6e469152", - "sha256:abc71504669d126d91f89fc0e388c6295d8fbd2439be884f175133fda8aa403c", - "sha256:ac870cc97b73bb00ac353329e9559a4bebc47c4c86792ed9b23b58c15b6ad838", - "sha256:ad71df7a04dd3497e9302e81f4a7c91bd401ea0e15a9df9029527900f94bee43", - "sha256:b1e5aa486e269b00ed35e64771c7d0ab8096cfd2643405ca8cd60ebedc099a51", - "sha256:b4fc96b159af0a3e0faa72475a69d66292bea72a5bed1e1aca1bffbddc3cb2b0", - "sha256:b767a9566f165dd14decf8f4194c6bb0ce3a8420cec213824e05a99400c9260a", - "sha256:bff9a671bc00709cab5a7f745c592b5671873449db0ee2a569af994f16b29a4d", - "sha256:c3b476ae63b4a3b4da681aafcb25ff3542d289fbda8b5da7caf76aaffafafdbb", - "sha256:c4bded758ad6f03b965830944a2f0bc5b2eb3767fe5a7310134315d1a6610e98", - "sha256:c8388ba7faf5dbf9ee106bb70d66f257629b1bd98091123e19e8a4553a319199", - "sha256:c8858d8ff9822a081e3cc49ae1b3b22f0f789c14001cdac8f94564010d9c9d66", - "sha256:c88abcf53daef80e01a75c7530e727fa6e2c1888fe83e3dcdba4c96216a1f5c7", - "sha256:cc2cea812e5cb179a796b766747e7d3b21088760d8deb95676d482b8c8e6fa7d", - "sha256:cd3a2edf0427013736b8127955cec62608c56e53ea47e82812ea32059cda407f", - "sha256:cdc021cb0b62471d6aac7f2bd92f3b4658073775f9ee7fcd325c511129e7bcc8", - "sha256:ce9f398f868d2b3b27aa2ea4de79645ef9077aeeac8dfc2814b0d542c6a2b87f", - "sha256:d0077f3d65541925fa83002f967b22ad6550d24813ac64cb905f717194128d9c", - "sha256:d0f7284f88f4833705132d06d3b425a43095c2cbd07c58166aac3ab646ba12a4", - "sha256:d2cc64539da63e39ffb9c7ede849b6e8ddaaf7b3876b5cfb04efd85a5f3f4eb6", - "sha256:d8c7ed08477429752b8c44991f40ad7838b18332a160698740a6bfbc10d998a2", - "sha256:df4ce31150bcd5d9f36f816aac3010ab4f4bf8672ac1d3b0ac7d539ec61c7c02", - "sha256:e045ff75d7d94900fc32896ed93c45ce2d2cac28c9dead582ff9a5a49d446e35", - "sha256:e2e692bc0d63f881cf7006730a56bd4e0c2fab5dc318466942805d692b166276", - "sha256:e31734c5077f29f892b2565eee5106d610278151ad49fc6a9d69a647cd5730e2", - "sha256:e3b9eaa742ae7a0aaaaad4ca4b69469d757af2d6e6663ef1dadc47adec0aeb41", - "sha256:e3f3d7ec0a51fbfe00d3aef047641ff2c58b25565b4717fc1f90e050be01cba8", - "sha256:e5301c35cf75655eb33498f2bd6ae8703ca19940e3167dc9cdf740c712a39c60", - "sha256:ea52a0d0f08c584943d5764be0e84efa912c8da23c23e1e285ff2f5641c18fcc", - "sha256:ed635a9ca4f3a5a2b900c10c69e823373bc00ebc114b459383596d3487da3570", - "sha256:fb8e2e6704a1e0b1b989546c69e2688371ef4a07fa5f61bde3eb6211186f5ac1", - "sha256:fc648a335d7e01adb3640b25f02fd0ea05886cf04d0af7f4ee902bc7b5e466e8", - "sha256:fc82c2ccc8e234c844f5303d9f2984b346dcdd53e94823ce8420d2c75b4b9023", - "sha256:fd1f2f557dd3491fe75905e578f4db967393d40d1a8f468edc4d40ac7f2d5944", - "sha256:fd85b0aa88efdb189d6ae2f35f4526943a8f091c38599c9c31478241c819e6a1" + "sha256:05246a100da68259af521b88788f131ba005465f1c95d358cc3c03ec5e351b52", + "sha256:05b7a271e21598694dcb7a6d6224f04e80ecc24b00a31ec57c658196377b0b29", + "sha256:0810e060e58f7960405172ad21080df8e7335841c9fe97417bd7d3f05af24f90", + "sha256:0a7a369e7fca9fc8c2c50df634382009b09af416853da3d4515e4bb048a5b9ee", + "sha256:0cabb9c17ab79b2549d1f23b36f436473ad9253ef53995a817feba26fae69d5b", + "sha256:0d245ac03f5ae77f1eea6eb19edd9e778c2f772490c20496c2f1cd3a102ee1b6", + "sha256:0dfc38cb672af51fc29696ba9c6f05d2315f5e62c4af2564e50f07f81198a163", + "sha256:0ea62bc142f4fa8b2e0ab058f50699ccd679ef6199c8fa3cc1c2396c7a659000", + "sha256:107eea1a511e98a3a5033b0c2cb403fbb37f05dee6ac1fb85c0460d311ec278c", + "sha256:1122f4f9e363da804ccba05a9f0f39baa3716eb82452c929258bc3f1420c899b", + "sha256:148052fc55013930217f531c6978e918ab210a12bd73cc9bd6de661a7adaf620", + "sha256:181a45000506a6382eb337354ca7e8525690702f1ccf2eae4f23a210ff339543", + "sha256:18baaf966bdc22dbdbe6e4323da8c17c0b7e8ea941dccf5426e741ae398953d9", + "sha256:1a3c4035d2026b87ef23dd8d165f1f8d3853ee2bd02791cfd22bd8c6226c41ce", + "sha256:1b35ef7379323a149a6398f6261248bf48b61666210bd69e2ab24a9a9afdedc0", + "sha256:1ccd22ef8690ca302425f26d4c3e8b24f1284d4351d20e49ce21f9c0dd58d64d", + "sha256:1d4da5f0e9a719471502b0db80d5c97503aeca796b7aeb9ab8f47403b2be76e6", + "sha256:1ebc0d09906057ada57a32158a657364ca40b8f86e604da3e7d979069b601502", + "sha256:1f17c5a3836397bf59fd57b0e5b0dc42969b1daa70d31aa361c6e13cbf138b5a", + "sha256:1ffb2823c95dbeb8a47fedfba9636b2afeb0a8ef94b66df97bd081bdfe5a263f", + "sha256:21cfe343ef9c2deb865ad0d5c57822266447c88dcf6d8805dd8c363fe367f30c", + "sha256:23a9d6cb6413359b76f030d6bbb75340b7669c69da245dde2919a4c93708993b", + "sha256:2ac82ef59ee05e259902bc7cf73dee5e6397845e8ccdc376d9d25536b59a877c", + "sha256:2e3d110d7f99644946f249927c346d9dba507a78815d1bcebdbf0d94c14c5649", + "sha256:2fd8a61c31220840c7f52621cf51c961af5058bd009a55bcdf4a6732bdb13b35", + "sha256:30cf86d1e35a57e772e4709a137c1731751255439368a41b1a2519561e385f4e", + "sha256:36703cafc2ec059e118c2175e6cb7ad7299c2924aecdcb1b7a7ebbf7a3e20c19", + "sha256:3f5dfb867d3f58fde0d850a302f1164bb83f4a922b037882bcc7e0474aa8312f", + "sha256:425349a99b8c9540399d36620c376dc26e6aca93071cd6fafa239c2f1b5d53a4", + "sha256:4343880acd72e74233baf092285aaaf4306244e31d7601828bd2600316027df0", + "sha256:439523506fd0d9af4f76d75f2e46aa4979e164fecba6890859326ff06edbaf9c", + "sha256:47abb2bb7f15b416e72fbe5e68e49a6f09331dae6af1ca6055f5aa2251d2bd2f", + "sha256:513dd1f4a1f91030d5656d9f4b3af8aa490d4db1eb53481e6846b8a5ee7acfcd", + "sha256:5375ff1d2159e2ef847449e3dd2329441423d0a3d895d123273a67095fe7ca0c", + "sha256:5421acb5c363a9bc959122a8645e3f1f42010c932dc53885b11a5ff5b5a6d730", + "sha256:557ebf4ce5568588368675014a2540405db687c2e4c7ad1eb83aa7e857be1864", + "sha256:57fa1a3fd1279b3ca7655b943ad61d298f2a2464a4cdca7ff298058e408322f9", + "sha256:58b2a87c65cbfb20917ec48ace47f71b1962c1f81dbf18a4052e3037abf72028", + "sha256:5df50c6133a63071fb77a0a091ceae36e78467b728d65e711ded02510edd9855", + "sha256:6058e12e9caa33468f9a36fb88c15a4bb30a479f997b37834b83abdbf062f264", + "sha256:6119e5d5bda268171af1f68ab5e7544c618f02a9bdc7c3929a458b719b88cd03", + "sha256:61253431e5a6f0eaeae71e2a101753fbaf4360b3e4dd8e118177d565ae119d40", + "sha256:6269637d9a54990430b4a769df15833935a46c4d004d9fe8a153bbadf0b9a097", + "sha256:63e58f96849f622ce769dcd705f83c7445cd9829bce1dae00e78bb031aec8096", + "sha256:65f2ee406dc592a5b22a7dc6abac13e8a3e8de4b2ecf5dc3c22937865496e4b6", + "sha256:672dd1bab4256311db1520b1b50e7a10cbaeaae2b0ac6bc5d858cc387ee605a2", + "sha256:6761765cc520ff9616fb035c02a85d1d744f7f70edd4649718fd0d09c589eacf", + "sha256:691671ea05684f921ffc2e935fd3f9311c1795a10fbbfa006b46269733668f66", + "sha256:6a31cc61ad1be4091f5b094c91d53d206609928af13b7b24573cb857a3bc07fc", + "sha256:6a9ee62a970075738909909bdbef3a7da9f7ae03dfca584db283547a29503b56", + "sha256:7138b0e7990e5555a905c519e8dad17c1da1f20e08b283e202c414229065740f", + "sha256:734ea79e4707751fb7cc4f716123b2115cd16ed0c4926e803540aece22e3ba67", + "sha256:76fb341d5a707a4f211631b8c77259b2df149147e9d9c245ae6ba3dd936bfdfb", + "sha256:77f0a74ff6f6cf89f5b673a732d5afe1911a6e6b1c017260836fdfdf85518dc1", + "sha256:78b7bdaa8b27b7f7607c66bdb6ab15c1dcbd9e9a1556a253a347dad511f615d1", + "sha256:79e68f0fd7d381b9bbd71776f602a2d5440d4d2077459128e02fd6607465422c", + "sha256:7e25e9697f60af41fb86b08697e470b1e7eb6cd6ac0eb25e4b1f519839adc271", + "sha256:7e2af7ff9553c492f684a41d903ec41e37bf6267ee3206c17518a349201cae46", + "sha256:8837fbe708cb9d8a2d32a37dee836d24a531f02560db26418e2b181986fa21cb", + "sha256:88bb24b9fdccb1d805258d5648533206eb58c58b6554985c47db53a89c11be85", + "sha256:94ebe745d1b0ebd3af91e22c38961616d32a228bdf9c326e7d4a6007a623d48e", + "sha256:99f8ea48f14a71c5e2df8763e9a490e8af63096dcd67755b7bab0a4b74fc7cd7", + "sha256:a039b009693b58f7e0cf6121851218c2227223e7601cc24ed4957ba0990fd25b", + "sha256:a10e9af5d4c5977d2d93e75d1662d076a8e8bf8c499dac7be4e78ebd8e0b59af", + "sha256:a145a7826eddea3eb5814903f98f93756042b919bb5305544cb1331daa2705b1", + "sha256:a346408f19b6d589bf029f25f65c0b4cdeed6302ef8f40da4e5d1552d22dc037", + "sha256:a45a5249a6965d91aac9f991fda7c17e6b8b41fe91592a6099f182bf53c82724", + "sha256:a5bb346a34499e091e4fa23df58251ad192173c088e5413d893ca1c730c133c7", + "sha256:aae2f5f4c77335a39ebe5a1c77d5519f6cefefc7dbff50bd551e3771d927e3fc", + "sha256:ab45839c912777e2738fed369636589c8b2a6d9c44ca56de0fd0814581d467c2", + "sha256:b312b3cc87951faaed3cfef984d768ee8bee7f935d9cc929aaa9946b0b96a98c", + "sha256:b58138d19f34e32833e62de5e910bc2a8baae43310b921d783bd39b15227c2dd", + "sha256:b620d7559b6b2197c5730332fab0867ecf1c8cb74d45533ebbcbcad1eacf4616", + "sha256:b640460f0ffb346b192686bd6fac5589e35a6c6640501c59a9fb6e82b0dd6bd8", + "sha256:b898caea081303006decc562c7fca5126f7c96507e78dd8f1ae3285dfa50ddc7", + "sha256:b95a6eca3b927853529eea958310563c83140ae8451dd5dc4399c7da385dc4f3", + "sha256:bad63bb4dea3c58e8078a3a173259ac2df5442a437e49c632b4099c0250e803b", + "sha256:bc5607c1911c92530cb402ea90d818933cffb28bd8de9b453a2542279816d8c7", + "sha256:bc6491d3008ecabf685b0746f03ad8241a0950336939b14addb03af39b51a316", + "sha256:bcd42e7b69c8c1e33a29b79b28de03bdc08876a49745830f9162a3af860e06d0", + "sha256:c3a78a3161b3a9bf07725822fd24d379c1f3f161b6db49166c4131096ea73b4c", + "sha256:c3dfb16e047c912e1a06bfbc45da752219f474897be85f55b8069f7936b08cc0", + "sha256:c48cdb6c904dca76d9915a579e4a5fab6b0c25f650c1019ce78a78effaf7a345", + "sha256:c57ddae24cf72eb6bd18112638a987cafe6109d90f2df111e6934362cc03ac1a", + "sha256:c932273bc43b068538f3874fa5e6c2a60f33fa0b11c1ebc7768652f6a0608943", + "sha256:cbd45dfba6b5c1bfbabe1feb3c0f117fbd62416e98268d9a7cd9ad8802875356", + "sha256:ce4cab32c37ef71e69cf88f909b7febd0dd79543e5ae3650e2b874e0f3d3b975", + "sha256:d75d6366203c8d025c1a74bae0b565952187ddae79bd5c7bf10687652a56f020", + "sha256:def66258d97ebf1e4e97def12c5daa542d1cc728a3da83ed3a43933f56df6dab", + "sha256:dfedf844892bf88f387cdeb9fa9bff1186904417c9f05087c99241bec24a65cc", + "sha256:e0345d4c1f7aa5a27075d28a7f0e9ed386729198045f1f08b47f8320d6bbda23", + "sha256:e3c6fb1c1a516881353186bed9cfcb8899f968c03b3509720c79db0d967acf3b", + "sha256:e5d4885c5625c9d2dcb49458700851574e9d0ea046c7a265526e990282f8ae8e", + "sha256:e716f47c7f61e11709d3c0904213c94fc22999abf0c41461276cef886c1e8b4d", + "sha256:ea4fdc79c0045d6bb1603c109127145245cafe888588888444e1e37fbeadbac3", + "sha256:f12e80c3089ebc03727d368f8205b811b5af2cd4a72b5e4cac75e901dd316e39", + "sha256:f42239c89430eee2d8a6dec39e34677abdbb67fff63caf2467dd6124ea4d4d58", + "sha256:f4ef4935962f7029b2058a99f1a47ccbffc3be919dddb3becb6c2c48eac3d9f0", + "sha256:fd91203e156d610ecb28b9ccd7b764af7a7b38662d7c163090babab0d10def0c", + "sha256:fe09aac4837ec720af606a493e814dcc3f65631984e1b7231b589efcf9917024", + "sha256:ff909b934b1958e31784d412abab5cbb0709fdbc01c86f22965e1d15331371ba" ], "markers": "python_version >= '3.9'", - "version": "==2.3.0" + "version": "==2.5.0" } }, "develop": { "anyio": { "hashes": [ - "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", - "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f" + "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101", + "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94" ], "markers": "python_version >= '3.10'", - "version": "==4.14.2" + "version": "==4.15.1" }, "async-lru": { "hashes": [ @@ -812,19 +934,19 @@ }, "boto3": { "hashes": [ - "sha256:4eb494d05b2bd08a7eee61b8ac4c34745c99e9bbce435c91f8d15d372dd8c2db", - "sha256:76297a0b415849c63575ae08a4f1661b2dc8ee0100f104b86f98aa69b47fa2c7" + "sha256:632a4f8298725b94144c8cd383cbdacb34624daa73221e954c3d33ac6e2528d6", + "sha256:c4e0f1a0295cbb7103f2950128cf88463c076d220080a7d0f127cf834969fc3a" ], "markers": "python_version >= '3.10'", - "version": "==1.43.69" + "version": "==1.43.107" }, "botocore": { "hashes": [ - "sha256:5caa46b740d9a886137146ffbb69edb691f702bfe74c64e85621947ae00181fd", - "sha256:b1f0e01c53d6b84ee9c184ebf3636c3b3aef85e0ae8498c74afb8734ff224f87" + "sha256:23cbe854e815dbaccf097f7fd32b461c9e1d2ed7e0c7dcc5658218704509d840", + "sha256:4a37fa072a00280c746313532d19b00e2dc53f1993222601df104d71d548d5b6" ], "markers": "python_version >= '3.10'", - "version": "==1.43.69" + "version": "==1.43.107" }, "certifi": { "hashes": [ @@ -937,7 +1059,7 @@ "sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4", "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264" ], - "markers": "python_version >= '3.10'", + "markers": "platform_python_implementation != 'PyPy'", "version": "==2.1.1" }, "cfgv": { @@ -950,110 +1072,189 @@ }, "charset-normalizer": { "hashes": [ - "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380", - "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62", - "sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c", - "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226", - "sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5", - "sha256:0fa1aec2d32bcc03c8fa0f6f1712caad1adc38509f31142112e5c9daf5b9c833", - "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b", - "sha256:16d10d789dd9bcca1173c95af82c58433122564b7bc39385124be735a35cbe99", - "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501", - "sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec", - "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698", - "sha256:231ddcbb35e2ff8973e1365db41fe0572662893b99a05deb183b68ad4c0c8bd4", - "sha256:253a4a220747e8b5faf57ec320c4f5efb0cef05f647420bf267143ec15dba10a", - "sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3", - "sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2", - "sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a", - "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e", - "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4", - "sha256:375b83ed0aecfce76c16d198fbc21f3b11b337d68662bea0a995046682a11419", - "sha256:3c09a49d6cde137258beb3d551994a2927fd35ad5cf96aed573f61bbd67c5f84", - "sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da", - "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519", - "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe", - "sha256:432786d3561e69aeeae6c7e8648964ce0ad05736120135601f87ac26b9c83381", - "sha256:43b9e366a31fdd1c87d0eb08f579b4a82b723ea54338f040d6b4e518a026ea29", - "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614", - "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0", - "sha256:476743fe6dfe14a2da12e3ac79125dc84a3b2cf8094369a47a1529b0cd8549fe", - "sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29", - "sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0", - "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917", - "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9", - "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32", - "sha256:58150c9f9b9a552505912d182ccdf26f6396fb6094816ceebcbb20eecabaed94", - "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63", - "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd", - "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198", - "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde", - "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012", - "sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1", - "sha256:65a7ff3f705e57d392f7261b6d0550fe137c3019477431f1c355e0db0a7d3e15", - "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b", - "sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993", - "sha256:68ce9f4d6b26d5ccbf7fd4459bf75f74a0a146677ebba80597df60cbdb20e6f4", - "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5", - "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8", - "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35", - "sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642", - "sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2", - "sha256:79580094b00d1789d1f93ea55bc43cb2f611910c72235b7657f3482ddcc1b22d", - "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9", - "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c", - "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33", - "sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db", - "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf", - "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9", - "sha256:8c041122946b7ba21bb32c45b1aa57b1be35527690aeb3c5c234521085632eee", - "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84", - "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44", - "sha256:920079c3f7456fa213e0829ed2073aaa727fd39d889ead5b4f35d0de5460d04f", - "sha256:93d59d504b230e83c7a843251681959a0b6a9cd76f6e146ce1b8a80eb8739af9", - "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9", - "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177", - "sha256:9bb41182d93ea91f60b4bc8fbf4c820c69ef8a12ab2d917f3f1834f1acad07e8", - "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b", - "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39", - "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41", - "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0", - "sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616", - "sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d", - "sha256:ad41ba96094304aa090f5a30cb6e4fb3b3f1c264c523394b4c39bbacc4dc92ba", - "sha256:b5314963fce9b0b12743891de876e724997864ee22aa496f903f426c7e2fa5b2", - "sha256:bcf74c1df76758a395bf0af608c04c82257523f55c9868b334f06270d0f2112b", - "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9", - "sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b", - "sha256:c1225416b463483160e4af85d5fc3a9690ccb53fd4b1865a6437825f5ede3209", - "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48", - "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046", - "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632", - "sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a", - "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2", - "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1", - "sha256:ddf4af30b417d9fe16481e9b81c27ab2a7cde1ff7ba3e85653b02db7d145dc7b", - "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990", - "sha256:df7276909358e5635ae203673ab7e509ddd224225a8d6b0790bf13eb2bde1cc5", - "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b", - "sha256:e9701d0049d92c16703a42771b98d560b95248949f23f8cf7b4eddd201814fb9", - "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534", - "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81", - "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a", - "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d", - "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf", - "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115" + "sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e", + "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", + "sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5", + "sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56", + "sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26", + "sha256:0891b9d3903c5571c03771ca669a4b0ec5618ca722a5c957d3d29cd4e5062848", + "sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718", + "sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93", + "sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640", + "sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3", + "sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875", + "sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e", + "sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275", + "sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204", + "sha256:15bb4005af6320d259dc7593ca84a38d7fe06a421dbcf7b910ae23979101e787", + "sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234", + "sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3", + "sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98", + "sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3", + "sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187", + "sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d", + "sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f", + "sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7", + "sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011", + "sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f", + "sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869", + "sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1", + "sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d", + "sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847", + "sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320", + "sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9", + "sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93", + "sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd", + "sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00", + "sha256:2cc961b171b3f3440f410489ab3573e86aea8736134ebbb40ea1338b7f0831bc", + "sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0", + "sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09", + "sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac", + "sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621", + "sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c", + "sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8", + "sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a", + "sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51", + "sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0", + "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", + "sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa", + "sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6", + "sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649", + "sha256:3ddacd27458c45bdacd6bd6db644bfb730efbf9e830310186e3045c9c5be8fb2", + "sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229", + "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", + "sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd", + "sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115", + "sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9", + "sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c", + "sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c", + "sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab", + "sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253", + "sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995", + "sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438", + "sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0", + "sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be", + "sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b", + "sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7", + "sha256:55ea99acb17b9325618de155a0cd6a2e8f5d10be008113e1d433bbb58db543b2", + "sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a", + "sha256:588461c2e8384d309bd63e5826019b6977bc66d629b99ac8737bb795d7b2cb5a", + "sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a", + "sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c", + "sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5", + "sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37", + "sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e", + "sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4", + "sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800", + "sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055", + "sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e", + "sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5", + "sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c", + "sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b", + "sha256:68eb192d85ab8e5f6ec69c2bc6ac0179fbf04a5ac1569d12fbef74883fe102d0", + "sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80", + "sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a", + "sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4", + "sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2", + "sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58", + "sha256:75a3ceed0724d625d64b86ca20aba182e4df462e04c2414fc941c0f523f06aac", + "sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc", + "sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639", + "sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf", + "sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d", + "sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f", + "sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c", + "sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc", + "sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4", + "sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253", + "sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade", + "sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858", + "sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26", + "sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96", + "sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8", + "sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249", + "sha256:8b2bfab86aa71ae13aa41a6a26aab338e0db2b8bc75434b05aea89e011ff35a4", + "sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13", + "sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1", + "sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03", + "sha256:93223adc95033dd47133a46ccfc316a0139176fd79085762e27202ec56018f03", + "sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e", + "sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364", + "sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4", + "sha256:9bde855991b7e362c146535e3136a50bfaffc0487d38b33ca7e5edefc6e23849", + "sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0", + "sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a", + "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", + "sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3", + "sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21", + "sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3", + "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", + "sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413", + "sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21", + "sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346", + "sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429", + "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", + "sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45", + "sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f", + "sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c", + "sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d", + "sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad", + "sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400", + "sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb", + "sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c", + "sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc", + "sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c", + "sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74", + "sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf", + "sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604", + "sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f", + "sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105", + "sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a", + "sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d", + "sha256:d4a7319f304a774bed22115bc891618e45f85065ab44ea6acd07d274e750519a", + "sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1", + "sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5", + "sha256:d913de495d90407cd859d263bee2e5d1a4ed3eb6573c04e70d9ec619a7cbed7f", + "sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e", + "sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709", + "sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874", + "sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5", + "sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc", + "sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95", + "sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd", + "sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0", + "sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d", + "sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3", + "sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c", + "sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3", + "sha256:e80e6c2f55656b4824d72065abb4ddd6a525c74bd78a0aab5d9fc2cf4fb5af50", + "sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491", + "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", + "sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5", + "sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655", + "sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288", + "sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd", + "sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084", + "sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d", + "sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4", + "sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915", + "sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1", + "sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd", + "sha256:fc14a032f813bf5fe624d991960ea83e9715adc27e4c1830a2361eb1d02ac341", + "sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424", + "sha256:fd1fbe0f116b6e55da77aca2c6ddcddcfac2186cbf78bdebf40fc156efca389d", + "sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f" ], "markers": "python_version >= '3.7'", - "version": "==3.4.9" + "version": "==3.5.2" }, "click": { "hashes": [ - "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", - "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76" + "sha256:255bc9599cf7748b4b1a446ccc735421bd08a2ae529a8b88597d3de5664ee360", + "sha256:ba0d2089de75ea0310e2dde03160e6ca10009947fb95a182f9b54021bb272e34" ], "markers": "python_version >= '3.10'", - "version": "==8.4.2" + "version": "==8.5.0" }, "colorama": { "hashes": [ @@ -1068,182 +1269,195 @@ "toml" ], "hashes": [ - "sha256:002a438859f7b430bc99afeaf01a6d187dad1d0dc907b64cdeffc632a5db8fd8", - "sha256:050467a7983b8e2fe7dd41a78bb30c3e7f8c0b8cafda14b1c46f8b5e3cf2dd3c", - "sha256:050f66a08805acb5b8a23c6d4a517b1ecf82c08e81ed0e4bd727df065e5c6624", - "sha256:0548198fff07ccf4faf469520bce1c2eceb1ce3e62891921138dec10907f9d00", - "sha256:05e491d4f3165d62d4f5c8fd48dfeabf2ae8f42cbbd484319af33ea851b78982", - "sha256:07545711d4f0f32852a18f18ad11f76f0109909d09e78b9008b4cfc67e829429", - "sha256:12b59c90084e3234fb11184886bf4a40f4f16a8c8f867be2e087b81f8e8868d4", - "sha256:141fae2cabf5569b782c10afc4c850ce10f618c13f8db54765cba99cc839da1f", - "sha256:150089274bdc9f940628552cb92844e0223c987f1902ab8efe9f45a2ec758d88", - "sha256:1587fb771d1ccceef708fdde1e5af8c7ed24b486b61d13a321acb7d8145390aa", - "sha256:1c9bf40ebef178a45192c75c4964760bb261b0e6ad725da5fc4c93f674f19753", - "sha256:1cd685005cd2c4200adfc14cf39a603b9320efab3f18a8f7f156d20c9cc3345f", - "sha256:1d10025d96ea89fc2f73714dbc4cbd433fe012c1ac9e23f895d7728b238b6e52", - "sha256:1f4f826d70f772ab8b0c052329580d7fe8b8abd191e4ce0c8f81aec6614665d3", - "sha256:21b803935e2efc3acebe9697197a294fccf5dc4e5382bd6369542ff7a7d2a1d7", - "sha256:226c66e80ec0598d3b9b4874123df167ccca342aca8714f77cac6829688ee09c", - "sha256:2413074a5ecbb61a01a7888fc72db0ca324d13588c5b38bc0dd8564cdcdfea26", - "sha256:288bde2a2d7ab6b6c2d7252fcde8b524387f2d970bdba9658fc6f8bbcaef0f9b", - "sha256:2c9872e4d9dc5d3cf616bf4b382f5a00359305a5be666a3dd0b5cdb4e49597f9", - "sha256:2e179f19bfe1d31f8eeeaa12990194d761c4f62f0759661000bca6cd8729f40b", - "sha256:2ff8f5e9b8f7a94f0c11c45631eee103dbcb7d63274edd12c56efe1be690b3b4", - "sha256:317db01a2cb02552fd67e2b1cca77a4b528a2a277176c5e0bf2cecbb639d3f54", - "sha256:337399ad2c93b3acd2a937627dae8b3e86b66707cd3d3e856347999aadf1ef8d", - "sha256:349062d66f00b40fa2c1c222438bad25fabf755631b5d82937fe985c8008615c", - "sha256:357a173465c7ce028d07a95cc2b63b5bf59f50ecdd5ad75c5cbb78ada984048e", - "sha256:37e2f0cdf58e2e1fed4e4d5a8f8786ae2f7eb80b478016876667dc4a01d60a97", - "sha256:39ece820e29e0a2ba34b3ecb3be83c27e997eed8926f2ba6fe7ce7a0bda5843b", - "sha256:3a54f5a0d85050c73a38f6793090ee83974531e67fe5e57a1da9bee11398aa5e", - "sha256:3d6f4955b73b5445271379a59e3792b0d978f42d4a01e0cf7a67d9c33a3bb0a5", - "sha256:3da9e92d1c551fd7563833e9ade686efb0c4b7363ab7681a94283958c950bf5e", - "sha256:3fc2130bf37df31852a8384f12601563a45a0024bccc6624f38355cba7a8d360", - "sha256:3fc9e047706fb4a9abb54f719d3aa643e80e5bb3818182c40aee01ac0f0247ba", - "sha256:3ff205ab5e3ecc670f6a4dd19d9cbf12ede53dd41cfc1e15716ec961ea6d314e", - "sha256:4256ced708e598e05209bc1a8ab4074e04a51dba4c62fb45926a229af675ace7", - "sha256:425920379052ff1fe465268f3361d35804a241bbdd5a1b592c8cb60df4c52325", - "sha256:43619d04c3671792d2c4706ae8bf45e265dc87bbd4078189ef8b847ea1e74be2", - "sha256:460115e32ee40566476db5048f9bec1e842c127ad8e6f8be745aad3ac9cbc839", - "sha256:46822e9b6ff1c6a72b518c162c44a8f45a61a1d609c51084bf5b16c023c5037b", - "sha256:474223409d88eb20d2d6a0d37ea60e8647a65a90cc008dc1f0410af5f64f1e0d", - "sha256:4a4bf917c9953f57c957be31c1cd504e3bd2f34d4a352b9d391a3025336f6768", - "sha256:4dff9daa47d83120c3ec38ce921214242944a832aa04e903e50b5b7ebac8972d", - "sha256:4e6f6f632b7b2f714bf7a1346e8f97b650ee71f3c298aaad42a2ab60f0f07645", - "sha256:5172326e861a38b48b48befca15e0f477a26b283337a33a739c8fed229934e36", - "sha256:5669c8378ebde86f5def7a25d29586631b58acc27ffde04399f678f3dfc6e082", - "sha256:5a325e815318638aed1655d9c06e6d7c2d3d46c09231ce988070428a8762d734", - "sha256:5c3431b2161279b7db5c2a1aa58ae02e5cb8c3c42d93a5094be3f5537bd5b11b", - "sha256:63fd6fcd1dd6e158f7eb78606e72933b3f6d01e7b747f99c6c12d764307a0fdc", - "sha256:67bc345491ab55b837277d76f5775d057e8c7f1ac44d890d8c2c82adde258c6f", - "sha256:6879ded16a27f3eeca19b900c147e81616e7054db451471a611b2755ee5249f7", - "sha256:68be5e1de60ff13c9095bbec0e5a7fa45b33b101752215b91345ea1f61c4a278", - "sha256:69484d1aca26e322e1c3ce03f09341e84524ababad2d7202161738d83cc9f82e", - "sha256:69bb2400abef928e365ea7d4d9925169ada78ed2295546780002d4b65de3df88", - "sha256:6befeab5fb2b51c958ca4ac6c5d141a1e8240f4f76e46350f1911963deda49cd", - "sha256:6e0a8a5083b096487d6cfced94cdd514d8f5db6f113610fb36c0620edb1028cf", - "sha256:770e9325ab5ea6d56f77e59b29ecfe0ac20b57a82a601876f90494a4dda0386f", - "sha256:7a2b580774a4786c1053157c0165e04476e03ff293993d7c148eee784a94bae6", - "sha256:7bbd7d6418e0dab31a206af5203bd43ae36edb8e7fba1940b055d3e9249290d7", - "sha256:7c922735321eef3f87c280a3d39afff6b646723a2880b862cda4ac7a093b8aa8", - "sha256:7d1abebdb047729e852b9c77a00497dfbeb11eb3a117e037d7dbc3ac8e5f5c54", - "sha256:7f2f62ae3cd189dd2e13aece758c57b3eecbd27be070dbd4cbd10936049e5dbf", - "sha256:81294c7e6ab30c5f74c0353b11b2fd6320e72d9bee6ac73b357caa8b916323a5", - "sha256:81661f82d302484e3119e7c80c519c02fa9bcc2a6b339baf67d67bc89c580f04", - "sha256:83cf06cdd687677742caff1a9134833b7a8b75f111519d2cb0e0ba1b9a851e15", - "sha256:899b9da30f3c6c336566e3707495bb23e8302d39d862f01fa78c48b99b9437e2", - "sha256:8af623e5cd92080acddd02b38f2f406a2c3a0893c38950b211890361448fbf26", - "sha256:8b4f1c3a69ca580f3fbd6b2046915f536d7f586874f25c1bb23add2a3c88d50f", - "sha256:8bc16bb47b7679670eceff71d78bfb7d6e5b143f6c2cd117487ec7c75e0d4b78", - "sha256:8df457da2249d3c75ca2e5e835d59c725abfe92d27fdff6cd99eed85b51d5e9a", - "sha256:8ee3838dcb656602c3b51e16aed9bfb0822f8d8d6d1c5966d32ec8c104be8e20", - "sha256:8fa4de68e2a752468ff14b4e15db7def689a71be759e826a31ccecbef69c5fd0", - "sha256:93a3a0b662abcc10c73a47cbc72cd60f63618d6989fb2d1286e50eacd974f303", - "sha256:964730a1e9de9c0cf11be6a1a3c79ce419c34882842abd256086ba4698705e84", - "sha256:96e257121228ec5cd2bb919276e94ac11074471bc37d68dbae0e8308cce15fff", - "sha256:986be58c3ab54aae8d3496a6225eea74f760fdbe739b38bd442c7e8d133aa53b", - "sha256:9e71e7bc71c686a123347ae47a0de33a175e797a85bb57b791492adf4eec8ed8", - "sha256:a0865421cfdc53654b342d515e5a233187590882d20b95752150e53f65460017", - "sha256:a093fd37229918976f602aa07aa59e0973cde82186f220c8e197f721f5be0ce4", - "sha256:a58a94fed5da6997d258e8f7668c1e195fbd04a691d781b7558f1e468f9e68bc", - "sha256:a67a9f78b2942d87ba8ce3059c642164d2aedd65337377fb52fe9803656bc5c7", - "sha256:a9447978a92f405d301123cfd39ff49895490efb769a758fe2734c7f631bf8ce", - "sha256:a9464451c4efffe8d47ace5a540b10b0dc10e879066290f8600872b7f54a419d", - "sha256:ac41cc14bebda0dbfb0628036b7f75706935c95bcc07fefe9a0f93614aa60a57", - "sha256:af6c538498ce66c10d3fd541c2a8d5b03da5850355add34e6cba564210cb9e72", - "sha256:b10075e5421d04265766a6d1dac809bbeb8a946fbb23c8f82c227409b2190719", - "sha256:b24e078eabcd6a9caa8b0713f9bc1eeb310bcc960a29d45a3b4fcd4b16d5b11d", - "sha256:bbac5abad70df71019988f83f26ac7092ff2642975def4429e98dc7585ef3490", - "sha256:be619439dbcd31a2eab10b32de9fff62c26ed4bab69dc32b8363fdaaa0882809", - "sha256:c2de40895718f91951b86712b4c5b694acaf9a0a49be13874896f599a1eed3f4", - "sha256:c38efe30fd74e5c19e9433f11fb1f5dc9c6522770971b7c6145bbaa413dc8800", - "sha256:c6103639613fe6c1e989082948419bc77a2d26b6c825c99d7fad25f7d3d87afc", - "sha256:c65a9e0dfc6143491879da4e13b5e30f8be192055de508d737fb14601edbd22c", - "sha256:c705b28feb2775dc82a25f1d473a370bc37ff93f5177f4e29ce2425f560f6921", - "sha256:c7dbc748ac8a1e3e59a2b28bea47675e6e778081dbbf081bde0d75def2fcbe1d", - "sha256:cb476b2e828ecb71cb6b6a928d23fd20a7ddb501188022dae1c37499149cc338", - "sha256:cbde877ef9dd7baf272b9bfef2b8a25edd45d9170fc326951dd20eb480335e85", - "sha256:cfe20cc8cf8821d4fe54f89106cbf06aa27f37b5bbe3535568065a81539b4150", - "sha256:d003b7a5708ddad5c206c79607a6b92abb6fc13c57d99d8a4468cc03a2941ced", - "sha256:d0be6daac4cce6b8c8dc65886bae1b082ddbca4da8e5cbb5e15166acf253e264", - "sha256:d12b33a3a50a1676b7784dc8d00a0c6d66a9f2add4b85a041c19b6a7e53ef23c", - "sha256:d15715e8c46552827e5e4f30a35575a2dbcad14454cf3284c54483946bd16931", - "sha256:d28a4a899354d0ea6214cc59b4fa19eefbce1b9ff1688ab579acf49e894bd3fb", - "sha256:d3af93dddb5659276c63bc16ac6466ac2033a70ca816097bbc06345b8ccdf571", - "sha256:d4fedd1f7f428f9fe83b1ead5e7cc87a43427be31aadafbac3ac0636dc7abb22", - "sha256:d802e1947603162ded419bff83ac7489820355d2b856dfb09206574e3a37ac0c", - "sha256:d80f974b20782d9612c8b4c9beeca867074c7cf4079d1419843fa25a26428b25", - "sha256:d9df165544774574ee004b953023d1bebada1894a80b1052a43d798b0f676e67", - "sha256:de602f34123c2f4af1c1869c6dbbbd60da6d5983bf01937367295d135cccbfce", - "sha256:def597967dafc2e8d97c9097ea453c464e0bb8ed38f193a43070f10dc623bb6d", - "sha256:e101dbb4b9b72f0cddd8cdc8c9c5b47f456766f5e0ac82dbfb75e5c55409b78a", - "sha256:e4193a04b518f7968f3099755f5509ee7cccc6dc2b92a6b14841934d22e222c9", - "sha256:e98dcc55d572b38e69d117da7e8e8efb8500f1f5eaf81ecd460a63220790b839", - "sha256:ea82116c9893fa89e929b7f197ee5a1950a76e91cc5c85ba503fc02379d04890", - "sha256:ebd5a6d8466ff30836572f3ba2cae8a5e8f85029b1c6d5e2ed338dc472a5166a", - "sha256:f0204ed122758782970526057093f448051a39db9d810d4e344bb87a3546f425", - "sha256:f21b56dcace11dfe013014201f577dcd592b2a9b72182d930361b47cf6f73f25", - "sha256:f41c17c4668a655ce96d090d8d5ffdc24ef64b5a02f9753884d08483e8a4a41a", - "sha256:f9de0a24a4079b53e523b5c5e2c5945ec251ab486652659955187cf255a259bc", - "sha256:fb55d0e70bb15f2e81477613627286581414693d74ac7963c93a790dd453ca9d", - "sha256:ff97a14362eef486483ed44042ca2027ea257df6ff768e62358ee0c9776925ac", - "sha256:ffb3c2aacea411cc7e1d27712490c11108e2de1d39019ae32915493a59a8b9ed", - "sha256:ffb58d7eff5b7f6ecc6fa21d6288ab7f968a212cb67d682c269c09b9eba3b66f" + "sha256:00d3eb96e9988c45f50cccd1f1496571ac5c1f91386ac02c4d55516eeda19a24", + "sha256:01c6908bc613b420c26c818fe948e1b97dfd041a53c98b01c63bd8321f5c9aae", + "sha256:066429634299e14dd2d511e1e85f8f9cecc500781f6b41907c0dd6f1baea7e63", + "sha256:0993d0e90858c03943d3cb152e068a20dd4707924deec84dd2230261baae3b1b", + "sha256:0dcbcfcc059117284c603ff8cb61a65872512882f84a8cf0339241f7f7c2f148", + "sha256:0fd7a86fdda7cb6d616d178654bd0ad6bc0f3f33c2e478aa598500a1a9e34eda", + "sha256:11d28e9123a9156cb405d8d27b44256c9a58fb5decc2073a8f17862057e3aa0f", + "sha256:11e597173af1dc33d5f8a7332ada544199269a223af1ee1770ddd5e245ad0fe8", + "sha256:126d1af8804d7224421fe991ff65d3ce649081560df7a98b1a5ffff07f9923bd", + "sha256:14253fc7bb15749b849795a06f5d3b6d8bc3fb8a4b5ddc341faf7a89dce205fc", + "sha256:152877cdc8a07264882cfcd503ba56a3ef6cba56a70e8c70f6eb8ffd7384789a", + "sha256:17228fbca0f22976f797be94e975dcd237799c657d49551c7de1e0654d1202e9", + "sha256:191803c4996b499fcd78c2ad5e5f767dcc53cb4dc6de6d6a741b443a1821ef02", + "sha256:1a37c6e478cf687e1aa30a593d19c92c02fad9d122b51ab73f51b8dc7a0c0fc9", + "sha256:1c569a9fd25505f1cd6bea90588818f90373ce90e2632e2cacf19ddbd6e14fdb", + "sha256:1d56e4d21c56d2046447733f8b118409597db48c01efe898ee9ac24e858ec2d6", + "sha256:1d5d0e3b660506fb84f995814e3118a21efdc0c8eb80127da1be627d90093c17", + "sha256:1f15254427c9b33eedac4f198eaf9e356eb4f6214551afb43da6194a2c088ad7", + "sha256:218d742afca2b5ad5ca759e93eddedfbcc6eadf8322f080dcefc40b7bd4e2d48", + "sha256:22957cef43ce038641de78ba995de7568d2d6a37c6ddbf7fa0fd7d1ae2344d91", + "sha256:23219888477edd736b6fcaec1272d47d93b926e999641ffea7e53a1738e70b2b", + "sha256:251aed777c47c77aba047096d4542889db089227655711dfc2b9c54ef0e15e35", + "sha256:28ff850182a67d117990fa2ce5ea1032836d8c9630dae867e8bdd3bff4533b79", + "sha256:29309ccc86b7f33df7db12813c299f215bbbc470ed6292d0bedd63ffae1ebf64", + "sha256:2aca0bdfa9e91621d5b09d815357bf63def4fc0e9cb66da67bf2cf93f3b1a6f5", + "sha256:30c1b65d529e46569899fadca59e4a87c1faf2886923f1307ba61e654d4f3c20", + "sha256:35f37886699cb9abd29958247d718628d5bc6f39e623dff66a09e546c42a7e03", + "sha256:382d3346d56b0eec1b793d53a4c88799c8053f516aa3a8d7c44315696954bacf", + "sha256:396bb16e04ce04efbb3df91456ae4e3da918e69ecdf67fb711b0a0fdf35ccce0", + "sha256:3e7f99698ba3a7d13988bdd984b7ebf13af4dbe2166dc8502eef90d77603b0a4", + "sha256:3e861f1071dcc2fec1e88bef0920f6b1eaa66a143555b4f8ab79ba2b0f30ef55", + "sha256:3f43bac1856ba269b905302778d4df433d6006489a192174ad77ac528e395032", + "sha256:40c0f00899fe6181ae7f434ceb200e51f5ee4b8ed10e3b5f0b605f0cae15da87", + "sha256:414c26dfdb96aac2d570a54e03008f001e32eb2d413705365503648c6bd361d8", + "sha256:4358b9c8c0125b460407f3017c6cce8156e904b32772c5630d27112f52bdbfe5", + "sha256:444889f7f66b74e4455c0a97e0e166dd41177f1dca8c0239a47cff25e05ba7e1", + "sha256:44f21e407b278efdfc1ee5e481e00518bd1d500310a30a5fbf2bcbedfef4aaf0", + "sha256:4cc4f73aa3fabc36e32046d6cd2971405948d8a903636508a3d3b2f9128b3a95", + "sha256:4dbbd1155ca46e6e0b6b89d204428c56ef6a459af21333f365d135a2820e5a09", + "sha256:4ee546b9e4872ffa194bf07ac87bfa1202ebb824d0795dc1ef22f175545ca90a", + "sha256:5139009b5efd2194fc168ee9362f0e191ba612ef5d29242f9269c22f9b8f80c7", + "sha256:5375ebd99038021b35e99dc88255022912c06565d316212f4a576e4b08d30f5d", + "sha256:5397e21a90dde0e9c6896b77ded8f0be26b66f8b22b33aed41f6043ed95d55e6", + "sha256:57ff3783f99d75a1e81dd56a9737eb5665e6736a5d93258ba596b6dcad8fd05b", + "sha256:58d4a54c6ea672afef66d49be922a2c69826c5ae1a42a9cd94f0c9c2bacdf800", + "sha256:59c3926585e1cd1f2190f4b2ac9014de1bbeaf0d5d0587b0dc6b0aa90d17896a", + "sha256:5a27b731c171e43dc8b5f32b76a5051dde2ec9b9366c87028f08a7088ebc2c7b", + "sha256:5b3146d2317c75f70df2509066d979dadd941f7021cdf9b5db4bcd8568258e25", + "sha256:5dca0bb66b4c3d624ba047887bf70270030c150692d543cb501293dc38a9f4b5", + "sha256:611a44e5229a59d7483ce830160e1a0e85f700562c7a5651c7c63fb8f4eb528c", + "sha256:648352b94507179d82637292e7ae8802508d95f78e2f00a705a50b6c48011681", + "sha256:6a75180829efb8ae62b4aded25be6ddca1c888d138d2d82e21d93bfbd88f41cb", + "sha256:705e5af11d34647efdc170c7840b6857c81cf74be96419a553f237e68e62cb72", + "sha256:723dcdab91357159b722935b500ee8abc0a66c8c432e1e9fabf4cc7598952de8", + "sha256:724bd0f1e81856b35e59fc98cf7b4e544a3cb662e4e0864dca73d4326ee9d808", + "sha256:732d950e51f3ba4fb6209c73250f3e8924fefca42953ee04a9e65d8c02414d7d", + "sha256:736fde09ea39646d11f8e3b76bd3425c075aa4dd45f24891970bb77c14ff20f5", + "sha256:7a076277ca9f5750cc230f0f578ebd2620cec60255b25707361699fef6fb465c", + "sha256:7b3bce4a0d05401d70b7d0d5ca783e686bc9d30e81dbd7d980d532609bf809e4", + "sha256:7b451c68218c150f616bc9649783ec8de76a59792c759b43aa0c9c0466a465e4", + "sha256:7d0732c83746bc24123c581a85d9dd96b70ddb538c9076020aa1a041790361e9", + "sha256:7ed238d227e23cc300c3d464babdaf9f6ddc740aa1b15a77ae96136e6a7c4516", + "sha256:80d3f7b48d43ee8fc5e8707a8adb43d743a5a1a85256c25a24f9d6d0e2238fa6", + "sha256:80e9fdb4c3d926b6ba721d4bf7435bdb869c3527ae7803290361d0ab73db13b6", + "sha256:848893e1d361448c113dc2f0913503522a6f7be231d0e38333d2a22d9698a011", + "sha256:893ea9cf86cb8d2546812ac93d973aaf2ee1fb45110a873b014214fd23e3725e", + "sha256:8afd9bf35cc6a1f22eb3634808fa8e0b91902459c5721ef2e4461dfe771d7f08", + "sha256:8be099e979fc42559328a21828281b4578304191ae46ed4e80a407048a82eee6", + "sha256:8e209591f7c41ae4a9171335cf6156afda0b21de73b02f73f5aa95b2d5fbb08d", + "sha256:8fc15cc8d0d06e873c00ef18e1372d605f9aaf3de27d8c24e50782e75bc8b843", + "sha256:9174f0af24e5eff248b9dbfe76ec5275a3d19d37edbc2810543f12cf97347a34", + "sha256:921415102a90637fcc2e3f169f61dad7699ecf690e8639fc21b813acbedc0967", + "sha256:967d72c835d7a8cf0af99ec813a2d06e3db6df706402f1fe85b31b437645f495", + "sha256:98d9c97f51b334b0adce7b964442a9af33c1a00c6ac856984cc5dc8d18f81c75", + "sha256:99704f73721e23859112072d522076e11c31744fc96b5652e5dd2018aa4359f7", + "sha256:9a75a4704ff640e46170042eec1f984385a121227c505d5a16ad8e495f452541", + "sha256:9acc7f7ec4a1b5f89bd929fde5b8a714f6fafdc6cc18725413d510aa082b47ad", + "sha256:9c6afdd69218202bc1758c9a14b86b8cf1084f37ed2ca143e567a103772b16d1", + "sha256:9cdf19874e0d247f32f03609200370343c3c7aa260b191d8c2bb251d36198283", + "sha256:9e1d0ced76318bab499693ff25f64faa343415187cb2e4d7befdfdd391a1cf6a", + "sha256:9fd670ac43b709c575aefc25bf52d8a598a3bc5017bddfd0a179152ab06a2deb", + "sha256:a0f2285329dac10ab08f79cb11f5692c497018e6c7c511f95e6fd63a70b8f831", + "sha256:a2fac6895eb299a2e52d7bbb8fb3903502b9da8d3f5309ceb16ec40c646b58ee", + "sha256:a336eec40e3520d369b8a6cdabb4f596e69a8b42927ca074aa1452fed943238a", + "sha256:a4624f80732f6b427ac58f1f59c577a0994a12e8174b5af6a027b4b58795d4c3", + "sha256:a56ac4fa5a75c7e182e8f62600cfb4aff43c5ed7356a034f3557659c3bec1d90", + "sha256:a678c0b6b22086ec2427359d22e37445d4a792f5fdbbc744112c7dade65cad02", + "sha256:a740ea6f083c6db7b926534d159508f80ba275ab35e722522de0d18d0f56e55f", + "sha256:a90700f743e29aa3d75a6ff5f01953176a889c00e526194bc4d281731b88d99d", + "sha256:a9a638be322a8d76a41cdb17781c7f82aaee6a66493d8ffb7e2c09ee22423d99", + "sha256:a9cd3de0a5bfe7b0e21ee10e1a14e3d61bf52efc88217ab1d95d6ace6970bd46", + "sha256:aa62c85046473959c13ba9edca9dc90a77d5c1095b1ba313556314d77fe5b036", + "sha256:aba5c63b7afdc749cc9eae943d5b868cba2b261a176378fa1c5a30bc8bc89982", + "sha256:ac0f3b379c94acc2f7dce5f5f0b24d44fa1cc6a509717ef83dfee07450c2117c", + "sha256:af2a2a8c7c74de0559e0c368d94c8def9e16c58faaee33a0bf081057c4227e3b", + "sha256:af98ad5ed9d6daaca956201e00bb429a7eb2b080426686f70a20353e0f9839f5", + "sha256:afdf43b72ef3876c1fe66423b91466e37877c9e81e8cec70542b7e8525b9d1b7", + "sha256:b88841e654f09732804809e435b3e005a929ffd9998b872b7b213957b8759cb8", + "sha256:bb2fc905bbf4e6b7f40806ea79e31515abf6349594cdf0adf27c4215f0463204", + "sha256:bb4ffe96aa663cee727659db5a2afeb38c95f8677b747d447b90d6d4874ea2c5", + "sha256:bc0b0ac781d489304b741269857f1f8338b7a26b1b89c06c0344658001ec0035", + "sha256:bf1bd822ec4e387ed245bed0d71151582cf7be9e5309bc4145eefe36083d5878", + "sha256:c19cd6d025c1673f22afcd22c7df8a662d779e05d8e3fa6820c22afb895b0206", + "sha256:c3305c38a2fa21a4254f2ace7dd9ef5fc569c9a558b66e7017650b3d637fb95e", + "sha256:c85d54e7e8a2ca932fe8399301af9b8d5907ea2a455ffaff6e7d1208db83b943", + "sha256:ca64d9f1f384f151b9511bec01126072acd2f313439f8ed015a22d8790aab6fa", + "sha256:cce2bc991293f15cc4084ca116827b5900c5f34e1a54dfe83f10ab5c43162eb7", + "sha256:d6276d78f6fca7d0ac066d5da4165c5acd07829e8305c2cb900b738fb3a75a72", + "sha256:d93db87adb6b1c1b408dce4763314b55d76a9f589e96783a84ac9e7689e48bdf", + "sha256:db5f8394e17f877a625b257f2ba0ce8e728a499c2c1579ad66220272cd3df510", + "sha256:db76506aa5416081f3e8974ae0f7965c58ada0bb0ef7339ac86099588dbb20d3", + "sha256:dba2edfb054f6d4a08df9d1637c39a5aa3865bca6617c13c86be21e45658a59c", + "sha256:dcf4bc2aab4e16b1c4c0c2005918f23a7dd5d7821ddae82caed9e3342dc2fcce", + "sha256:e1fa594c887365b69745f25a416806e61085dd07b94c9eae68a6e20730629b23", + "sha256:e6c52d3307824ff93b39efd99e4185d557db40bd841452abfb32e5d9151ca162", + "sha256:eb57acff4a74246ae513c142d4b36e18c389c3aed8661914a53f7cd0071031b2", + "sha256:f80bd9f9633eafc73d0a913ba2645c96ba58bba1befc30590f7c0fbfde59d865", + "sha256:f8475460aa33ee28ac896ab1156d0bb3b6c639f7f8383c2677d3359eb35f8205", + "sha256:fb2bde05838fffae1a1bf75e5d411a6cac3e4e9bb97e6640fed8cd47888b33f0", + "sha256:fb9d92ecfe2d5b494367c67f7446f8b75b68d8d0c8cf3bc3e6997478be25d9e2", + "sha256:fd3d72233eb8b48acc94fa57d44e2d32ce8e7abed02882ccb6d855ccc4ed33ec" ], "markers": "python_version >= '3.10'", - "version": "==7.15.4" + "version": "==7.16.2" }, "cryptography": { "hashes": [ - "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03", - "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7", - "sha256:07479a1cb08219ab719147e742e76090c9c773321959bb94946fffdd397a6437", - "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987", - "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025", - "sha256:11b74db56cdbe3cdee6e3f6982ecb70334fa10dce99ed58bf7894aaaa3b2a037", - "sha256:12b9c6996425c76ea6c457ace4f3073e715b8c545add07cd1a8f3a4f90691269", - "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105", - "sha256:19736989797678c6af1e55cd49055cdbcb55d8f6b5583ac5335f933aba9101dc", - "sha256:1b4a266766514614f8aa60416e71f2fc6e575d36e7bdc90f644fadb2f4b75b95", - "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b", - "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47", - "sha256:3f5735ffe4996d28b809371756219f5354864902a3b9e7c0b9ee87041209fc9c", - "sha256:49e7d93abdbd2990caced757e5fade25302f719c3c8fb6e6fff2dde98999fc41", - "sha256:5e34edd123674534acd70147f0ca331eaa2c74e6325fb2028c886aa26ba0b68c", - "sha256:62598a8a57f815db4c6259a4e97d857dab56697e7de8e8ab02352ab74da1995d", - "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7", - "sha256:6ba6a53445bd3cfa809ef3ef5f1589aa6ba08784a1d962bf47d0940e871dab1c", - "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708", - "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef", - "sha256:80b63928fa35083b33966ce1efb70e5b9607181e49dcd1c22c8c005e319f667f", - "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f", - "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a", - "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f", - "sha256:8eb5e1172eb569ea8a872796576e6a67c276351728b6455d5beb01242b027c6a", - "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a", - "sha256:910d11e1a385c654bf738bf3e6b8e6ed5de0f5610fcae2be9e5b398d8081d20e", - "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3", - "sha256:9aa87839c383bdbab6ef865787a1fb877af8dd03464c4400322726feaaadfc6d", - "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3", - "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f", - "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae", - "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30", - "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9", - "sha256:c99c003e088647b8a5b7c145d6f78c335f6348332b62e142d411c4b63d1460b9", - "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07", - "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba", - "sha256:d58c3db7cd6eed54e6c06744db55456b65ebd7492ddeae9c1e93cfca7aa857d3", - "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f", - "sha256:df2a58a472f332225671c35b0a830208b86d004f82baa8530fa3782c85646533", - "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5", - "sha256:ecfed7367f965a0328cfbdd70da860f15441f002f613185668c6e6ebf5a0ac11", - "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9", - "sha256:f59e38625469987d7ef6d495323c55e7db6c212eaf6112267e0d3b565a2e9c9f", - "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169", - "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645" + "sha256:0ddc924c04591c2811ca024d62ecad4f7f6f08af8939c211438f48a16bd23602", + "sha256:0ec5f09541743261e66e291b4a0cbf0fb2997aeaab6d9e9c740b9dba1b58d1c2", + "sha256:0ecbc5652bdb6fc9eaf89a7d196e20941adfe812f43bc4ca05d9150496821047", + "sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c", + "sha256:1ba34f04897fcdaa73f74145c25f3ec146fbd56593853e88adc2e811303c5f42", + "sha256:241449bf940a5d27309bd317e6f9a2af6932113818bb2b8f5c59ddc7ef16da18", + "sha256:25784ce8b9621c90c643efb9e1e2162ab3b0224cae446ad5e70e7fcb1ce18b51", + "sha256:3dc4fd8058cea1644971207d530e1a03a184a805ffc8ebdddf0599d78a331b81", + "sha256:4061c0079120205fb760c58acab6443e217307dcf05e3702cf970e0689972856", + "sha256:4a20ce1e5cb4284a86692fdcba7cb8754185c6b2e5c56fcef3751cf451d3cdc2", + "sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de", + "sha256:58a0c478eeca76fe5e07993c5a0703def34a6dc6a0cda4f5564639b33112ffe7", + "sha256:58ddb5a8e3179d12f19e4ea34d2d32e9d63a4baa142c875c1eb59f41b7243acd", + "sha256:630ebfea3bf689d075f82316324ff7433dc447fe6bc1bfc76524b74b4a9567d2", + "sha256:6f8700550aa1474a91e5dc07049c46f98b423b5b1ddd0483e0b51362eeeaf5be", + "sha256:78198641e5be9521beea5aa782bb551a58068d10e6eb04c9c680c1b69f2e7d45", + "sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0", + "sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e", + "sha256:7afa5a6602a9f29af1f3a2965f831bae7c9d5d597b7cbb716d41ab3b7d89879c", + "sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5", + "sha256:7b75de3c8b3be1cdb1052747c929440c3eea46c1bc2cb8a6e3a48388e9b7b452", + "sha256:7c6d0330c472d96f6a6afe24d80dfdf15176c33096f0a4397ae4c60f3dd3be48", + "sha256:828d49b0ff5a0e3975865571c5d91dbbdd0d38d8289b249a163e9425413a5e05", + "sha256:84f964e537f916e2cc85199e5a88742e964939b575ac8598b3f9d6cc416cdaf1", + "sha256:85d0d9a31b9098e98534226d5686b47264b95e62ce459dc2e62fdfc809f9fe93", + "sha256:87e9ce85beb6b328ba370cc6e6aea483c92617b4c95b1d33a49297eb662bfb04", + "sha256:8c71ba2cd31fc93748c38e1b613200ff1c2665cbfd5341fe3a61cfde35a1430e", + "sha256:92e665960f25fcdc73725b9cec7a3824f279ba97a98653afe9ffac2e43668f67", + "sha256:94e5e9f108ee10471288214d3d233fbfbb492840a8457eb85178d643ddeb32c7", + "sha256:9c8402a82ea0dc4ceeab793db05f0fafa8ca139ca34fcde5df0f596103c74107", + "sha256:9dab55f57c74c3cad24c323bacbbd04be4705ba6eb0d92e920b1fc4837ed5079", + "sha256:a582ab2ae1d34f67112cadc86702774c9ea4374df6bca6afe672817203c99134", + "sha256:a6557e5f38e065ca9fbdaf7cfc7435ecb1d113aa81a022d1b51921ee7432e227", + "sha256:a9f7355e6fab51f6c369b86fb7571cffa05edee2c2121e0380a37fb9ac1cd5c1", + "sha256:ab50ee449bf968271e820086f10a33d101dd060370abc10bcd22279be2656539", + "sha256:ac9ed99d81760c62fe89d5f0815cdfa1ba9a35141cf30f1c2d044f04b4803d2e", + "sha256:b13478603dcd0a2479ff8e87e2c19a7d525734686fe3c49542472293a204212d", + "sha256:c423ab384a46c4dff7217b2ea5ba2e11cffdeab6441acd04cf65a369caf0366c", + "sha256:c5e67125c7dca78d199ec4e116aa93dbb83494808ecbb8211a2cb09b1bf41dbd", + "sha256:c71be1cbfa5cd9a41ee452acf1eccd82b2c05950358b106ec8ceb83411d1a020", + "sha256:cbc8738fd8526d80f35cb3a40d41f41a2e7030bb3b18b09a6778ef63d291c2fd", + "sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94", + "sha256:d370b8d1dfcdf7130178137f6fbee6140774a1acc6cacefc4b42643ec11d0a3a", + "sha256:d38cdff612d06fa6a32840d5e1b1f7a27cee4a349aa9085d94a67789d6bfd408", + "sha256:d8947001be83df1394050758ce0e745dd74fb134eef0a4b5124208dfc3a68c37", + "sha256:deb9fde5c60e437ee4821bc9bc39ff31b42135c27e1dc61ef0a629389c1de62e", + "sha256:dfe9763530994147d9af1def057a5b9658b00e8f8fe8743d144d1e0911c2e454", + "sha256:e105ab60406787da31fccc883fc0f733af1efd78f0136a4599692c4083a73d0c", + "sha256:e275096ea1e60cc595cda2836fd4a6c725d1125108b868be17f53684d164e2cc", + "sha256:edc3342adf8f697fc5f59c887a304356f147b397809440ed64e2fa6af2f50f37", + "sha256:ee247f5c245c9a2fe7c8e2214e295918838e44e00a45a6718451e4004219e767", + "sha256:eef4c2f3423810b3070ab391f85436d2f8bbfcb286ac15cbc73190b3563b1f1a", + "sha256:f21e8a22c8605750c7af886bab299a363721264061b4ac0a30efb73cfd58efc5", + "sha256:f265528741e048bce55c3463ed721fb0aa45a5888d8add8cfeccb3035451bbdc", + "sha256:f2f9bd7f90c64fe89253f0a2c05e3c4856072660429ce8831b4235bf29403a67", + "sha256:f785f6161f202ab04d8ca194158968798e480ca058943907972da5f12e2881e8", + "sha256:f9f6143a8c75945eb960d9eb98905a441394abfa24afaae239d514ffb2586480", + "sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb", + "sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b" ], "markers": "python_version >= '3.9' and python_full_version not in '3.9.0, 3.9.1'", - "version": "==50.0.0" + "version": "==50.0.2" }, "dataclasses-json": { "hashes": [ @@ -1286,11 +1500,11 @@ }, "filelock": { "hashes": [ - "sha256:87dd94cf281e586d135fa51132b8e3d9a598b316e90377a288663c9321036c82", - "sha256:c33351e1f49cae33414acbc6d56784e6ecee82514ec90795da1161fc4836b5b8" + "sha256:635e7d67fa92654eed444e75e9ca18426d34e77ad9c469bf4373f75a932f7b22", + "sha256:9287fd61b99a806e5202be29a83034c0808a1b9830e820537c2f5773981f7eeb" ], "markers": "python_version >= '3.10'", - "version": "==3.32.2" + "version": "==4.0.9" }, "flake8": { "hashes": [ @@ -1315,19 +1529,19 @@ }, "googleapis-common-protos": { "hashes": [ - "sha256:28a1934bcd33b9c9da66ac301a0a4227e3367f095a17d0375cb98f0a09d93b79", - "sha256:d3042c6c5a2d4e67113104d6b6818b59b6bd92a197f2a91508e801fe815cf071" + "sha256:c7a866fc34ed29a3b10af627a4b9b1dc2433313ca6e959f0ae4feb132047ed72", + "sha256:d7285525c23039db98f2463e6d5a4f9b958b94d497f03a844ece3259c4e72d5d" ], "markers": "python_version >= '3.10'", - "version": "==1.75.1" + "version": "==1.75.5" }, "griffelib": { "hashes": [ - "sha256:762a186d2c6fd6794d4ea20d428d597ffb857cb56b66421651cbba15bdd5e813", - "sha256:cc7b3d2d2865ad0b909fcc38086e3f554b5ea7acbaa7bbb7ecaa3f5dfb7d9f00" + "sha256:1b8f9cd525681c26b1d6d574faa1371651e8459ca51d209684f50b8096ae06e0", + "sha256:7b0952caf5bca6afa4bb5ee8c6a2d183fe3f21b62efc5f6c7243cb2b26d2d115" ], "markers": "python_version >= '3.10'", - "version": "==2.1.0" + "version": "==2.3.0" }, "h11": { "hashes": [ @@ -1355,19 +1569,19 @@ }, "identify": { "hashes": [ - "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", - "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842" + "sha256:6a16b69b93187244e0548cbfd25b3e4a6f9a7a2ad784625c3bec2b8d27b81aaa", + "sha256:ad729860a923858d26917c2f4fb0a1d83d27a75b1e090c06440c573f048f3285" ], "markers": "python_version >= '3.10'", - "version": "==2.6.19" + "version": "==2.6.20" }, "idna": { "hashes": [ - "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", - "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848" + "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", + "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c" ], "markers": "python_version >= '3.9'", - "version": "==3.18" + "version": "==3.20" }, "inflection": { "hashes": [ @@ -1419,11 +1633,11 @@ }, "markdown": { "hashes": [ - "sha256:3589362618f743188b4d955b874402bc814f4f83f544dc207719f4baa7d9c45f", - "sha256:fa6c92a00a4a3c98b22728c64a935ae1928250ae65058a6ded814d2cc29a4cea" + "sha256:180224db6aed87ba9ce1f2781ebcd5826253de8ff637112090e24b84502bbf9f", + "sha256:cd6c89e7eb308c8b332ed673215a52d208a43f8bacc030b1419376129408719e" ], - "markers": "python_version >= '3.10'", - "version": "==3.10.3" + "markers": "python_version >= '3.11'", + "version": "==3.11" }, "markdown-include": { "hashes": [ @@ -1609,11 +1823,11 @@ }, "mkdocstrings-python": { "hashes": [ - "sha256:30c837bbff016549f659fcba6539ac351303f0fd7e713c89a040611072236e9d", - "sha256:3a4d92556ad39637e88af94a5374213af9a8e3040c3824ceaed04b486c017594" + "sha256:ae945637dc0618c6beedbee169f10c0234b77f322c53db3fc9fb4c29b3013038", + "sha256:c0233eff3f84d78110df50541918e7ec2bcff8e1614faddea34290a90321a416" ], "markers": "python_version >= '3.10'", - "version": "==2.0.5" + "version": "==2.0.9" }, "mypy-extensions": { "hashes": [ @@ -1633,187 +1847,206 @@ }, "networkx": { "hashes": [ - "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", - "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762" + "sha256:e3fd2c13a7814cee3746340d8d7f8598a67f16a58bf47fb7f8793fab6efca1b0", + "sha256:fd77a511bd90f39f3d016351345b52cf5319b813bdca01de3f755d3cca62e96a" ], "markers": "python_version >= '3.11' and python_full_version != '3.14.1'", - "version": "==3.6.1" + "version": "==3.7" }, "nodeenv": { "hashes": [ - "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", - "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb" + "sha256:3ce8fe5b71d16e8af7039ca65257354100bc772965d6bc549070649e53b1b146", + "sha256:edaa16e6c14d7cf395d75d4bbd5a26390f4dc06501a33b4e76282b02cc688a25" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", - "version": "==1.10.0" + "version": "==1.11.0" }, "numpy": { "hashes": [ - "sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a", - "sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f", - "sha256:07d4e89f3a9ab0a9ba24264ccdb642b3dd951b2281e8883a5481a4aa79cc31a7", - "sha256:0a4035ae1129ff8777f08bfbd44f1e5d8e9c049ce0c2dd78fc0d92c13e7251c0", - "sha256:0aadf13b60048d501e05fa699efaf7734e2494f3498a4c2a5521d822640324f3", - "sha256:14e373cfc6387177e8409dac3c7159be8eb05cd77096cd7c950268b86f62831c", - "sha256:1ab3d4a901f844ea836c3e80bf463c6a27d7f3c14e8e292fcf28d348b25b9bce", - "sha256:24b9dc2e3d84aa58523798805194e23e736f3f6ce2d1a5b92583ae734e6dbda8", - "sha256:27650bb0e7140fa3d37b9923b4803645e0b125d190f326eecfd3f4dad8e8ade1", - "sha256:28ac63476ec7651484215ee7fa15a1f78b57c14621f01e392afe17b9a1390ce4", - "sha256:29b86ff8a6cc556b47ec6b64b194815cc80e6bf5eedcc6cddfd65318cb0b4eee", - "sha256:29d81e97f668489cba8ebfd796b9bdd453525d35dd9e162e2daec94bf3fc7740", - "sha256:2cc779226e476d1e1f08c74068c419e60f41a9e0e069c92f6671d31d5c985e98", - "sha256:2ffa7bacab3e2ee1b19ed31766bb60bb380b68c23f051e199c5cc598afd68710", - "sha256:318b9a4c845dbea06708a29c84ee429cc3065048db34cdb799047643492050ee", - "sha256:34c319e2963be042673fb46570501b2f06c41924e17e3563d58646b4380dfb68", - "sha256:3a2f061cebd9e3d23bdcfaaded5e2293a4c6a5b60fa42df85d410a725ce621bf", - "sha256:3cdec01fa790a186d430433fdd4d4ffb70eed6f0eeb4bf05c8dbe2dce0a9bcb8", - "sha256:3e4c367352d3747784248a227fbec218e193b56f7e6692e3b64fc805478ecfdf", - "sha256:40f4d451aed46a8046a1aae41c4e55fb3612273df9c502480135e1501576a34b", - "sha256:44ef9675d908e65f9953063837c3277730f3f4437615a4cdab67b366cabaf884", - "sha256:4bbd96c833ecc8cc069ce518078fc8c60cb9cbfb0fea5b7a803ad65035596d03", - "sha256:4ec954036759bcee3aa484f8603bd9c14f3e776293b85578b8734c2d72777c69", - "sha256:4f9744f9fbdcea0bc552e8f19e1f141f811a3f9bc2be2cc6e86d982cab23e3f4", - "sha256:50a68f4bacd8a2b33d8da3d2269d0d78500f86ea582e4786dc10f5ef2c2c6842", - "sha256:50e500dc868e9313530ce12ba470fe50ff3afe3d62993ed6eff652dacd555b65", - "sha256:52c808f96484f5571a5cc863775ce50247c17dfb3b0361f8ed6b4b0456f80080", - "sha256:5f8e00be2ec6f45f4e8a41a527f68d44a7d96fee92a650e4d8b1326f77f61e6e", - "sha256:60e902ac295855348a5ca2ea4c89108989a9f5fddfad3dfc0a8f36b10358567e", - "sha256:65f188481f1669e26f62b701e8205d19e460fa4a9b52a1414ba382330e4a3414", - "sha256:6950c4b7dd562453090548ba7f5da7e59f57f85663f15d5dcc60e249192f7e59", - "sha256:6a9bb119fb8dd21ba30b3f0e555b7e2b081bd9883af21ec9c1c633d161cda3a8", - "sha256:6b588cc8f902d6bff201c19fd00c43ab8545671e3554d014e12e14139e5e8617", - "sha256:6df895598c0edcb41030126c89e0f353b07d93238116143b7405e937359736c4", - "sha256:6e8172ddfcf5cf74b811d372b570b83c60bd2de87a6fbfbebdadb4a9bd9c6cbb", - "sha256:7354826bc6f8f69402e9b7fe28d15fcd34feebd74f856f111585c5b0c9fb0251", - "sha256:7587f53dfbd5edc0f7b87c6217b4c6d2d1f2ef9c3da70bc1315e7db5f8d7ec9d", - "sha256:77843ca236b777e67f8d6b3660ea116e499612703a0ecd7093f316201eb9d8e2", - "sha256:7999d4ddb0c4025018373fd787510d46e04c769467af22869707b3c1cfd459ab", - "sha256:85aaccb24182c25df891ad0ec333585967e115269d5f1b17f2c9ae005bc96657", - "sha256:8e4cb9a754c8a0c62eaa88273a5fba3391f4a610d1dee893c0755da31c083f15", - "sha256:8ee9c4eeb8454b3660a8b53493563c3e121c2fc94fbd72b848ef814ed7b676a9", - "sha256:9a0731745a72a184490a582fb4af2533512bd071ace67785b5fdffc0ae58dce8", - "sha256:9e9413326d726c2545bfa65d2c0876871e8d8386e77f992c1d426e180bbd4323", - "sha256:a610dc7e3c52edd39c2bc2375ff9c3fd59cb3ad00e4472d36f83bc1457145788", - "sha256:a839318485284a6fb31be4f8f2c91c8f2cb22f4543c4a8903f12b0671ffe07cc", - "sha256:afb3f0632d6b2e3ba04dbce8d1e48d321b369138b73830b5ca371a0e8d479d56", - "sha256:b879fb674276e331513fb136b78dbc6bd3c848309e0d841cfd63be3896c4cfc1", - "sha256:b9727f472d2f3888053b8a75ab0cb94745a9de224bb5846dbadc0092101bc71d", - "sha256:ba0a474801b8dc67b66bf465548abc90e82b44d2611b5770f33008dcabffe8ec", - "sha256:bd68ece1553d2023c09a4226d9e41c586ad2d20594d1a456186c33513d2cb3f2", - "sha256:c081cbe16ba1ab53078e5ff29013621e33c509eedab055775d956427712c236e", - "sha256:c1f017dc0875c9209d219f97feceb7d54c2661bb243deb4114478e1295808af7", - "sha256:cebc2d6dbb605a7703d59751dea4bd6b0ab127a5a4338a6f432df1936fef8b26", - "sha256:cf7de32f486e4ac9e2d93b810f9e9ac72a728dd46a32a0bb403222f27f653514", - "sha256:d482d171c406ae88c5b19cad3b6a1c4c5209f886ab74bc44c2c865c23f52d860", - "sha256:d6a48072864e3324e194a8fbb3c657bcc5b5c869dbc64c9537b1d5c862572c0a", - "sha256:d787cf769c3baeb5f6235e778edb52c08dfa923789b5958f28e6450f96107cb1", - "sha256:dc649493697006bc90614a5f0bbc8cb3cb1866715c474e473694968d7e6b99ab", - "sha256:ddf47472af2e4280d79bac82304f5e80150211f1b9e614b760061d5fdfbb6eba", - "sha256:e5651f3f87add730ee6608d915009e19c911fba0cb000c7e3ea994b7d768eb12", - "sha256:e79aba74ffaf5f78a050d777c184cddf8fdffabab38acf5f3ef1fecbc17895d6", - "sha256:eaa088384c46f519dacb93b7ec483a6d6b19a4a2085ae4f25ab9b1c43d387d1e", - "sha256:eaca7ff36f0f52e2111ec71f169d8fd3e889e7ddc0d2592e0d703fd8d3ce8fac", - "sha256:f06571a052127dc1b4e8b83029b4d1b20daa2b64a31cdd181fc6bc774e9000eb", - "sha256:fd0d703772bba096843785bd38371e31bb4a0c1151497ad5739d182114a73f7f" + "sha256:012e66aca395d795496446e52aeeb5866312a5d4d3f27da270e5a0b43f70dc5c", + "sha256:09d5a423c71ad5feb5625844ad58050e35df43871004b52ac9c0ad44a56775be", + "sha256:09ffa5d903faeaa5c4dd05009cf81c8bab9f2cb37c548b8d39b65b4cfa7c97f7", + "sha256:0a59a421a32580a009e8a1751345bf829631b990dc1794b80514ab722b435def", + "sha256:116f96cadd935c6122e9228d676fe7ede19e741f5c8bb1c3cddbe0c51ccebea2", + "sha256:1302b90c0e52281681b2975adfe8a860cb7b12216a27b4b0b4207c44bf7bccf0", + "sha256:15aa985ac73a8db02db7663381aa109510449d3819d37206caed27b33a65a8a6", + "sha256:1aad64d99730d013cfc6debafed22783b4fc5a7f4b8bc744d2d8cf7dcc880551", + "sha256:1c80eabb4035ecf4ca9cd49cde8a9fdd69a729e63e6474887d1523ade7aa277f", + "sha256:1f3ed25271581281f2fccb1adcedfcde4c07362eec69189b50baf6f90e3ae159", + "sha256:1fb6f8fb9ff0b3a69f52c66ce397b0246583e9f28616231b0e32ca49259a5fa6", + "sha256:214045a5bf00113a146ab9ee9730c44501af6723cdf1f6830932f7b5ef2e7af0", + "sha256:26e15e4aecd8617dfbaecb37d223e365d7b39411fba20454be2670a96aa74cb5", + "sha256:2c25dfa72943e4336ddb6b0ee4277b47a0c85bede0807530ec68103bf58e2c10", + "sha256:2d8240cb4c16fd831074aa2b2cf9fc54664d826341d61c372245b96a74a49a9a", + "sha256:350ba9783ce969cf9f7ce6e6a9a58e1a6e2a19ca025b7ee448c4db727706212a", + "sha256:4c8a6d2ebce6305fd82fbefca827775437147052a976ee7c94b36a0c1b52ac6c", + "sha256:4f8929ee6c96bfbd7b4ed2032e0c03af86fe1826740ab61ddabf9072d06e57ff", + "sha256:536f963710a4e63934d80ac0dc4f478804a83e9a84b6828018f25d09953ada33", + "sha256:54a115e5a73b8fc44f0cebef486365a1894b5c9760685d4558b72b7c3eb846e0", + "sha256:595d020938c84e320bcf40ad71089e108eac0d377cd018e14a8c094f39e98d85", + "sha256:66a78fe4556c60aceda5916f9eacd638b18e9e681016ec302dcb4682d6d4d034", + "sha256:6b05c171afb3aa07adbd20abc00aea86fe375beb0fdb9ef780ec5b7f63bab1c0", + "sha256:6cef4bb1706dfec49243c05d921eefb4e190d41e2528b30d8035ea1f36b4c24a", + "sha256:6f24021b9f22bc6301c37b196974a92c1c18dccedb6fef3dd252e95f2d6adbe4", + "sha256:71b39d9f935b6ec0f8753e3e2afb51e3efba6f2e05b68b32a40754d24bcd4a3c", + "sha256:71cad2b2a7451ab79d8f5e71b453485b6775963d5cf794179144a7463fe6e8ec", + "sha256:76c2c1e6bfa5c84adc6434dfbf013aa92096a7985221762c8f11fedfd20fff58", + "sha256:8617bbfae4486cf99c9f899966699428d19da931d06ca94ad3da986c76e15997", + "sha256:86bff898a431c0fb71f7610b75726e75a54d47b37edc9d537f48de63bb3c0b90", + "sha256:8e4dd766076855b5ff7ea52fa5f07ce26286726e0f8bff446b7739d02e6ea204", + "sha256:92f30e89b8ee0ecf363033576c422b2f58fed6a80bed0aa48dff6d14c654663e", + "sha256:93e1f5447e2b1e479d7bd74701e84746b86450cff1fc368b132d195e2b8f8211", + "sha256:9a37475425b431b4d060f23b4f52cd2f3aef6bc7c654bd760adf0040eec9d435", + "sha256:9deb49575e5b0b94ed72c8a64ec4d033381adc27e9060ae842971f697ba96104", + "sha256:a5fa86b80fd24bcd1aff83ad23be44ea323de3f787be8f8b15d4a65621e25321", + "sha256:a6391fafaba97500887132cd582abc6e19452b1ac775a47caa7b24490e152058", + "sha256:a72f874bc9e10e4b8f80426fb49716d5141f64442a0c8418065093ec8017fbb0", + "sha256:ac7bb1c52d445bd4f8f7f97fefe6abc3a084dc4d63df50d79b17fa2b78e89297", + "sha256:adc1ada2662f8a5f960b8a10d9986897e7499ef07e06d4cfe7197f8cce923c07", + "sha256:b00eefbcf0f292945c4b4dec2ae845389ef5bcdcd596e6e4328051db5b5ba694", + "sha256:b0521d0f4aebb6e06189451025fa17a913287b13c03d5fe05c017333b654ea5b", + "sha256:b5d93cf48f687479941d12b69c873ad2cc76bbd487f0091c2200636497f34034", + "sha256:b7e18c623bb5c95acb3b3328861272816ba199fb531921c5d6d0b675f1fde9e3", + "sha256:bd4cb9ad3c7889b9b3fe0a9a9fb5d2ed26f9879bff2608d9f01aed147a20d231", + "sha256:be5a8381859b6da607c84f4f7d6847725f1cf1853ef8a2c9e115b7d58bef47dc", + "sha256:befa1ae5bd6030b3f512b43ff3fa5290bbed6b84411a44244b14adf835f5b89d", + "sha256:bf63afbe037eb5d2fe87fbcc7778e61da53ebaf21d938a4515aa73b62532a5d4", + "sha256:c00abe94c1a69d75d827dcf1c025b25c8a45d230b3bcd77a9020883a1b047653", + "sha256:c2381f82999704f818e2c987a865050e285ec3621262c66d40f5a96c8f899f8e", + "sha256:c76d5dde9f445058f83d0c02af00557a4db91de9a9a57c0df87d1535001d654b", + "sha256:cb189f09db39283b26bfd061ec16189e14f71c6755207f72a0f7540867afe5b9", + "sha256:ccb32e0525d29e8b0572eb84c9a57af0e7a4e615726927506f55063c62414034", + "sha256:ccbc4665079665c3cf3bab4db9f6b095370cd6437d66be549b6c2a1fd19e1958", + "sha256:d1c89973648c85069c5046ad460f7b8a00218b29a2e42359ac8cc63e9ab94832", + "sha256:df2d5874ff183595a4ba404edd04f6bd9b5505c1d7708573f6a6c17489a67563", + "sha256:e01c918ac3d48e18a927cf7b14a26a3e29ff2bdf2eacb976da0aecd6a43ed034", + "sha256:e6ab667ba76450084eb64013762c438ea76d9d29cc676dcd6c2e9892ba37f841", + "sha256:e931e4f499e0dc7ef29d269a8e5b35dd722e5d14be07df6240166ea7c6532fae", + "sha256:f54660b0eb6b0b9f36e7fe1cdfdff472028dd0d14acd9b9b65098efbad059469", + "sha256:f59a878c33d6b88122d80d239bb3b845d58708750b0cb06a09aebb9b18ec696c", + "sha256:f7fabeb6cea87d65f3b926de33d03fb016cfdc29314c90974383b5582ae72891", + "sha256:f9579f383d1bf9df80081e72760e84960a7fd4f88cf0c9e535a8597c9bb646f5", + "sha256:f9a2353b37a1a9e78fd82b27ad7e2a32a2d036604d18f02b05e3136c62ca3b09", + "sha256:fc36dc566135b5eceec4cf89758fcb719266a019ef07dae1754ae7c9f617ef3e", + "sha256:ffdc76bfcae6b255dff75202c5e7feaf95b40246bc0a17944facc1fecf9f79ab" ], "markers": "python_version >= '3.12'", - "version": "==2.5.2" + "version": "==2.5.3" }, "opentelemetry-api": { "hashes": [ - "sha256:67647e5e9566edcf421166fdf022b3537f818635daa852b289e34604dc6fb33a", - "sha256:94b98c893a91b88657eaac1e3ba89618cdb85be6918196705354f34728b2cdef" + "sha256:711ede81773c8025c2c03dac0450bc89f3d30aea6eabcc815c570d4e35a963f7", + "sha256:80e068aba7cd56c8b58512d6a36f8d25cb1dfaa0c0a4cc1c938ccf9f362d9cb3" + ], + "markers": "python_version >= '3.10'", + "version": "==1.45.0" + }, + "opentelemetry-exporter-http-transport": { + "extras": [ + "urllib3" + ], + "hashes": [ + "sha256:2c229b6593eaa22c86d9b8a15843dc23b406dbda00fb138339189aab07923b4e", + "sha256:c82689928a11505a2a0a26a04afe0ce06d270d3db984bc16c1a80ffa902db00e" + ], + "markers": "python_version >= '3.10'", + "version": "==0.66b0" + }, + "opentelemetry-exporter-otlp-common": { + "hashes": [ + "sha256:35d24c867310f4713a9738b0202b6bade77955418fccb9e2f7eea01b76263916", + "sha256:362268ec6aa705e183776ff938539df1e8ce45bc5509d242538b1d40c26fe6a6" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==0.66b0" }, "opentelemetry-exporter-otlp-proto-common": { "hashes": [ - "sha256:9a9fe61bba73d802904bc989f1d6b4a7b1ee40f06c40e98d6f85af65aaebb694", - "sha256:dc87a5a5bc58f149a56d1547e4691588fa12994cdc3bc039a694ccb3375862ac" + "sha256:36495115a0c6a7aa946cfda9d59b6ed4e917b6ab0f75cdaf66bc1b176ec1be1f", + "sha256:7e1410ae6d3ed301f7a74bec96467d519d3f37e52f9d95b309ae125e5a1af863" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==1.45.0" }, "opentelemetry-exporter-otlp-proto-http": { "hashes": [ - "sha256:838592fce774c1c8bb7b9a0a7facbfa82e17be5a8a4e94cef10cb84ae026bae3", - "sha256:c633d7270ad6b57cd4cfbe8b0007a9e2e7c0cb50bd6c50fe2a7b245f721a09d8" + "sha256:2f35496d96809f946f41b8805e6b93aec6c9b71b5fd759b75b6af4c084d992ae", + "sha256:74385f99266dafdefff41f3da4b76f6dba79d237a9d4487e6ff1ee653c74a0a3" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==1.45.0" }, "opentelemetry-instrumentation": { "hashes": [ - "sha256:071d9d9eced9bd6460444ec3b0c77229870ed05a881c22c84fdede58e4eed09b", - "sha256:ea967a72b9939b5fcfdad572753b4306c59dcb99e3f382d95dae04286805e137" + "sha256:0b32e2fcfec1e4bd48511a3b77ce32bfb1c16dcd5479396b21f9086a4b06c0c9", + "sha256:316715ed7b33a12530c0ae3e8d4cdf26d70e1aad358d7ba256e5dea2d4ceed71" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-instrumentation-httpx": { "hashes": [ - "sha256:400f1b78afa4ee2332b5debe58e1ed1b317913d58812c952576be76660aeadb1", - "sha256:4627aa9c6bb99bf4462c8b565b0ef6aeb9ffad95c6c92868be1ef7895de112ee" + "sha256:2735d1868749ca04ce47a3802b0b809e3a00c05a65140e05bac5700e74410539", + "sha256:c89297975f54d67692d3c29e9e33a1bdac47710031cc3ed0d83a0c9765336981" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-instrumentation-requests": { "hashes": [ - "sha256:1d601548f89236d5ab373c7208a2e1e162a8d6462b5b972f9ad8fb0ed82d7438", - "sha256:91688ec0d4d1fed75ea8d026ef2c66274ed9868c22b6be211ef85d832d16f957" + "sha256:053dde08fbc1d223058e33d477cf81e2bdcbe7af3893787283339b2b557d4b7a", + "sha256:2f9df08bf99f5da4bcfda70735492b4364bfcc5bd3f48232658e936f97ee1a22" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-instrumentation-threading": { "hashes": [ - "sha256:aefd23eb16c5e7a7c6c6eacdcb6c6f269ed8ed3a1b458bf5dd555b878bf58937", - "sha256:d8a1a1f35418a32769d469ef2d7e8401935e097a8553abcfba833da9c74736ce" + "sha256:4aaf38b96b47a04319b8d96bee4f1daa04e0d6c697525595746aeb61618c002d", + "sha256:4c1c9adf42b83b6f44ca4bb99799e066ccfb1869c2029bc73d862c40a8ef932e" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-instrumentation-urllib": { "hashes": [ - "sha256:8e7d1ada475296136815763bdabe683460969d09d93752c4f11ef0175598151c", - "sha256:df1b79e50d6d59f4248acc659bbed0ada8ccc8a028ee915d3fdeaf9140672b87" + "sha256:3eb6d2b9b28bb51188d77092a58eac2ab04852d244acb51333bdf42b0e933c68", + "sha256:a919d8014dcf0065ad42ce5c78dd158c76c7342929f451d726462f7ffa68e367" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-proto": { "hashes": [ - "sha256:898b155a0e1557afd867478fb6158e8122a46329ca0bb8dc53cc55e98f017f56", - "sha256:c547a79c2f8c0c515d31509154682e5921c7cfd5ca67b70e1f9266e2c3e103f3" + "sha256:96ee414f24bc3f61ea8e17dc56b4348d4049d73db3eb17c6b3edf75b5b403300", + "sha256:9731566359d7b8e1ee1e149d8e4ad6865bab965e657ad3387ec2784d16927666" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==1.45.0" }, "opentelemetry-sdk": { "hashes": [ - "sha256:cebe7f65dc12f26ead75c6064de12fd2a9052e5060c0272d402cfa203aae123b", - "sha256:df081c4c6bcfdb1211e3e86140376792643128a25f8d72d1d27675936e7e96ad" + "sha256:20caa5130505e386c67c3da1c76e446c842698ced54c76c6148679539aa97972", + "sha256:5dc634c946546f61b757c5b1781f9fd1a10e96ffaf7357c797e508fe9c57e75e" ], "markers": "python_version >= '3.10'", - "version": "==1.44.0" + "version": "==1.45.0" }, "opentelemetry-semantic-conventions": { "hashes": [ - "sha256:1cacde7b0ad306f84c5ef08c3dbe1bbaf20165bba6f8bff43b670e555a086bcb", - "sha256:f9b2b81e9d5b64f11bc952075e7e9c7fb0aab075c7fd1c46d597f1b919852d60" + "sha256:175b19dd98c4473f4f43a2b1df59186fd7b4a48cd3f77cbe03438b6d6fda230a", + "sha256:97a77dce484c54861e7eeff7651fd8a806dd3c30e501dc316730215ec36890e6" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "opentelemetry-util-http": { "hashes": [ - "sha256:7553b606f963097cb190536dc30556cce85090692e471a422fff30ca29b04348", - "sha256:84f82d826978bba416ab453460ff6a7391cdc3534c93a786595e4068680016b7" + "sha256:7f5e581e94f023b30995f700e41ce319cec82bd542ff1c1c7c9b56d6b10bb687", + "sha256:a2d53859630abe8e5abcc4f867c5a809bb95873033573b1a67f6ef43b57a8627" ], "markers": "python_version >= '3.10'", - "version": "==0.65b0" + "version": "==0.66b0" }, "packaging": { "hashes": [ @@ -1916,11 +2149,11 @@ }, "platformdirs": { "hashes": [ - "sha256:3a2ae5fca3520a01ab1be8b45613537f52ddf5b5f6f53d88233892dfbf0cd82d", - "sha256:7f89089b6ea71bda7962953edcf784b2e2d9d285b40ad88be2bb75c6e9d82ab4" + "sha256:29dbf06d96c500bc6bdbce75fb0a14d63279c93b1842f97e72a135b33e856983", + "sha256:eab5f70271a490ef74618bb314fbb86e3c7e82fa3b9c922c2ea0e0a1a155d329" ], "markers": "python_version >= '3.10'", - "version": "==4.11.2" + "version": "==4.12.2" }, "pluggy": { "hashes": [ @@ -1940,17 +2173,17 @@ }, "protobuf": { "hashes": [ - "sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799", - "sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87", - "sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6", - "sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30", - "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9", - "sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4", - "sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4", - "sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a" + "sha256:497d0463ff3316681da6c0b9e8d06cb465d61abce00b613ab42226175644d1bb", + "sha256:89f23aa53c24553a2416fd4fd1ec06f74fa42b14b546d8883128813f775bbfd2", + "sha256:912c1221170e16c08d1f086762f563dd61ff83c18b5fa6652952dfaded66f728", + "sha256:a300819d441e078a5608c0d3c709796bb548136058fda017ae51d425b44fd353", + "sha256:bdb3a345d48db958e6ce1f18e508beb0cc981d64f24088427549c866cd039f1e", + "sha256:cbc70b17ee27e28894c7fee8bb04be1abead49e936bc70eb60052531eee2079e", + "sha256:e11e1f0180583a2af89db6a2ecd9e8dc40aa6d2988ca175bfd0e6d12ea72d74e", + "sha256:f4fee11ec330d238b34a05c9b675f693c20415d1c5bd7d5320cc2f8a798eb9cf" ], "markers": "python_version >= '3.10'", - "version": "==7.35.1" + "version": "==7.36.2" }, "psutil": { "hashes": [ @@ -1992,7 +2225,7 @@ "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992" ], - "markers": "python_version >= '3.10'", + "markers": "implementation_name != 'PyPy'", "version": "==3.0" }, "pyflakes": { @@ -2005,19 +2238,19 @@ }, "pygments": { "hashes": [ - "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", - "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176" + "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", + "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c" ], "markers": "python_version >= '3.9'", - "version": "==2.20.0" + "version": "==2.21.0" }, "pymdown-extensions": { "hashes": [ - "sha256:db3943a62bab7e03af1364f0c4083e64b91fb097675a4b6cceccfbe9a77e5eb2", - "sha256:dd2905ae6fc5b75582fafb139a1266ffc754705efa902aa50067fa7ff4f94ec0" + "sha256:4a254b771acfcddc6c110a7f4590d818f1f849e2d5aacf69b4b07c8dd2a9700d", + "sha256:fdb8f47f5d7fd069d10ef2a7d8908e613d7865ff0419d544a0ffd3984e884f11" ], "markers": "python_version >= '3.10'", - "version": "==11.0.1" + "version": "==12.1" }, "pynacl": { "hashes": [ @@ -2052,11 +2285,11 @@ }, "pyparsing": { "hashes": [ - "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", - "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc" + "sha256:928ae7e20211f3b6f3915a72f06a0cfd29ab9d24279dd6346b6b1a7146397d36", + "sha256:ece8c00a69cf01b45d0b1dedabb469c90d8caf996d4fda40f147627a122849a4" ], "markers": "python_version >= '3.9'", - "version": "==3.3.2" + "version": "==3.3.3" }, "pysftp": { "hashes": [ @@ -2106,11 +2339,11 @@ }, "pytest-mock": { "hashes": [ - "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", - "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f" + "sha256:007cfeb257801d88d9c0b2a7b5a15a15e73b71968dfd72e7bf8c4a2f8393aec8", + "sha256:5a8395528b8f498205f3718f575228d0edaed7425fff638f87d1a6c3e0383636" ], "markers": "python_version >= '3.9'", - "version": "==3.15.1" + "version": "==3.16.0" }, "pytest-rerunfailures": { "hashes": [ @@ -2144,16 +2377,16 @@ "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.9.0.post0" }, "python-discovery": { "hashes": [ - "sha256:ac07f44cade589d954e9d6a1e1468539fdddd2cf676beb51da73e0f156b7c932", - "sha256:e2ea8b884cd1701f386eda8cf327b87743f1dc21b7f784470799537d95635384" + "sha256:cf87d3627dfb4412437fdd5b13eae402607722998d21567993aedbc59b23c15e", + "sha256:d43fcdef879fe795352bd13ccf8d185ba5a9f86f36cfcd00529f596e737442b3" ], "markers": "python_version >= '3.8'", - "version": "==1.5.1" + "version": "==1.6.1" }, "pytokens": { "hashes": [ @@ -2205,10 +2438,10 @@ }, "pytz": { "hashes": [ - "sha256:2211d3fcf9a797d3405cac96ac7f61d80e6a644f72a3309607282fe8a2010c5d", - "sha256:dd95840dd199baea12d9cc096a1d452caa6596a1c1e4b5f3dbd1541855d5e815" + "sha256:464303645bafafd72418898368b2429458f709cf1eb6a15372fbcc396b64da63", + "sha256:9d514388fbc89ca0833203464272ac485b8828568ab73532f5020f17e892a0ff" ], - "version": "==2026.3.post1" + "version": "==2026.4" }, "pyyaml": { "hashes": [ @@ -2464,7 +2697,7 @@ "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.17.0" }, "synapseclient": { @@ -2481,11 +2714,11 @@ }, "tqdm": { "hashes": [ - "sha256:55b0b0dbd97462d06ebee91e4dac24ed4d4702be82b24f07e6c1d27e08cea220", - "sha256:7f585706bfddbdebf89daac705b2dfcc16890130727d3197ca62c732b4310953" + "sha256:c293e525e6fef9c20e8728fd4612df02a0aa31bb5fe91ecd93e123b1b7bffa73", + "sha256:cefd0eca11b2a37a3aee776544d4f4ae913f02688135b5556b8788dfa474afc4" ], "markers": "python_version >= '3.8'", - "version": "==4.70.0" + "version": "==4.70.1" }, "typing-extensions": { "hashes": [ @@ -2504,27 +2737,27 @@ }, "tzdata": { "hashes": [ - "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415", - "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931" + "sha256:c2169a8b0a7a5e9674da5a135ccdfb2b3e671b333ed9fed17b41f73c34476e81", + "sha256:f1b8bd365d8d210c55353f4d7f8d6d8561c0ba50d704b700d195a9424bba0d79" ], "markers": "python_version >= '2'", - "version": "==2026.3" + "version": "==2026.4" }, "urllib3": { "hashes": [ - "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", - "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" + "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", + "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63" ], "markers": "python_version >= '3.10'", - "version": "==2.7.0" + "version": "==2.8.0" }, "virtualenv": { "hashes": [ - "sha256:376ec93cd6aab3044fa395d7db226db38043b7b5748948044b2a87168525e843", - "sha256:c9d960c95fa458171e58222a5ccab7465298e4b6559977865e627c4719f1e825" + "sha256:2d1a394ef089220b4606408b184433e49417a6e5590a09c7b8a67fb1e013af56", + "sha256:d7f167214b3c4f69df5386677dae5091dbc9c400fc46080187ae28064c9d453d" ], "markers": "python_version >= '3.9'", - "version": "==21.7.4" + "version": "==21.14.4" }, "watchdog": { "hashes": [ @@ -2564,99 +2797,110 @@ }, "wrapt": { "hashes": [ - "sha256:0a45ffae742ce91a16e11cb6c7cd71e7f9994f3cbd283b962ab093f5c6dcf525", - "sha256:0bb2797048db0956348cb3058c33bc4184614f13231389cfbccc16a5d32780a7", - "sha256:0d3fb71e65b001adfc42684522eeccd9c21d8ba679945abc993439567b66e59f", - "sha256:0db083387d6e75ec0be8173ecbf0e811cf60bae1cc75a815feb104167ea10d4d", - "sha256:10461884b3014fbfc8eb7d09a93c5f246363e6711d9d881f95eb8c27fdef049f", - "sha256:1236fa25173ca964c97422470482e9011b9e3c7ed0d75798b40b3da3b0e0e760", - "sha256:141ed6211286a9660d8d6702de598b43f0934b4f0eda16393f100a80f501d945", - "sha256:1598becd30f8f2777d18564064eb4f4dbe1ab0e05a8f09786d0ef505ac782bf3", - "sha256:195b1842b4122fb54e3cd3dd5b2b4aa49302a5a61da901df0481f5c97aedde84", - "sha256:1d6159c9b2fefec02314e1332dbbbfaf960e369dfd26bcf7f8b258b5732065b3", - "sha256:22cc5c0a717bd4da87018ae0bffd4c19c6fb679d3ff357216ba566ab26c76cab", - "sha256:242b60c21e30866e6a2fa606c612b47c553fa60c0eaeeeb7797fb842ac0ce609", - "sha256:24da48596326ef8e448cfa837b454f638713d3531262375f00e5a9681682fc07", - "sha256:261f53870cd4fb2bf38f9f972c56c728fd224cb7c65721307de59d9e7e6741ae", - "sha256:2935d5454b3f179a29b12cf390ee47246740ba2c3a7545b1b46ba31a5f2a4a0b", - "sha256:2e49885a62ec4ee854d1b9e6371fda6afd219917225752abf729a3f36d4df9a5", - "sha256:379f670f45b7bb8993edd9f6fc36c6cc65edb81cffa0b504be34acb0303fff0a", - "sha256:3873c3c5ca9f4ef91f693602eca19d1f1e7c410338df82a4ff11d826b5896a8f", - "sha256:392158c9a7f2ab1b8699418bfc0fe6f83548788c418b27d7bf2019ad3405cebb", - "sha256:39febbee6d77301d31da6996b152ce52452da7c7ef72aba10c2fa976dff9c295", - "sha256:3d1c2c1b808600d2ea808e6360910a60ed5f409a4011655e10f9164ba0a414a6", - "sha256:3da470536bf9645143323dd41b32db55c6f4304ad382094c1a1da8a92061e10d", - "sha256:418f54bb09d1762db02c7009b4051149893af3153a87f92d70356703c11eea02", - "sha256:42869085687f0aefd57c0f636c3f9354f8ffb321a8ba9cb52d19beb796e561c5", - "sha256:45c9279b373d15649dfa2c2077cb3408ea1a6d3125afbdab9d6b809a66f68e14", - "sha256:4fa0df3bff4e7ce45759f33fd39335fe2f60477bb9ecf7b8aa41e7d07ee36a23", - "sha256:50f416b74d092bb9f41b424e90dd457f365f7ba4b11de62a23679769a21bd85c", - "sha256:51a7a4181c1295774812271fbcd7c909df372bc25579d4ed9eb875caaf0ae86f", - "sha256:54ca1d5573f69b5fe1d74f1f65799c68015e82f685efec9fd8cfa40a094c44d0", - "sha256:5ab559e1b2551d23d54db2a0001c6d73bad022a254639561c5f6c382a9d6c2fe", - "sha256:5ba1e5e08ddc46130e9682b2c249f2d1dd39bda9106ed4bd401b7519f18f41bd", - "sha256:5d221a6e6ddd302b8397433184e96b59f259f50024b854db1c411a881586b6b8", - "sha256:6208f302f110295d64b22a7ac96500c791bf492dce4366e622e4912b077c9687", - "sha256:626b69db2021aa01671ec7bbc9740e558522bd44c18cf2ce69bf3d666a014109", - "sha256:628f3ba8ec793a5b10a6cd8c6c6b7b55eb552abd1f3bd301336acb74c7a82dfe", - "sha256:629d73378082c00a8173031f9fb30a3ac6abbc894a5bfdfae71fabc60642d501", - "sha256:646d20d413ffcd1b0a2f700076e2d0252d872dcb7754860a73e45a59ea883614", - "sha256:67bfe2485f50368c3fcd2275fc1fd100e350d601e0058921a7c82678a465aeab", - "sha256:681a2d0eefd721998f90642762b8e75c2159ec531b20ad5e437245ea7b06a107", - "sha256:69e477046f2237ef0bc6547544ee73008dc764ca26eff44f09e976d221b34d5d", - "sha256:6db604ef0c67bdb2042ecdfd7b7f037cf09733557ca42360d1018285634f7b98", - "sha256:729126e667da34d251b8ebf8a45ef0c5ddadc21542b3d6e1abf4259ece6508df", - "sha256:73d0b10b64620a2cf4bc3d31775c4d9527e309a5549e4379e3bf71e8d2dc193e", - "sha256:7ebb274aba688b043429eb1500ff8a76ce0cb8ac0812ca3e301f06247b8722b3", - "sha256:8159ec0b0cb7608175eb150de94c19e34f4d47ac655f5ca9baf45df6b688ffd3", - "sha256:816877aa749253149f9ecfd2635d4d948ecfa338e1a0311d187b1acb1bb8a3eb", - "sha256:85de890ff968196e92dd1ae73a9fb8970495e7650a457b1c9ef0ac3dd550bce2", - "sha256:8f8a1c6472675956cece9a8f403f43c3594f1681319eed2dd56f60877397c636", - "sha256:9045917809c63fdf7abe3a2ceaed3d670b8ee4500ddd9291192d30aeb34467c5", - "sha256:932dced0a7b2950ed58a3325536a1dcb7b58e7330af54e8552d2e566b5328b99", - "sha256:93513bec052c6cd987f9f580c3df068c8bc4ebae6543736be3ca7ec5959cafcd", - "sha256:9790ea25190a4e0fe4cdf4eeb868e9d75f8a024a70a5b6bf9c348a3a2b72e731", - "sha256:9f5d2aec29dfc76c37e23897dee92766a3fd4f3bff3ae7fc9c6b4bf37d8c1360", - "sha256:a65e8db2b4e90c2e7ade931086351c98ef420bf7a94ee08c95ac8a3cbbc43579", - "sha256:a6b5984cd65dd639546f0eb4b8eacf1c31cb2fe9fb5c27bffe240987cdb2cf84", - "sha256:a6e19531ae33c508cea7d84a7edfda01fa86e51b8d1a93a77712c55e6e469152", - "sha256:abc71504669d126d91f89fc0e388c6295d8fbd2439be884f175133fda8aa403c", - "sha256:ac870cc97b73bb00ac353329e9559a4bebc47c4c86792ed9b23b58c15b6ad838", - "sha256:ad71df7a04dd3497e9302e81f4a7c91bd401ea0e15a9df9029527900f94bee43", - "sha256:b1e5aa486e269b00ed35e64771c7d0ab8096cfd2643405ca8cd60ebedc099a51", - "sha256:b4fc96b159af0a3e0faa72475a69d66292bea72a5bed1e1aca1bffbddc3cb2b0", - "sha256:b767a9566f165dd14decf8f4194c6bb0ce3a8420cec213824e05a99400c9260a", - "sha256:bff9a671bc00709cab5a7f745c592b5671873449db0ee2a569af994f16b29a4d", - "sha256:c3b476ae63b4a3b4da681aafcb25ff3542d289fbda8b5da7caf76aaffafafdbb", - "sha256:c4bded758ad6f03b965830944a2f0bc5b2eb3767fe5a7310134315d1a6610e98", - "sha256:c8388ba7faf5dbf9ee106bb70d66f257629b1bd98091123e19e8a4553a319199", - "sha256:c8858d8ff9822a081e3cc49ae1b3b22f0f789c14001cdac8f94564010d9c9d66", - "sha256:c88abcf53daef80e01a75c7530e727fa6e2c1888fe83e3dcdba4c96216a1f5c7", - "sha256:cc2cea812e5cb179a796b766747e7d3b21088760d8deb95676d482b8c8e6fa7d", - "sha256:cd3a2edf0427013736b8127955cec62608c56e53ea47e82812ea32059cda407f", - "sha256:cdc021cb0b62471d6aac7f2bd92f3b4658073775f9ee7fcd325c511129e7bcc8", - "sha256:ce9f398f868d2b3b27aa2ea4de79645ef9077aeeac8dfc2814b0d542c6a2b87f", - "sha256:d0077f3d65541925fa83002f967b22ad6550d24813ac64cb905f717194128d9c", - "sha256:d0f7284f88f4833705132d06d3b425a43095c2cbd07c58166aac3ab646ba12a4", - "sha256:d2cc64539da63e39ffb9c7ede849b6e8ddaaf7b3876b5cfb04efd85a5f3f4eb6", - "sha256:d8c7ed08477429752b8c44991f40ad7838b18332a160698740a6bfbc10d998a2", - "sha256:df4ce31150bcd5d9f36f816aac3010ab4f4bf8672ac1d3b0ac7d539ec61c7c02", - "sha256:e045ff75d7d94900fc32896ed93c45ce2d2cac28c9dead582ff9a5a49d446e35", - "sha256:e2e692bc0d63f881cf7006730a56bd4e0c2fab5dc318466942805d692b166276", - "sha256:e31734c5077f29f892b2565eee5106d610278151ad49fc6a9d69a647cd5730e2", - "sha256:e3b9eaa742ae7a0aaaaad4ca4b69469d757af2d6e6663ef1dadc47adec0aeb41", - "sha256:e3f3d7ec0a51fbfe00d3aef047641ff2c58b25565b4717fc1f90e050be01cba8", - "sha256:e5301c35cf75655eb33498f2bd6ae8703ca19940e3167dc9cdf740c712a39c60", - "sha256:ea52a0d0f08c584943d5764be0e84efa912c8da23c23e1e285ff2f5641c18fcc", - "sha256:ed635a9ca4f3a5a2b900c10c69e823373bc00ebc114b459383596d3487da3570", - "sha256:fb8e2e6704a1e0b1b989546c69e2688371ef4a07fa5f61bde3eb6211186f5ac1", - "sha256:fc648a335d7e01adb3640b25f02fd0ea05886cf04d0af7f4ee902bc7b5e466e8", - "sha256:fc82c2ccc8e234c844f5303d9f2984b346dcdd53e94823ce8420d2c75b4b9023", - "sha256:fd1f2f557dd3491fe75905e578f4db967393d40d1a8f468edc4d40ac7f2d5944", - "sha256:fd85b0aa88efdb189d6ae2f35f4526943a8f091c38599c9c31478241c819e6a1" + "sha256:05246a100da68259af521b88788f131ba005465f1c95d358cc3c03ec5e351b52", + "sha256:05b7a271e21598694dcb7a6d6224f04e80ecc24b00a31ec57c658196377b0b29", + "sha256:0810e060e58f7960405172ad21080df8e7335841c9fe97417bd7d3f05af24f90", + "sha256:0a7a369e7fca9fc8c2c50df634382009b09af416853da3d4515e4bb048a5b9ee", + "sha256:0cabb9c17ab79b2549d1f23b36f436473ad9253ef53995a817feba26fae69d5b", + "sha256:0d245ac03f5ae77f1eea6eb19edd9e778c2f772490c20496c2f1cd3a102ee1b6", + "sha256:0dfc38cb672af51fc29696ba9c6f05d2315f5e62c4af2564e50f07f81198a163", + "sha256:0ea62bc142f4fa8b2e0ab058f50699ccd679ef6199c8fa3cc1c2396c7a659000", + "sha256:107eea1a511e98a3a5033b0c2cb403fbb37f05dee6ac1fb85c0460d311ec278c", + "sha256:1122f4f9e363da804ccba05a9f0f39baa3716eb82452c929258bc3f1420c899b", + "sha256:148052fc55013930217f531c6978e918ab210a12bd73cc9bd6de661a7adaf620", + "sha256:181a45000506a6382eb337354ca7e8525690702f1ccf2eae4f23a210ff339543", + "sha256:18baaf966bdc22dbdbe6e4323da8c17c0b7e8ea941dccf5426e741ae398953d9", + "sha256:1a3c4035d2026b87ef23dd8d165f1f8d3853ee2bd02791cfd22bd8c6226c41ce", + "sha256:1b35ef7379323a149a6398f6261248bf48b61666210bd69e2ab24a9a9afdedc0", + "sha256:1ccd22ef8690ca302425f26d4c3e8b24f1284d4351d20e49ce21f9c0dd58d64d", + "sha256:1d4da5f0e9a719471502b0db80d5c97503aeca796b7aeb9ab8f47403b2be76e6", + "sha256:1ebc0d09906057ada57a32158a657364ca40b8f86e604da3e7d979069b601502", + "sha256:1f17c5a3836397bf59fd57b0e5b0dc42969b1daa70d31aa361c6e13cbf138b5a", + "sha256:1ffb2823c95dbeb8a47fedfba9636b2afeb0a8ef94b66df97bd081bdfe5a263f", + "sha256:21cfe343ef9c2deb865ad0d5c57822266447c88dcf6d8805dd8c363fe367f30c", + "sha256:23a9d6cb6413359b76f030d6bbb75340b7669c69da245dde2919a4c93708993b", + "sha256:2ac82ef59ee05e259902bc7cf73dee5e6397845e8ccdc376d9d25536b59a877c", + "sha256:2e3d110d7f99644946f249927c346d9dba507a78815d1bcebdbf0d94c14c5649", + "sha256:2fd8a61c31220840c7f52621cf51c961af5058bd009a55bcdf4a6732bdb13b35", + "sha256:30cf86d1e35a57e772e4709a137c1731751255439368a41b1a2519561e385f4e", + "sha256:36703cafc2ec059e118c2175e6cb7ad7299c2924aecdcb1b7a7ebbf7a3e20c19", + "sha256:3f5dfb867d3f58fde0d850a302f1164bb83f4a922b037882bcc7e0474aa8312f", + "sha256:425349a99b8c9540399d36620c376dc26e6aca93071cd6fafa239c2f1b5d53a4", + "sha256:4343880acd72e74233baf092285aaaf4306244e31d7601828bd2600316027df0", + "sha256:439523506fd0d9af4f76d75f2e46aa4979e164fecba6890859326ff06edbaf9c", + "sha256:47abb2bb7f15b416e72fbe5e68e49a6f09331dae6af1ca6055f5aa2251d2bd2f", + "sha256:513dd1f4a1f91030d5656d9f4b3af8aa490d4db1eb53481e6846b8a5ee7acfcd", + "sha256:5375ff1d2159e2ef847449e3dd2329441423d0a3d895d123273a67095fe7ca0c", + "sha256:5421acb5c363a9bc959122a8645e3f1f42010c932dc53885b11a5ff5b5a6d730", + "sha256:557ebf4ce5568588368675014a2540405db687c2e4c7ad1eb83aa7e857be1864", + "sha256:57fa1a3fd1279b3ca7655b943ad61d298f2a2464a4cdca7ff298058e408322f9", + "sha256:58b2a87c65cbfb20917ec48ace47f71b1962c1f81dbf18a4052e3037abf72028", + "sha256:5df50c6133a63071fb77a0a091ceae36e78467b728d65e711ded02510edd9855", + "sha256:6058e12e9caa33468f9a36fb88c15a4bb30a479f997b37834b83abdbf062f264", + "sha256:6119e5d5bda268171af1f68ab5e7544c618f02a9bdc7c3929a458b719b88cd03", + "sha256:61253431e5a6f0eaeae71e2a101753fbaf4360b3e4dd8e118177d565ae119d40", + "sha256:6269637d9a54990430b4a769df15833935a46c4d004d9fe8a153bbadf0b9a097", + "sha256:63e58f96849f622ce769dcd705f83c7445cd9829bce1dae00e78bb031aec8096", + "sha256:65f2ee406dc592a5b22a7dc6abac13e8a3e8de4b2ecf5dc3c22937865496e4b6", + "sha256:672dd1bab4256311db1520b1b50e7a10cbaeaae2b0ac6bc5d858cc387ee605a2", + "sha256:6761765cc520ff9616fb035c02a85d1d744f7f70edd4649718fd0d09c589eacf", + "sha256:691671ea05684f921ffc2e935fd3f9311c1795a10fbbfa006b46269733668f66", + "sha256:6a31cc61ad1be4091f5b094c91d53d206609928af13b7b24573cb857a3bc07fc", + "sha256:6a9ee62a970075738909909bdbef3a7da9f7ae03dfca584db283547a29503b56", + "sha256:7138b0e7990e5555a905c519e8dad17c1da1f20e08b283e202c414229065740f", + "sha256:734ea79e4707751fb7cc4f716123b2115cd16ed0c4926e803540aece22e3ba67", + "sha256:76fb341d5a707a4f211631b8c77259b2df149147e9d9c245ae6ba3dd936bfdfb", + "sha256:77f0a74ff6f6cf89f5b673a732d5afe1911a6e6b1c017260836fdfdf85518dc1", + "sha256:78b7bdaa8b27b7f7607c66bdb6ab15c1dcbd9e9a1556a253a347dad511f615d1", + "sha256:79e68f0fd7d381b9bbd71776f602a2d5440d4d2077459128e02fd6607465422c", + "sha256:7e25e9697f60af41fb86b08697e470b1e7eb6cd6ac0eb25e4b1f519839adc271", + "sha256:7e2af7ff9553c492f684a41d903ec41e37bf6267ee3206c17518a349201cae46", + "sha256:8837fbe708cb9d8a2d32a37dee836d24a531f02560db26418e2b181986fa21cb", + "sha256:88bb24b9fdccb1d805258d5648533206eb58c58b6554985c47db53a89c11be85", + "sha256:94ebe745d1b0ebd3af91e22c38961616d32a228bdf9c326e7d4a6007a623d48e", + "sha256:99f8ea48f14a71c5e2df8763e9a490e8af63096dcd67755b7bab0a4b74fc7cd7", + "sha256:a039b009693b58f7e0cf6121851218c2227223e7601cc24ed4957ba0990fd25b", + "sha256:a10e9af5d4c5977d2d93e75d1662d076a8e8bf8c499dac7be4e78ebd8e0b59af", + "sha256:a145a7826eddea3eb5814903f98f93756042b919bb5305544cb1331daa2705b1", + "sha256:a346408f19b6d589bf029f25f65c0b4cdeed6302ef8f40da4e5d1552d22dc037", + "sha256:a45a5249a6965d91aac9f991fda7c17e6b8b41fe91592a6099f182bf53c82724", + "sha256:a5bb346a34499e091e4fa23df58251ad192173c088e5413d893ca1c730c133c7", + "sha256:aae2f5f4c77335a39ebe5a1c77d5519f6cefefc7dbff50bd551e3771d927e3fc", + "sha256:ab45839c912777e2738fed369636589c8b2a6d9c44ca56de0fd0814581d467c2", + "sha256:b312b3cc87951faaed3cfef984d768ee8bee7f935d9cc929aaa9946b0b96a98c", + "sha256:b58138d19f34e32833e62de5e910bc2a8baae43310b921d783bd39b15227c2dd", + "sha256:b620d7559b6b2197c5730332fab0867ecf1c8cb74d45533ebbcbcad1eacf4616", + "sha256:b640460f0ffb346b192686bd6fac5589e35a6c6640501c59a9fb6e82b0dd6bd8", + "sha256:b898caea081303006decc562c7fca5126f7c96507e78dd8f1ae3285dfa50ddc7", + "sha256:b95a6eca3b927853529eea958310563c83140ae8451dd5dc4399c7da385dc4f3", + "sha256:bad63bb4dea3c58e8078a3a173259ac2df5442a437e49c632b4099c0250e803b", + "sha256:bc5607c1911c92530cb402ea90d818933cffb28bd8de9b453a2542279816d8c7", + "sha256:bc6491d3008ecabf685b0746f03ad8241a0950336939b14addb03af39b51a316", + "sha256:bcd42e7b69c8c1e33a29b79b28de03bdc08876a49745830f9162a3af860e06d0", + "sha256:c3a78a3161b3a9bf07725822fd24d379c1f3f161b6db49166c4131096ea73b4c", + "sha256:c3dfb16e047c912e1a06bfbc45da752219f474897be85f55b8069f7936b08cc0", + "sha256:c48cdb6c904dca76d9915a579e4a5fab6b0c25f650c1019ce78a78effaf7a345", + "sha256:c57ddae24cf72eb6bd18112638a987cafe6109d90f2df111e6934362cc03ac1a", + "sha256:c932273bc43b068538f3874fa5e6c2a60f33fa0b11c1ebc7768652f6a0608943", + "sha256:cbd45dfba6b5c1bfbabe1feb3c0f117fbd62416e98268d9a7cd9ad8802875356", + "sha256:ce4cab32c37ef71e69cf88f909b7febd0dd79543e5ae3650e2b874e0f3d3b975", + "sha256:d75d6366203c8d025c1a74bae0b565952187ddae79bd5c7bf10687652a56f020", + "sha256:def66258d97ebf1e4e97def12c5daa542d1cc728a3da83ed3a43933f56df6dab", + "sha256:dfedf844892bf88f387cdeb9fa9bff1186904417c9f05087c99241bec24a65cc", + "sha256:e0345d4c1f7aa5a27075d28a7f0e9ed386729198045f1f08b47f8320d6bbda23", + "sha256:e3c6fb1c1a516881353186bed9cfcb8899f968c03b3509720c79db0d967acf3b", + "sha256:e5d4885c5625c9d2dcb49458700851574e9d0ea046c7a265526e990282f8ae8e", + "sha256:e716f47c7f61e11709d3c0904213c94fc22999abf0c41461276cef886c1e8b4d", + "sha256:ea4fdc79c0045d6bb1603c109127145245cafe888588888444e1e37fbeadbac3", + "sha256:f12e80c3089ebc03727d368f8205b811b5af2cd4a72b5e4cac75e901dd316e39", + "sha256:f42239c89430eee2d8a6dec39e34677abdbb67fff63caf2467dd6124ea4d4d58", + "sha256:f4ef4935962f7029b2058a99f1a47ccbffc3be919dddb3becb6c2c48eac3d9f0", + "sha256:fd91203e156d610ecb28b9ccd7b764af7a7b38662d7c163090babab0d10def0c", + "sha256:fe09aac4837ec720af606a493e814dcc3f65631984e1b7231b589efcf9917024", + "sha256:ff909b934b1958e31784d412abab5cbb0709fdbc01c86f22965e1d15331371ba" ], "markers": "python_version >= '3.9'", - "version": "==2.3.0" + "version": "==2.5.0" } } } diff --git a/setup.cfg b/setup.cfg index d91a6c786..88203ce89 100644 --- a/setup.cfg +++ b/setup.cfg @@ -44,7 +44,7 @@ packages = find: python_requires = >=3.11, <3.15 install_requires = requests>=2.34.0,<3.0 - urllib3>=2.6.3 + urllib3>=2.8.0 deprecated>=1.2.4,<2.0 opentelemetry-api>=1.21.0 opentelemetry-sdk>=1.21.0 From bf3b9a68beae498e7909f6a5823acb4f00de140b Mon Sep 17 00:00:00 2001 From: BryanFauble <17128019+BryanFauble@users.noreply.github.com> Date: Tue, 6 Oct 2026 07:01:55 -0700 Subject: [PATCH 07/15] Remove pip and unused apt packages from Docker image to clear Trivy findings (#1468) pip's vendored urllib3, msgpack, and setuptools trigger HIGH CVEs even on the latest pip release. pip is not needed at runtime, so uninstall it after installing synapseclient. Drop the Debian python3-* packages, which target the system Python rather than the image's Python, and run apt-get upgrade to pick up the patched libpcre2. --- Dockerfile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index cd27ddf0a..99b8ffdaa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,20 +2,18 @@ FROM python:3.14-slim RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections RUN apt-get update \ + && apt-get upgrade -y \ && apt-get install --no-install-recommends -y \ gcc \ procps \ - python3-dev \ - python3-setuptools \ - python3-pip \ && rm -rf /var/lib/apt/lists/* -RUN pip3 install --upgrade pip - WORKDIR /synapsePythonClient COPY . . -RUN pip install --no-cache-dir .[pandas,curator] +# pip is not needed at runtime and its vendored dependencies trigger CVE findings +RUN pip install --no-cache-dir .[pandas,curator] \ + && pip uninstall -y pip LABEL org.opencontainers.image.source='https://github.com/Sage-Bionetworks/synapsePythonClient' From b67b48a714c8a6dcf00b348b708f6eb1277b2741 Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Fri, 23 Oct 2026 07:57:56 -0700 Subject: [PATCH 08/15] deprecate schema registry functions (#1467) --- .../extensions/curator/schema_registry.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/synapseclient/extensions/curator/schema_registry.py b/synapseclient/extensions/curator/schema_registry.py index 2899163e6..d8c83a95a 100644 --- a/synapseclient/extensions/curator/schema_registry.py +++ b/synapseclient/extensions/curator/schema_registry.py @@ -70,6 +70,8 @@ from dataclasses import dataclass from typing import List, Optional, Union +from deprecated import deprecated + from synapseclient import Synapse from synapseclient.models import Table @@ -120,6 +122,11 @@ class SchemaRegistryColumnConfig: uri_column: str = "uri" +@deprecated( + version="4.15.0", + reason="To be removed in 5.0.0. Use the Organization and JSONSchema models " + "from synapseclient.models to find JSON schemas instead.", +) def query_schema_registry( synapse_client: Optional[Synapse] = None, schema_registry_table_id: Optional[str] = None, @@ -130,6 +137,29 @@ def query_schema_registry( """ Query the schema registry table to find schemas matching the provided filters. + **Deprecated:** This function will be removed in 5.0.0. Use + [Organization][synapseclient.models.Organization] and + [JSONSchema][synapseclient.models.JSONSchema] instead. + + Example: Find JSON schemas with the Organization and JSONSchema models +   + Get the JSON schemas of an organization and the versions of a schema. + ```python + from synapseclient import Synapse + from synapseclient.models import JSONSchema, Organization + + syn = Synapse() + syn.login() + + org = Organization(name="my.organization") + for schema in org.get_json_schemas(): + print(schema.uri) + + schema = JSONSchema(organization_name="my.organization", name="my.schema") + for version in schema.get_versions(): + print(version.semantic_version) + ``` + This function searches the Synapse schema registry table for schemas that match the provided filter parameters. Results are sorted by version in descending order (newest first). The function supports any number of filter parameters as long as @@ -357,6 +387,11 @@ def query_schema_registry( return uri_list +@deprecated( + version="4.15.0", + reason="To be removed in 5.0.0. Use the Organization and JSONSchema models " + "from synapseclient.models to find JSON schemas instead.", +) def get_latest_schema_uri( synapse_client: Optional[Synapse] = None, schema_registry_table_id: Optional[str] = None, @@ -366,6 +401,29 @@ def get_latest_schema_uri( """ Get the URI of the latest schema version for the given filter criteria. + **Deprecated:** This function will be removed in 5.0.0. Use + [Organization][synapseclient.models.Organization] and + [JSONSchema][synapseclient.models.JSONSchema] instead. + + Example: Find JSON schemas with the Organization and JSONSchema models +   + Get the JSON schemas of an organization and the versions of a schema. + ```python + from synapseclient import Synapse + from synapseclient.models import JSONSchema, Organization + + syn = Synapse() + syn.login() + + org = Organization(name="my.organization") + for schema in org.get_json_schemas(): + print(schema.uri) + + schema = JSONSchema(organization_name="my.organization", name="my.schema") + for version in schema.get_versions(): + print(version.semantic_version) + ``` + This function queries the schema registry and returns the URI of the most recent version of the schema that matches the provided filter parameters. This is equivalent to calling query_schema_registry with return_latest_only=True. From 4de2b9f63df1a661d1a13ea3903474af5e5e2f13 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Wed, 28 Oct 2026 11:13:03 -0700 Subject: [PATCH 09/15] [SYNPY-1941] Preserve data_file_handle_id when file handle is withheld (#1474) * [SYNPY-1941] Preserve data_file_handle_id when file handle is withheld Synapse omits the file handle from the entity bundle when the caller lacks DOWNLOAD permission (e.g. unmet access requirements). _handle_file_entity still called _fill_from_file_handle() with an empty FileHandle, which overwrote the entity's dataFileHandleId with None. This caused File.get() followed by store() (e.g. moving a file) to fail with "Cannot store file". Only copy file handle fields onto the entity when a file handle was returned. Co-Authored-By: Claude Opus 5.5 * [SYNPY-1941] Move file handle guard into _fill_from_file_handle `if self.file_handle:` is always true for a FileHandle dataclass instance, so an empty placeholder FileHandle (left when Synapse withholds the file handle due to missing DOWNLOAD permission) overwrote data_file_handle_id, content_type, content_size, and external_url with None. Guard on `file_handle.id` in File and RecordSet `_fill_from_file_handle` so every caller is protected, and revert the now-redundant guard in entity_factory._handle_file_entity. Add RecordSet regression test. Co-Authored-By: Claude Opus 5.5 * [SYNPY-1941] Revert to guarding in _handle_file_entity Restore the guard in entity_factory._handle_file_entity and revert the _fill_from_file_handle changes in File and RecordSet. _handle_file_entity is the only caller that can pass an empty placeholder FileHandle and it handles both File and RecordSet, so a single guard there is the smaller fix. Keep both File and RecordSet regression tests. Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- synapseclient/api/entity_factory.py | 7 ++++- .../models/async/unit_test_file_async.py | 26 ++++++++++++++++++ .../models/async/unit_test_recordset_async.py | 27 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/synapseclient/api/entity_factory.py b/synapseclient/api/entity_factory.py index db3472641..be9207601 100644 --- a/synapseclient/api/entity_factory.py +++ b/synapseclient/api/entity_factory.py @@ -259,7 +259,12 @@ async def _handle_file_entity( entity_instance.file_handle = FileHandle().fill_from_dict( synapse_instance=file_handle ) - entity_instance._fill_from_file_handle() + # Synapse omits the file handle from the bundle when the caller lacks DOWNLOAD + # permission (e.g. unmet access requirements). Only copy file handle fields onto + # the entity when one was returned so that `dataFileHandleId` from the entity + # is preserved. + if file_handle: + entity_instance._fill_from_file_handle() if download_file: if file_handle: diff --git a/tests/unit/synapseclient/models/async/unit_test_file_async.py b/tests/unit/synapseclient/models/async/unit_test_file_async.py index 1d7478fc3..878a7b835 100644 --- a/tests/unit/synapseclient/models/async/unit_test_file_async.py +++ b/tests/unit/synapseclient/models/async/unit_test_file_async.py @@ -797,6 +797,32 @@ async def test_get_with_id(self) -> None: assert result.file_handle.is_preview assert result.file_handle.external_url == FILE_HANDLE_EXTERNAL_URL + async def test_get_with_unmet_access_requirement(self) -> None: + # GIVEN an example file + file = File(id=SYN_123, download_file=False) + + # AND an entity bundle where Synapse withheld the file handle because the + # caller has unmet access requirements + bundle = self.get_example_rest_api_file_output() + bundle["fileHandles"] = [] + bundle["restrictionInformation"] = {"hasUnmetAccessRequirement": True} + + # WHEN I get the example file + with patch( + "synapseclient.api.entity_factory.get_entity_id_bundle2", + new_callable=AsyncMock, + return_value=bundle, + ): + result = await file.get_async(synapse_client=self.syn) + + # THEN the data_file_handle_id from the entity should be preserved + assert result.id == SYN_123 + assert result.data_file_handle_id == DATA_FILE_HANDLE_ID + + # AND the file handle should have no metadata filled in + assert result.file_handle.id is None + assert result.content_md5 is None + async def test_get_with_path(self) -> None: # GIVEN an example file file = File(path=PATH, description=MODIFIED_DESCRIPTION) diff --git a/tests/unit/synapseclient/models/async/unit_test_recordset_async.py b/tests/unit/synapseclient/models/async/unit_test_recordset_async.py index 0b9e577e7..8e4fc1d2f 100644 --- a/tests/unit/synapseclient/models/async/unit_test_recordset_async.py +++ b/tests/unit/synapseclient/models/async/unit_test_recordset_async.py @@ -571,6 +571,33 @@ async def side_effect(**kwargs): assert result.id == SYN_123 assert result.name == RECORD_SET_NAME + async def test_get_async_with_unmet_access_requirement(self) -> None: + # GIVEN a RecordSet with an id + record_set = RecordSet(id=SYN_123, download_file=False) + + # AND an entity bundle where Synapse withheld the file handle because the + # caller has unmet access requirements + bundle = { + "entity": _get_record_set_entity_response(), + "fileHandles": [], + "restrictionInformation": {"hasUnmetAccessRequirement": True}, + } + + # WHEN I call get_async + with patch( + "synapseclient.api.entity_factory.get_entity_id_bundle2", + new_callable=AsyncMock, + return_value=bundle, + ): + result = await record_set.get_async(synapse_client=self.syn) + + # THEN the data_file_handle_id from the entity should be preserved + assert result.id == SYN_123 + assert result.data_file_handle_id == DATA_FILE_HANDLE_ID + + # AND the file handle should have no metadata filled in + assert result.file_handle.id is None + async def test_get_async_with_path(self) -> None: # GIVEN a RecordSet with a path (looking up by local file) record_set = RecordSet(path=PATH) From 12ffcbe355dab9a9109726920ddc6c2e690b8f67 Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Wed, 28 Oct 2026 15:46:54 -0700 Subject: [PATCH 10/15] [SYNPY-1933] Updated pandas to use 3.x (#1471) * updated pandas to use 3.x * fix tests that do not work in pandas 3.x * fix issue with duplicated df indeces * fix nan to none helper * construct_rownames now takes a RowSet * added comments to tests * cast columns to objects * pinned numpy versiosn for specific pandas versions * added unit tests * added helper function * add type hints and unit tests --- .github/workflows/build.yml | 47 +- CLAUDE.md | 8 + Pipfile.lock | 1092 +++++++++-------- setup.cfg | 9 +- synapseclient/extensions/curator/CLAUDE.md | 4 +- .../extensions/curator/schema_generation.py | 25 +- .../models/mixins/table_components.py | 60 +- synapseclient/models/services/manifest.py | 6 + synapseclient/table.py | 50 +- synapseutils/describe_functions.py | 7 +- synapseutils/sync.py | 25 +- .../synapseclient/deprecated/test_tables.py | 10 +- .../models/async/test_entityview_async.py | 8 +- .../models/async/test_table_async.py | 15 +- .../deprecated/unit_test_tables.py | 90 ++ .../extensions/unit_test_curator.py | 212 ++++ .../mixins/unit_test_table_components.py | 195 ++- .../models/async/unit_test_manifest_async.py | 21 + .../unit_test_synapseutils_sync.py | 98 +- 19 files changed, 1370 insertions(+), 612 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 381ce013d..f134759d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -313,6 +313,51 @@ jobs: name: coverage-report path: coverage.xml + # run unit tests against older pandas versions, since the test job installs only the newest pandas in the supported range + test-pandas-versions: + needs: [pre-commit] + timeout-minutes: 60 + + strategy: + fail-fast: false + matrix: + include: + # pandas < 2.2.2 is not compatible with numpy 2, so those entries pin numpy 1.26.4 (the last 1.x release) + # pandas 1.5 is the lower bound in setup.cfg and installs only on Python 3.11 + - python: '3.11' + pandas: 'pandas==1.5.3' + numpy: 'numpy==1.26.4' + # pandas 2.1 is the first version with DataFrame.map and the first to support Python 3.12 + - python: '3.12' + pandas: 'pandas==2.1.4' + numpy: 'numpy==1.26.4' + # pandas 2.2.3 is the first version to support Python 3.13 + - python: '3.13' + pandas: 'pandas==2.2.3' + numpy: 'numpy==2.5.4' + + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + + - name: Install py-dependencies + shell: bash + run: | + python -m pip install --upgrade pip + + pip install -e ".[boto3,pandas,pysftp,tests,curator]" "${{ matrix.pandas }}" "${{ matrix.numpy }}" + + - name: run-unit-tests + shell: bash + run: | + python -c "import numpy, pandas; print(f'pandas {pandas.__version__}, numpy {numpy.__version__}')" + pytest -sv tests/unit + sonarcloud: needs: [test] if: ${{ always() && !cancelled()}} @@ -350,7 +395,7 @@ jobs: # on a GitHub release, build the pip package and upload it as a GitHub release asset package: - needs: [test, pre-commit] + needs: [test, test-pandas-versions, pre-commit] runs-on: ubuntu-22.04 diff --git a/CLAUDE.md b/CLAUDE.md index 3155b0df9..a19452b19 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,6 +9,7 @@ Synapse Python Client — official Python SDK and CLI for Synapse (synapse.org), - Python 3.11–3.14 (`setup.cfg`: `python_requires = >=3.11, <3.15`) - HTTP: httpx (async), requests (sync/legacy) - Models: stdlib dataclasses (NOT Pydantic) +- pandas (optional): `pandas>=1.5,<4.0` (`setup.cfg`, 4 places) - Tests: pytest 9.0.3, pytest-asyncio, pytest-socket, pytest-xdist - Docs: MkDocs with Material theme, mkdocstrings - Linting: ruff, black (line-length 88), isort (profile=black), bandit @@ -107,6 +108,12 @@ pandas, boto3, pysftp, and other optional extras must never be imported at the t For type annotations referencing pandas types, use `DATA_FRAME_TYPE` and `SERIES_TYPE` from `core/typing_utils.py` rather than `pd.DataFrame` or `pd.Series`. These aliases resolve correctly at type-check time without requiring pandas at runtime. +### pandas version compatibility +Code must work on every pandas version from 1.5 to 3.x. Use one code path that works on all supported versions. Use a feature check only when no such code path exists. Known pandas 3 traps: +- Text columns have the `str` dtype, not `object`. Use `pd.api.types.is_string_dtype()` instead of comparing to `object`. +- `DataFrame.applymap` is replaced by `DataFrame.map`, but `DataFrame.map` is not in pandas < 2.1. Use `df.apply(lambda col: col.map(func))` instead. +- `iterrows()` gives a `str`-dtype row when all values in the row are strings or missing, and `None` becomes `NaN`. Check each value, not only the column dtype. + ## Constraints - Do not use Pydantic for models — the codebase uses stdlib dataclasses with custom serialization. Mixing would break the `@async_to_sync` decorator and `fill_from_dict()` pattern. @@ -126,6 +133,7 @@ For type annotations referencing pandas types, use `DATA_FRAME_TYPE` and `SERIES - Integration fixtures create per-worker Synapse projects; use `schedule_for_cleanup()` for teardown - Auth env vars: `SYNAPSE_AUTH_TOKEN` (bearer token), `SYNAPSE_PROFILE` (config file profile, default: `"default"`), `SYNAPSE_TOKEN_AWS_SSM_PARAMETER_NAME` (AWS SSM path) - CI runs integration tests only on Python 3.11 and 3.14 (oldest + newest) to limit Synapse server load +- CI job `test-pandas-versions` (`.github/workflows/build.yml`) runs the unit tests on older pandas versions: 1.5.3 on Python 3.11, 2.1.4 on Python 3.12, 2.2.3 on Python 3.13 (ubuntu only). The `package` job needs it. pandas < 2.2.2 requires `numpy<2`, so each matrix entry pins its own numpy version (1.26.4, 1.26.4, 2.5.4). ## Maintenance diff --git a/Pipfile.lock b/Pipfile.lock index b38f178bc..5164fb2fb 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -455,118 +455,120 @@ }, "opentelemetry-api": { "hashes": [ - "sha256:711ede81773c8025c2c03dac0450bc89f3d30aea6eabcc815c570d4e35a963f7", - "sha256:80e068aba7cd56c8b58512d6a36f8d25cb1dfaa0c0a4cc1c938ccf9f362d9cb3" + "sha256:aa38ed19bcc084ba42782a73255b3582283eced7ad6dddbd6695189e69adfb75", + "sha256:b31553efa588ae44bc306f863c785c5333a9ecc091248c6ee68b4b6c87fdedfb" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-exporter-http-transport": { "extras": [ + "requests", + "requests", "urllib3" ], "hashes": [ - "sha256:2c229b6593eaa22c86d9b8a15843dc23b406dbda00fb138339189aab07923b4e", - "sha256:c82689928a11505a2a0a26a04afe0ce06d270d3db984bc16c1a80ffa902db00e" + "sha256:2f95404bdee7f9d2d529c7de56c7bd86d014d774d8fbf137810e0167f8a492bf", + "sha256:443080203bf52586ce0b2ad901e8951c61833eab1aa539ae6f1f16fe9e8e7952" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-exporter-otlp-common": { "hashes": [ - "sha256:35d24c867310f4713a9738b0202b6bade77955418fccb9e2f7eea01b76263916", - "sha256:362268ec6aa705e183776ff938539df1e8ce45bc5509d242538b1d40c26fe6a6" + "sha256:00ff8592c3a7cb729ff3fdc7ffa12372c243bdf2163e80c180994d0c7bd83ee9", + "sha256:6b1403487a2185ac1feb45fd5546fdf8630ce71c36bcefaadf51e2130e9e23f9" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-exporter-otlp-proto-common": { "hashes": [ - "sha256:36495115a0c6a7aa946cfda9d59b6ed4e917b6ab0f75cdaf66bc1b176ec1be1f", - "sha256:7e1410ae6d3ed301f7a74bec96467d519d3f37e52f9d95b309ae125e5a1af863" + "sha256:2e4adcc3a67bcf57804fc49514f0ef64974ca7590aa3491da389852b4a0628f6", + "sha256:2f446183ae7047b036226f1d846c41a834b0e8755ad13b51a51dd38952eb466c" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-exporter-otlp-proto-http": { "hashes": [ - "sha256:2f35496d96809f946f41b8805e6b93aec6c9b71b5fd759b75b6af4c084d992ae", - "sha256:74385f99266dafdefff41f3da4b76f6dba79d237a9d4487e6ff1ee653c74a0a3" + "sha256:24a97cf3753c7fb52fad44a696e452ff371686339e2acf3309e2eda3d0230700", + "sha256:45c218405ce3fd879596924b1874bf9a8f6880206d61065c5a912c8e5c297fb7" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-instrumentation": { "hashes": [ - "sha256:0b32e2fcfec1e4bd48511a3b77ce32bfb1c16dcd5479396b21f9086a4b06c0c9", - "sha256:316715ed7b33a12530c0ae3e8d4cdf26d70e1aad358d7ba256e5dea2d4ceed71" + "sha256:4c4aa14dc9a24a02325a9d4c42c4d0208dbb1374c2b1b8fe6c9392d59f3e1008", + "sha256:e79a510f7d87c72d95e964ddb42193a0d9a75668c027d980eab032ea1322a5ce" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-instrumentation-httpx": { "hashes": [ - "sha256:2735d1868749ca04ce47a3802b0b809e3a00c05a65140e05bac5700e74410539", - "sha256:c89297975f54d67692d3c29e9e33a1bdac47710031cc3ed0d83a0c9765336981" + "sha256:0342a4002c6dbc6c4bf22cc7e698f50f5c8b77f63325c6f40c94ab87e016bf4d", + "sha256:5865a72c68098c85955a271ab8744b480a36e3ee492d35b8cadb93c7c4dbb618" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-instrumentation-requests": { "hashes": [ - "sha256:053dde08fbc1d223058e33d477cf81e2bdcbe7af3893787283339b2b557d4b7a", - "sha256:2f9df08bf99f5da4bcfda70735492b4364bfcc5bd3f48232658e936f97ee1a22" + "sha256:28578f72e68e3a5be3226c618ac9570ed360ef1dd22d5d6e0721c6905a4ccc67", + "sha256:7ba17d984a2bd876b88bf0aafcca27b5e3ff4c1821e0fe07641e380a3cf3a3a2" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-instrumentation-threading": { "hashes": [ - "sha256:4aaf38b96b47a04319b8d96bee4f1daa04e0d6c697525595746aeb61618c002d", - "sha256:4c1c9adf42b83b6f44ca4bb99799e066ccfb1869c2029bc73d862c40a8ef932e" + "sha256:2c217359439d09ca4a4be524db368c05a3cc7f218b85e8086f22664db0a03538", + "sha256:94039c60603060d26524e31aed1181a5d153e43f58462d110dbeb4830687d7d7" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-instrumentation-urllib": { "hashes": [ - "sha256:3eb6d2b9b28bb51188d77092a58eac2ab04852d244acb51333bdf42b0e933c68", - "sha256:a919d8014dcf0065ad42ce5c78dd158c76c7342929f451d726462f7ffa68e367" + "sha256:6f679d785ebcb04b791a889d8a9c0e8edf897a85ab80a7a12b0139c461b14627", + "sha256:f00daa25375fbdf88b7e1a425ef54c704674d8bef639c834de93df9b3f88d7f4" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-proto": { "hashes": [ - "sha256:96ee414f24bc3f61ea8e17dc56b4348d4049d73db3eb17c6b3edf75b5b403300", - "sha256:9731566359d7b8e1ee1e149d8e4ad6865bab965e657ad3387ec2784d16927666" + "sha256:79e0fb95e4616691a469439238aa9224d75779b3e108e895d1aa125ab29ca77c", + "sha256:f38e2a8413053c180cd3d2637fbb279673ec2f6a6e09c995aafa2f452c52b46e" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-sdk": { "hashes": [ - "sha256:20caa5130505e386c67c3da1c76e446c842698ced54c76c6148679539aa97972", - "sha256:5dc634c946546f61b757c5b1781f9fd1a10e96ffaf7357c797e508fe9c57e75e" + "sha256:63d24a6ca645019a631e6a51999c73e93adcac1196ca640b8ae78a7cc4762bf3", + "sha256:c604c11dc429810812348989115fa44bd558772a3d7442afc43d024f2c250ca4" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-semantic-conventions": { "hashes": [ - "sha256:175b19dd98c4473f4f43a2b1df59186fd7b4a48cd3f77cbe03438b6d6fda230a", - "sha256:97a77dce484c54861e7eeff7651fd8a806dd3c30e501dc316730215ec36890e6" + "sha256:497ca63bf383723411e8eaf60c8779e9877633c936bb641080adab59d0eb6ec8", + "sha256:d4cddeb4315490b35213f55e2bdc9ac54bb1e4d318927475bed62b35545e581b" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-util-http": { "hashes": [ - "sha256:7f5e581e94f023b30995f700e41ce319cec82bd542ff1c1c7c9b56d6b10bb687", - "sha256:a2d53859630abe8e5abcc4f867c5a809bb95873033573b1a67f6ef43b57a8627" + "sha256:047dea1a628031f857a5a32261dc0e955bc162d39993ed1cffb8f2cff5ba8a62", + "sha256:8f443d7abcaf29c4a07b373bbd31b5b39132c0ed3c27d015a59dc0323d5b1c58" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "packaging": { "hashes": [ @@ -619,11 +621,11 @@ }, "pycparser": { "hashes": [ - "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", - "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992" + "sha256:51d5a8ba2be0bbe440b99d2112604c95bbbc3c2748a64260186c541e1729cd80", + "sha256:d875f09c3507d00e1aba0eecc6dcadc1352f30fff09dc6bff2f1c2935e97c2bc" ], "markers": "implementation_name != 'PyPy'", - "version": "==3.0" + "version": "==3.11" }, "requests": { "hashes": [ @@ -820,15 +822,16 @@ }, "backrefs": { "hashes": [ - "sha256:4a627b817fd2dce43b79ab48da63613340509381cd8ce0897078a0bce79a2ab8", - "sha256:601ce68ca12385dbda06ce264406b4c4210cf5b79fd0fd627592365c92f29a88", - "sha256:87f0fae8c5f207fe9f4b2887efc71d42f4900ac78faa1af08d675ef303692dc5", - "sha256:9ec96efa080938be92323e8e730e57718c9c88eb15ad70bbef4e1766df591408", - "sha256:b556cd7d36c3a3a2f256b89590b176b8eddfb73bcfaee3a3ddd84ea66d21ce50", - "sha256:f0c35cf0102ba6b6070c12a492be3c1c1d3f5839529784b9a9565d6d04569a01" + "sha256:11f61846e446fa8637af2f5c073f1083aa58dbb7460b019fd51689f564e44f7e", + "sha256:1e857c32e91b8fe46ddb359ac21021a37b090fa4239566a61e9856123e334041", + "sha256:438bd38dc7fa0cded52786a1351a2dad9efc2cda95d047284c41d916a22312a8", + "sha256:9c8fe3e2eaae4301a9ce787341d986e5ba25a887d89da6de0de5d58eca26a949", + "sha256:b472c76082769f86a97ffccfd1f2599b2b706610c6154955664fffe67e909035", + "sha256:db577dbae1c61187534d35fc9bfbd0c01158fff6239a66fecf7590e5b17879a9", + "sha256:f86d9312df3ebae1241758af80809a319cafa1d8f32189edfb242c9aa55573b6" ], "markers": "python_version >= '3.10'", - "version": "==8.0" + "version": "==8.1" }, "bcrypt": { "hashes": [ @@ -901,52 +904,52 @@ }, "black": { "hashes": [ - "sha256:0e48b87e03bf109288e55cfceadcfa15ff5470aca2851a851950ed2926f450d7", - "sha256:1037d5ac7b7b310b2632ad867ec8d0e4c4819dcdb0b820f63135da746a24e418", - "sha256:1ef92b76f7733f282fd096ea406200b5a286c42947412b0eaff3a74e3616cefe", - "sha256:1f7ea64ebfa01b50f693508fc39f875e264446d3b097088f84f203b9d09618a0", - "sha256:22f2cd76d069cc54c71f10360744ba8983fbb616903b4304a85b734915c8e1b4", - "sha256:2b36cf2ddf5566e205f6535f782a62194a184d33e175b64ae8c40b1737522be3", - "sha256:30d3c14661f2792e9142cce3eeeb1cbc175b3eb5f733be0c8eeb99651e52b0c3", - "sha256:32d5ea7f6c8bdfa6e648326ebca1f02b0764e2a029edc6f8dce2627e19d468c3", - "sha256:3915f256e75a2d7cf88d8953d37f780455dc586cc72dee059c528fe77f581217", - "sha256:4ad6fa01f941920f54f2bbb35f3df7673428a0ef98a0b0840c2eaef3b110efa8", - "sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2", - "sha256:5119fa92ae61f786e8c3662fd60aece1d0a2dd5cca5d0c79417a95e7a4272a59", - "sha256:577f21094ea469ef92ec1adaf2c9441a226d2144d01a5be2fa823cecf6543e50", - "sha256:58b4bd92cf88aacf83d88479c8f9caee044b1ec55f2451a337354a7ea2590a22", - "sha256:5c34b25da232ead53a6f335b76dbea124f4d152ad568b9080d6f944bc2b34b52", - "sha256:87ed5c6f450580a2f6790bc7cbfb016dfc73bc750249762268a3695361315eef", - "sha256:89c93167a74d3a75dfaa38a5c7cca015537d5820dd7f17d63267d674a61cae90", - "sha256:96ae2c733b2aabdd9986e2c5df628ff3473676cd1c5faded1ff496cf6d74083c", - "sha256:9942db8888e06943c5dde66ca0037dcff82a2a4ec1ad0ada9e0d2ee9d9823893", - "sha256:9d98d4137277c75dfb898ec8d846c4fd68ba1e9cf77f95e2865c203dc18f4c3d", - "sha256:a1dca32d9f1784af512a13410ec204c6f7f0aa9797a111c42e1c03449821c264", - "sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73", - "sha256:e1a26503279b6b310669fb0b219c39e4820b77e8189fe80f522bb511f247db0a", - "sha256:e88976690a64b0af98312ca958415849cb42423423c5f2ee74af4b49a97a2168", - "sha256:ea8d16dc41655aa113cd64665e7219446cd7e4ff2248d7178eaa905190c86b18", - "sha256:ecb3e624844c798144e9bd986954e0adc81d8911a1f30f375e1252fe26e8c294", - "sha256:ed1a20af114c301a0269bf01163d51dbef72737fd65f850001e7cbe7f3c7abae" + "sha256:03c0ddd93bb392e71209903a691767eb366fe1a76deb9509ccbaae9e1f14bb52", + "sha256:0ce08b367307b0fd91c9dd1d4084e62b05b3055475f951f0f34a46b6e2393b64", + "sha256:182f6c32be38074b16d378498c498b32cb51928178ee611485344972c35ec9c6", + "sha256:1935b32f5326028019856e18cb42b4da63db23765dc84464cec723e0de478a9b", + "sha256:19fa8f5beb5e77c54c9c7e21d00cc93ed6c8b6228ee385616906d6befe081143", + "sha256:2520037aa62f8a1454d0811b8f5c88b444445b03a4bfba480d8d220893b64c34", + "sha256:28842f9a8207cc1df6eb983a35a14c5a0dfcd603d214fe82d84bef552afd2e3a", + "sha256:289282aa2e09d3162312a3be1788ff21b08e9ea9cc4a81e656024728b32428fb", + "sha256:2ffbc023a12d0c729408823b8f10514490bd0baa301d0d4e21a7240249f9507f", + "sha256:3414a0c52901964dceabd98c7c56beac0f964115a116ecedcce7247359b14017", + "sha256:4d9a90516db1d99c25dbb20cc0998e0e01531dd903466c7744e56d66f864220a", + "sha256:51d5e417e700fe6ec0b0ecdc408c6f6cb5def80328f31f724993d82c6486b746", + "sha256:5cd88fd7b444ca51f3fc883b6f6657ea53a258b0b2eef6d9f2dfcfa17ce0e27b", + "sha256:5f9f83beae62437e060dafd53d7f1fc327e3d3494f74d72ee5c2b73eb90fc4e7", + "sha256:70ccbd175b7f6be29d2b727ee7ca6b4c54053df59da653a6df80b175d20a94fa", + "sha256:7bdade400bfe24d78a7762896acc2f9a8e1a17fb0fd0536bf6b7c7097cf3eec7", + "sha256:8375962579d537364cc0efa19b1474481915d3a793f9fc0774901814c5e5b5f4", + "sha256:978113a40223a6aaefc17364176a809a320e6b288683841427fff04c6d7b4130", + "sha256:9a0219b29cd70e49f920acb7081e6ce5025c719008447c521d0200dcad93206a", + "sha256:b5347d760f0c02bb00dd249384cab71c3bf828b4f68d5b401eb116e0390f147d", + "sha256:b6272cfd7e1e8e271f5b0e0207259fe2834687e5cb9b5f620b34a44db9754993", + "sha256:d42dd2fac7c342ae67e64ee99c9532e20b2a84e92c79ed3317fa2ef54c801d93", + "sha256:d5bd3518d8e97138fef295230b1e9804076d69fa4e3594071494a8c68abe6266", + "sha256:d8b3a9074a680b3c5749633714e9ae3992a1e5a23343a97ad61cd9b119b444d2", + "sha256:f6dba8138cdc99061ef07b958ac082d2aa057b6961d1936f9717c350f02bab5f", + "sha256:fe85fc4019bee59bc495c0f2a8ee76c5cd02c7015508d94a967ba2376f39a52c", + "sha256:ff57f63029aa1353fa8b1b0c8971fd88a6c92dc766608d2eee33ad2deb23270e" ], "markers": "python_version >= '3.10'", - "version": "==26.5.1" + "version": "==26.10.1" }, "boto3": { "hashes": [ - "sha256:632a4f8298725b94144c8cd383cbdacb34624daa73221e954c3d33ac6e2528d6", - "sha256:c4e0f1a0295cbb7103f2950128cf88463c076d220080a7d0f127cf834969fc3a" + "sha256:5ae342a16c848909cd42d4be404f69d9082e5705460198d4d3327eca5f6cddcb", + "sha256:c79994619c8d89e45f6fd0edc5c5b5a70c9358f00423f4c99cb64931f89ecf37" ], "markers": "python_version >= '3.10'", - "version": "==1.43.107" + "version": "==1.43.111" }, "botocore": { "hashes": [ - "sha256:23cbe854e815dbaccf097f7fd32b461c9e1d2ed7e0c7dcc5658218704509d840", - "sha256:4a37fa072a00280c746313532d19b00e2dc53f1993222601df104d71d548d5b6" + "sha256:44d5e80962ac6cb9e85af72667b77c9586451e3328ab0ce33195380767e213d8", + "sha256:f1f4c28cb2a096bf246d0bb24cbb1a01c5cb696ef499fa71b155adda7b94c90b" ], "markers": "python_version >= '3.10'", - "version": "==1.43.107" + "version": "==1.43.111" }, "certifi": { "hashes": [ @@ -1475,14 +1478,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.3.1" }, - "dill": { - "hashes": [ - "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", - "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa" - ], - "markers": "python_version >= '3.9'", - "version": "==0.4.1" - }, "distlib": { "hashes": [ "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b", @@ -1500,11 +1495,11 @@ }, "filelock": { "hashes": [ - "sha256:635e7d67fa92654eed444e75e9ca18426d34e77ad9c469bf4373f75a932f7b22", - "sha256:9287fd61b99a806e5202be29a83034c0808a1b9830e820537c2f5773981f7eeb" + "sha256:3f4a557945a7b0f95efeb1f432267affe5d45ac8ddde2aed1b97ebb62382c089", + "sha256:7ba0927482c5a814b0a7f391d029ccdb8010f576f0a74c0dcde1811e8bc4c1b6" ], "markers": "python_version >= '3.10'", - "version": "==4.0.9" + "version": "==4.1.1" }, "flake8": { "hashes": [ @@ -1537,11 +1532,11 @@ }, "griffelib": { "hashes": [ - "sha256:1b8f9cd525681c26b1d6d574faa1371651e8459ca51d209684f50b8096ae06e0", - "sha256:7b0952caf5bca6afa4bb5ee8c6a2d183fe3f21b62efc5f6c7243cb2b26d2d115" + "sha256:8e710afededd5607f95bf3c8ccc175ee306e7084459faf27b9f9f44ef2a7a274", + "sha256:df00c7a0dee3d86268d76788997a1859272cb1fb7b865658e043d2c0c3d52e60" ], - "markers": "python_version >= '3.10'", - "version": "==2.3.0" + "markers": "python_version >= '3.11'", + "version": "==2.3.2" }, "h11": { "hashes": [ @@ -1593,11 +1588,11 @@ }, "iniconfig": { "hashes": [ - "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", - "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" + "sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960", + "sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7" ], "markers": "python_version >= '3.10'", - "version": "==2.3.0" + "version": "==2.3.1" }, "jinja2": { "hashes": [ @@ -1649,98 +1644,160 @@ }, "markupsafe": { "hashes": [ - "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", - "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", - "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", - "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", - "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", - "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c", - "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", - "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", - "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", - "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", - "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", - "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26", - "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", - "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", - "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", - "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", - "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", - "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", - "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", - "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", - "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", - "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", - "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", - "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", - "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", - "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758", - "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", - "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8", - "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", - "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", - "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", - "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", - "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", - "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", - "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", - "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", - "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2", - "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", - "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", - "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", - "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", - "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", - "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", - "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", - "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", - "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e", - "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", - "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", - "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", - "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", - "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", - "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", - "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b", - "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", - "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", - "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", - "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d", - "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", - "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", - "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", - "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", - "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", - "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", - "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", - "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", - "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", - "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", - "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", - "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", - "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", - "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", - "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", - "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", - "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7", - "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", - "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", - "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", - "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", - "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", - "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42", - "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", - "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", - "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", - "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", - "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", - "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", - "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc", - "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", - "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50" + "sha256:007e1ffd9bf65bb6ee96df7b258fc632a4868dd5566037986c64781f35a36e98", + "sha256:02fa4acbc6a3fc5c693c34d4dd8c1130b7fe99cc915181b0ddd6f72aeb296002", + "sha256:03470d1a8268e692ecf79ecd565593e59d44219377a7ead61f1f1b94c1f7ff6b", + "sha256:04e7902ba80ee4bac1d50a549606527a1dcf0476cd81403db41099d3b60ec653", + "sha256:051417f74bcaaefa316276e0ff723f541616ca51043d070da00249d9bddd3e3c", + "sha256:05295589e619b9bed252a86b532b8e27350abc372d18ba89b59375325e91ec1e", + "sha256:06de8ef6331f6e822c28d577dc8bf43fe398800477c49498f38fc38b67ff33fc", + "sha256:0764a13d34cae40db7bbf3a09b7e9b491bf4603e20b263a7a9d6b8e324975d0a", + "sha256:077293e425f28ec737dbcad442a71752e28f8ae27cde3d68acd1fb212091cd92", + "sha256:0930db9bdc62d22944e10b066448bb65dc9abe9112880c7cab8da54db4284d5f", + "sha256:0cee7cb0f9a1b6892ea482237d9403b3d1b4603aee057d0ff01f0fac2d019a97", + "sha256:0d9c47709875fdb321452056622e930c52afbc07a7d780762fbb8b4d91ce6fa4", + "sha256:11935df9bf455ed0c04eb87bcd720f02b1fe5e02128a9430f23aed6f93336fc7", + "sha256:12a606a492de952afcb43b59a14aaaaad120e708d3663dd0fdf2d738d427a691", + "sha256:14bd2d845d62ab678eaf81da89d7b621b51756c72346745c1a594c09d49207a2", + "sha256:15ba9e28640feef770374b116a6f019c21f52404aeabe516aa7f800587b98cfc", + "sha256:18a801868a884f216e784d7d14db2a4077143ce7610440aee2ce8f734e7cfcde", + "sha256:1c0df495a977d10460a94941799c72d5b5ab03d3858d949b55b5a66c8f371c99", + "sha256:1caa2fa5a6184fb233153b35f654e6687bd555476f6170f29d8ee9be1a8b0af9", + "sha256:1e1451fab512d1bcc3dc26988ec1edb0b82c2db909132872cd9356070a6b63df", + "sha256:1f1f9477e174582b0a1b583d60b66e1f2cf5d3fe12cee985e4aedf44766600e5", + "sha256:2628d3a8cb648ecebb3c5d6b0a1052d400e4d8b7ac0fb786be8d285b50040d17", + "sha256:26e9867520db70d37f7fb421a7f0d8adb40171011fb84ce869afa1a83370dfa8", + "sha256:2a6ef68ae94aed8721934072b27a3b654ea2100b97e4ab864cf1489c90926fbc", + "sha256:2b2b1e18af909b448bb3cf9e3433366f7a8726271fc214e8b10e0f62a78c724b", + "sha256:2cb3dd71fc6be918ad4264346a8ed69485f9b7ed7bf35495d8e22807cd6b8bea", + "sha256:2d1b7d9308288661f56672b1b157d75fc536714d3638487bbea17b6318a78248", + "sha256:2dad610540cb2e6272855c178f08ae9a1c7ac258a7fb71660553a5f104b42741", + "sha256:2e5a7cd7fdd14fcb1ae5d7d8bf23d24fbd1daefd1fbca2580132e1ea75f098b5", + "sha256:2e9ad7dd851bf45fab9f75cbff4cb493fee9979e8d8c7c9c3ee119022518edd6", + "sha256:340cbb1957ba99929cbf19a75626d36ba1ae21d1730b287d1cf7f824a20c4fc7", + "sha256:34bdde374c5932765d7dc685c4a1d191a3207852d67e8e0a9eb6ea85156181f1", + "sha256:353bd63081912ab8cfa6a0c7d185934cdf8426f04c618bba6bc4b394f2069b67", + "sha256:387d8cd30e69b3f0a72877b9ae717033396404e19095b17fe89753a981fda44f", + "sha256:3882fb412298575bae3b9c46868251f15cc69307359f87bb1b382e53d6e5a2c9", + "sha256:38fc55594dab834470b6733dead2ee9e3f657fb0608c769dcafa0ba5ab52f45c", + "sha256:396ec4e65cc889f69786b3b89478b471cee5a3bcf468b9d9bb03e1a30fb291fc", + "sha256:39dbacefc411633db5b4378b066a9aca70a3d7e2922c9e578d825f844026eeba", + "sha256:3a93d9616ddecfb393727a0041a562cf0b15a244e20f2bd25efc7949be4c4f17", + "sha256:3d23795802fc8bd72534836d64489bbf0f67c088959091bdb22e10735a5107bf", + "sha256:434139499bb20b502ed3baa1f169e618f924a97e7a777fea1a49446d80106cf6", + "sha256:436e3ffc6310d3c41878c601db29098102fe5d8a467c49da4a4125254e0980f2", + "sha256:489505b03f692c3f376394e49194fa7a7f9e8558d6e293a7056a0032b0c38163", + "sha256:4a540e2d3192792fc84eced57bef37851ccb2b41f73291bb17408eea77bcd278", + "sha256:4a7cdc2a420ca01058182da4253329764d4bfa055564d1eced90e6ba1e8b1d3d", + "sha256:4bced6e2a6dba6a28f7dd3c6ce14df1b2dd495923f16ea484cad03decd463b2b", + "sha256:4cf3468d5ec187ffffcaca8e61929a37448f215dafc1386a12c750a72fe53634", + "sha256:4e2c4809c14559aa7ef426f27fb35afbb38104c349a903bf8f3600456764bb38", + "sha256:4ed644d75aa94a2baf7ec3a96eaa160ea58c742eb9d27c6506053c5c40fc84ed", + "sha256:4f6e0852a0283b1b1fd776eeb7b766a5f440b3e2bd31ab51af3b400585f3965c", + "sha256:5066b244f576f91afc8ee3ba029a89f99d39c79b1853fe9d39bea9f0afbec148", + "sha256:5086f9975abb1ab531ee6afca1761e4b59a19b446f3f6522ed776963228cfe5a", + "sha256:50b5bedc9ed8a94fc8857a42ef4f84a81ea88f8d4f05dc8705fb23ee6d8dcca7", + "sha256:52704c5d36eb6dda8866493decd61111fff86244c9b1ad225ca01b9e91e5970f", + "sha256:55ffd6ce583d97dc71dc92e930324c8c0d25aea7e3ade6ae54ef77cedb096811", + "sha256:569d65055d367e3dcdf30c3f41119467b73d9ee9faf332bdf40402644f5ac08e", + "sha256:57f9947a7e57a081c1e3e0a2dd0d2dcf290a4531450e6f611e30084c222a7295", + "sha256:5989cb26b2e1efc6a42216a9f6b5ee495ce5ace2e5b352a9af489976b32d1ee2", + "sha256:5c22873ad1f0532ba40fa1727f3c0fc1bbbaab6d373d4cbe3f0dc74b2e2521c7", + "sha256:5e8b3d0b18fd623afa12ecb2ce8d8becef69f9b5440c6330c7972200e0bb84b0", + "sha256:61631e08084be9e21a8967ec3139c7616ed7c5e9368e05c86d1b39562c8a57b6", + "sha256:64511c54db4e4987aef4c41923235927428729e8174c5dba488429be70a998ed", + "sha256:6669c1bf34080161ce49c589cc512ef24d4c704ac9d2b2d3667f519c60418378", + "sha256:672d207103e6b16ca098611b0f9efad6bc00afd47c03d6ef62186495ca677dc0", + "sha256:6768d67d1bce64270e0fdc2e69309d68b9b18ae56ddf6c711d168e9d051c2cac", + "sha256:6a45c3d514f2436064db00d7fc8778d888f0236ebfed649b53d13a59e69ad51b", + "sha256:6bd9e1788e15bfcf6a9082de42e30387e7b85d211ab21e57a939bb8cfaaf8d96", + "sha256:6d2a9efe686f9de00d0d1ea32a4a5a86d558a2277501bd78d964214eab625e59", + "sha256:6da83a088f8ef93b2d483a8232a4dbf4d69d3d8496b568a03c56becac43e1808", + "sha256:7018d4af1cd272e847aa5917983ab5e83e4f6579f9dbfecd4a79c0ca80b144c2", + "sha256:71f88e749ea29f67f21f3b36433c1dc54c7729ed2a6d9e2da2e0d9e0d7b224eb", + "sha256:737c9c3981998eba27f11786f84fddcbabc74068b72a4a1f454ea02094b57b65", + "sha256:73e77980c7207854f00fc4e71fb1626868d5740ab4012623d55c7a99ad122a72", + "sha256:799c39bdf5e2f1292fedd3009f7b3c9e760f10b2420cb9638d56920840ff6db8", + "sha256:7a83aa6e4805df46fed18e989d3d16f86ef60cb50bbc8d9ce3a6be89165fbf6e", + "sha256:7d3391b2188d18737cb2fa147028b1096236eaa7e156446c650a489fa2cadc91", + "sha256:7e1636da3d8dfc220b6dd10264db5f2b165e4888c4518594898fbe381049af8a", + "sha256:805c8b84534fa10891890f0e4be39f3a99e94615d93e8836bf9fa1fdca2feeb2", + "sha256:811d02d5122171c1941357efd8f9bf4ffe907b7f0a1a4e729a880e4be3f46e3e", + "sha256:8138eb83940ec7299024d92d4dee45f601b9e6c5ffde9d25f4e35e326203c707", + "sha256:83b3944fea42a8400edf92fd1770fb8d0d4f7de651353bd2d8525a92dba69a21", + "sha256:849dd2bb0e5e4ab2b71c7191726a4a8d5aa8a610daa584728cbee0b710ddc4ef", + "sha256:8698d70a8081ee8c090dbb394768b5789a1da8b131b5499f89d071dd3cfaf6be", + "sha256:8781a792a070cf2bd1b86d3aa943894115faaba6e88122a7bf32d62072742453", + "sha256:88d59b473bfb03259722600839af9bbd7fa13a2eb514beefeedb95997882f69a", + "sha256:8909c2f1c6dd65e054ac4b573a91c8384d1492281e55d82d159d653f7a13adf6", + "sha256:8965520ac587c94a4ac48b729be3d8b8de00af39699b17585dfb599babe77977", + "sha256:8b5d563170ff8ba3181caa967c99a3c804d1dedb702c7cb93a6a7c32247da978", + "sha256:8e124f974786f831d6043728e38296969d3579db8896fe004682f5758e613581", + "sha256:8f0fac8b13d14bb06c68195f849371924ae53dd7b1c00fed24650f704383b692", + "sha256:9240187afb63d2f9ddc3e032c670356fe941f6e20662ea168a5dc3f1f317e1b3", + "sha256:925f929d6b59a8b3f8b8c6ac363cd0af7eecc81efb3071770b3c6717c450a369", + "sha256:9348cbb300d224fe3b89793262cb093504d4ae927004468463f745188a193e4a", + "sha256:9388003072b95f2f1e3fd908604194d653ba21330d811961a78b7da1a77e9e36", + "sha256:9438a2648b2195980cb2dd8e53ed7b8df91319e2d0b70ae61a9e1d1bc8d3bec9", + "sha256:94e4c421742086aeee4c32a506eec8859d7634aad943f7e6aacf70f813478768", + "sha256:94f5407f7bc64fa6463906b896f9904beeeb7dd8dc116ee8e9056c8714ff9916", + "sha256:971a3bbb75d97ae4e2e8f7d4834236f86f85f0c85e04ab2e191db1123b04f80b", + "sha256:9e227f3dbe6bde7491cf0a9965d00b88c6b1a4a95d11480ddf88bb96d397c19f", + "sha256:9e25feb9e330b63edb0278a0acdf85e50d0cb0fbf49c3084abbe4e24ae195346", + "sha256:9f098115c247e11d138ab83a28fa0323c77015007ea2df73ba5fd714dfefd67c", + "sha256:a18f38cafc329bac5e3c2b96c765b4c96d3d103421ed22ab7988c1e3fce27464", + "sha256:a4bbd2d87dd233b9fc5812160c3d0ffbe42edc22a26ce0469f58479ede633fe9", + "sha256:a5fcffb37e602b0b3c1638a97746b9b96125caa9bcf6fa41d337a9261de231ee", + "sha256:a8e9f292fcda89b324f2f5c91d13f1424a153e40fc2756f38ee23b15835ff300", + "sha256:a9f54054101545a9a9cccefddf54316aa6e4491611fcbef9e91b3b6bebec04f6", + "sha256:aa2c838cc024642cc04c6854232f32b43e5e22833dd11119c1766c7873b8370d", + "sha256:ac0c7c9f1609b0c4c114feb1d7a3409564c7fb77e360bed9e97e5d25dfeaf868", + "sha256:add96447a86d205ab616665d53b2950ee81083757f56e6ea833c8b2917646b46", + "sha256:ae9dcb8fbe244cb82f8a6458b455b927a03685e383d9bacf1ea5ce180b96dc97", + "sha256:b4a635a0487774f841cb1fb62e907e7195cc95bc761e053184b8acc3ceb20733", + "sha256:b4d12837e0203bbace818ff4a7461afdcd78bcd782351cea148139180d7bcffe", + "sha256:b61687d0828e72bf5cda24a2690188f37170bd31c9359ac97e4e66569f120a16", + "sha256:b807e598953730f82e4eae3bd30f6a122cf6b31c398c6b504c0e04c13c170429", + "sha256:b8cd1f918b26fd7b1832ece557cc18f2d8747309ff8b3f0ef9d4250c5ad67a39", + "sha256:b91cc9d336957239ff200f30097e6fea2dc6d6fb3c81e853eaa09eac904fd894", + "sha256:bd3ce56ae2cbae3ba82b683bc425cd7e48d2ed8b10f3e818186b6f5646d9271c", + "sha256:be6cb0c799abb0e2ba3e618e6d28ddddf7e485f6c2ce938dfa237daf3905072c", + "sha256:befb4158af32106b9a93db8d6d1d1cbbd418c0d5aca0cabb7b1780abf0c89169", + "sha256:bf053da3c97a4bc5ecfbb218cdd2983febd91c617be8367d139882aa11e490aa", + "sha256:c02e8f18bdedba082cef725942ac823b9b60656db07f7e265cb31618dfd00d77", + "sha256:c1bc67752d5f21013cfe430df4062441714eab79f65a6a05e01505957e9c35fe", + "sha256:c61750fadcd119d0825bcb7d7d675dd264dcc89cc05292aab5be68ebdbb374ad", + "sha256:c90d5b3d4e944e065a301d741b3c1d784f6bd1f503aa68b4967e32b2ba313d85", + "sha256:c9a7f43c0b202b334cc9184af09bb8f21d3a209e038efaf106936fb69e6b026e", + "sha256:cb96e6e088d6cf71c1ea977510948320234824cf226e32f6f6e044f7a9c82b34", + "sha256:cf63c214fe879a65e69a386f915e36104fc84254ab141240f8854602d8e0be2a", + "sha256:d1aca03ede943eb80ab3d63bb082c84b7aab85ea83bd0fd0c200260945fb49d9", + "sha256:d2e56fd3b00222722abfb3f5f0759ddbae4b90811b5ad4343c64030ad1bde70c", + "sha256:d5f93ebbeb8032d47e349328ec8662d973d9b05a70b3c35df1f91fe419b84749", + "sha256:d882a373d8093c2941e01291b7ced96e9cbe4781da9a7751ca7e6c70385e5214", + "sha256:d920abdfa61279ba1a2ef9484aab07bf03331f8c08a10120fa332353d06e6932", + "sha256:da2af0d7aebfc2074080d72efa6ab8317c62481ef1f896f65d9999c1c01f4494", + "sha256:dd8ea6ebee7aedbf7c749fa80521d9ccf1ba473e0d1e14805caafbaad281c889", + "sha256:de8b364c423ef0a4bad9069657d617f9a5d2b2062457a89b1fa16ee199c399c1", + "sha256:df1ae86ff54725a01fa1a0510b914ca53a161b7050be74f6204e24aded5971d0", + "sha256:dff05cb7016dff1e9fd68f4122c127b65dfc59de5306cfb7ad92f956f230bee2", + "sha256:e1a622f13970d81f95d0c72f9dc090dce9085fccfa4c9f2174377ee32bd15786", + "sha256:e49fb0d1ce92cfa0cb198cc5b1b11cdf9d0638658e2a2db2687e39db7c87fc78", + "sha256:e5c802729725bd07e2bc3ab7b76dc7e0bbfc53129d8f1eb1c002c24cf774717e", + "sha256:e841068dc0be4cb6dfb5c890eb88cbdcff2f4a332393c7ec94e8e618bd32c1a8", + "sha256:e916035e3e9930cbdfdd10abf48861340221857f45509565898e012263f7b289", + "sha256:eba154571c16e032112afac0dc2dfe9e63c2ceb7aedd07bb7eecf2ce26d4dd4c", + "sha256:f03460ff076f70ab595bb45a0205ccea1971443575b6920c52e755dec2b3fbfe", + "sha256:f0ec3b750b59375eab5b0fb2b9254810c00a3375be6d789899f1055a1d556237", + "sha256:f291bcf42ae98eb5107edb162c3c998b4a89648fd8e99ed4cbd12705292788cd", + "sha256:f61efe1d2fe0de16158a5fe1d1cf3c14bdb6aecd54d8938fd26512c525c1f624", + "sha256:f68edfc67aabac33708941f26f22a7b8e9f81429bc0cf249fcf7d66b23af8d19", + "sha256:fa95848c929b6a75f6848d3c9793e59db365ee436776e57db835cdbfa79ba977", + "sha256:fd9f8797427910198f95bced71ddfed61130d7e349213bfb8466c9c99e2c46a8", + "sha256:fdb4ca07ab75ffadab4a8b135ad59cdbb3156b99310f3d565370da74a15d6bd3" ], "markers": "python_version >= '3.9'", - "version": "==3.0.3" + "version": "==3.0.4" }, "marshmallow": { "hashes": [ @@ -1815,11 +1872,11 @@ }, "mkdocstrings": { "hashes": [ - "sha256:2703708697487d1b6d6d7b412e176fa436edf120c1bf81dc9e126b12d00893c7", - "sha256:a0b8c2bdd29a6416c80d717aa369bbf7831946bd9f23c2a66db1b1dbe7693dbd" + "sha256:0951b147f352118a45a3db85f0f3b660833d34cb5120a2751315b8d08dafd159", + "sha256:9563828667eeb35256f87a6b61fe857676ac628ec1abbce9aea9839a502c9cb1" ], "markers": "python_version >= '3.10'", - "version": "==1.0.6" + "version": "==1.0.7" }, "mkdocstrings-python": { "hashes": [ @@ -1863,190 +1920,192 @@ }, "numpy": { "hashes": [ - "sha256:012e66aca395d795496446e52aeeb5866312a5d4d3f27da270e5a0b43f70dc5c", - "sha256:09d5a423c71ad5feb5625844ad58050e35df43871004b52ac9c0ad44a56775be", - "sha256:09ffa5d903faeaa5c4dd05009cf81c8bab9f2cb37c548b8d39b65b4cfa7c97f7", - "sha256:0a59a421a32580a009e8a1751345bf829631b990dc1794b80514ab722b435def", - "sha256:116f96cadd935c6122e9228d676fe7ede19e741f5c8bb1c3cddbe0c51ccebea2", - "sha256:1302b90c0e52281681b2975adfe8a860cb7b12216a27b4b0b4207c44bf7bccf0", - "sha256:15aa985ac73a8db02db7663381aa109510449d3819d37206caed27b33a65a8a6", - "sha256:1aad64d99730d013cfc6debafed22783b4fc5a7f4b8bc744d2d8cf7dcc880551", - "sha256:1c80eabb4035ecf4ca9cd49cde8a9fdd69a729e63e6474887d1523ade7aa277f", - "sha256:1f3ed25271581281f2fccb1adcedfcde4c07362eec69189b50baf6f90e3ae159", - "sha256:1fb6f8fb9ff0b3a69f52c66ce397b0246583e9f28616231b0e32ca49259a5fa6", - "sha256:214045a5bf00113a146ab9ee9730c44501af6723cdf1f6830932f7b5ef2e7af0", - "sha256:26e15e4aecd8617dfbaecb37d223e365d7b39411fba20454be2670a96aa74cb5", - "sha256:2c25dfa72943e4336ddb6b0ee4277b47a0c85bede0807530ec68103bf58e2c10", - "sha256:2d8240cb4c16fd831074aa2b2cf9fc54664d826341d61c372245b96a74a49a9a", - "sha256:350ba9783ce969cf9f7ce6e6a9a58e1a6e2a19ca025b7ee448c4db727706212a", - "sha256:4c8a6d2ebce6305fd82fbefca827775437147052a976ee7c94b36a0c1b52ac6c", - "sha256:4f8929ee6c96bfbd7b4ed2032e0c03af86fe1826740ab61ddabf9072d06e57ff", - "sha256:536f963710a4e63934d80ac0dc4f478804a83e9a84b6828018f25d09953ada33", - "sha256:54a115e5a73b8fc44f0cebef486365a1894b5c9760685d4558b72b7c3eb846e0", - "sha256:595d020938c84e320bcf40ad71089e108eac0d377cd018e14a8c094f39e98d85", - "sha256:66a78fe4556c60aceda5916f9eacd638b18e9e681016ec302dcb4682d6d4d034", - "sha256:6b05c171afb3aa07adbd20abc00aea86fe375beb0fdb9ef780ec5b7f63bab1c0", - "sha256:6cef4bb1706dfec49243c05d921eefb4e190d41e2528b30d8035ea1f36b4c24a", - "sha256:6f24021b9f22bc6301c37b196974a92c1c18dccedb6fef3dd252e95f2d6adbe4", - "sha256:71b39d9f935b6ec0f8753e3e2afb51e3efba6f2e05b68b32a40754d24bcd4a3c", - "sha256:71cad2b2a7451ab79d8f5e71b453485b6775963d5cf794179144a7463fe6e8ec", - "sha256:76c2c1e6bfa5c84adc6434dfbf013aa92096a7985221762c8f11fedfd20fff58", - "sha256:8617bbfae4486cf99c9f899966699428d19da931d06ca94ad3da986c76e15997", - "sha256:86bff898a431c0fb71f7610b75726e75a54d47b37edc9d537f48de63bb3c0b90", - "sha256:8e4dd766076855b5ff7ea52fa5f07ce26286726e0f8bff446b7739d02e6ea204", - "sha256:92f30e89b8ee0ecf363033576c422b2f58fed6a80bed0aa48dff6d14c654663e", - "sha256:93e1f5447e2b1e479d7bd74701e84746b86450cff1fc368b132d195e2b8f8211", - "sha256:9a37475425b431b4d060f23b4f52cd2f3aef6bc7c654bd760adf0040eec9d435", - "sha256:9deb49575e5b0b94ed72c8a64ec4d033381adc27e9060ae842971f697ba96104", - "sha256:a5fa86b80fd24bcd1aff83ad23be44ea323de3f787be8f8b15d4a65621e25321", - "sha256:a6391fafaba97500887132cd582abc6e19452b1ac775a47caa7b24490e152058", - "sha256:a72f874bc9e10e4b8f80426fb49716d5141f64442a0c8418065093ec8017fbb0", - "sha256:ac7bb1c52d445bd4f8f7f97fefe6abc3a084dc4d63df50d79b17fa2b78e89297", - "sha256:adc1ada2662f8a5f960b8a10d9986897e7499ef07e06d4cfe7197f8cce923c07", - "sha256:b00eefbcf0f292945c4b4dec2ae845389ef5bcdcd596e6e4328051db5b5ba694", - "sha256:b0521d0f4aebb6e06189451025fa17a913287b13c03d5fe05c017333b654ea5b", - "sha256:b5d93cf48f687479941d12b69c873ad2cc76bbd487f0091c2200636497f34034", - "sha256:b7e18c623bb5c95acb3b3328861272816ba199fb531921c5d6d0b675f1fde9e3", - "sha256:bd4cb9ad3c7889b9b3fe0a9a9fb5d2ed26f9879bff2608d9f01aed147a20d231", - "sha256:be5a8381859b6da607c84f4f7d6847725f1cf1853ef8a2c9e115b7d58bef47dc", - "sha256:befa1ae5bd6030b3f512b43ff3fa5290bbed6b84411a44244b14adf835f5b89d", - "sha256:bf63afbe037eb5d2fe87fbcc7778e61da53ebaf21d938a4515aa73b62532a5d4", - "sha256:c00abe94c1a69d75d827dcf1c025b25c8a45d230b3bcd77a9020883a1b047653", - "sha256:c2381f82999704f818e2c987a865050e285ec3621262c66d40f5a96c8f899f8e", - "sha256:c76d5dde9f445058f83d0c02af00557a4db91de9a9a57c0df87d1535001d654b", - "sha256:cb189f09db39283b26bfd061ec16189e14f71c6755207f72a0f7540867afe5b9", - "sha256:ccb32e0525d29e8b0572eb84c9a57af0e7a4e615726927506f55063c62414034", - "sha256:ccbc4665079665c3cf3bab4db9f6b095370cd6437d66be549b6c2a1fd19e1958", - "sha256:d1c89973648c85069c5046ad460f7b8a00218b29a2e42359ac8cc63e9ab94832", - "sha256:df2d5874ff183595a4ba404edd04f6bd9b5505c1d7708573f6a6c17489a67563", - "sha256:e01c918ac3d48e18a927cf7b14a26a3e29ff2bdf2eacb976da0aecd6a43ed034", - "sha256:e6ab667ba76450084eb64013762c438ea76d9d29cc676dcd6c2e9892ba37f841", - "sha256:e931e4f499e0dc7ef29d269a8e5b35dd722e5d14be07df6240166ea7c6532fae", - "sha256:f54660b0eb6b0b9f36e7fe1cdfdff472028dd0d14acd9b9b65098efbad059469", - "sha256:f59a878c33d6b88122d80d239bb3b845d58708750b0cb06a09aebb9b18ec696c", - "sha256:f7fabeb6cea87d65f3b926de33d03fb016cfdc29314c90974383b5582ae72891", - "sha256:f9579f383d1bf9df80081e72760e84960a7fd4f88cf0c9e535a8597c9bb646f5", - "sha256:f9a2353b37a1a9e78fd82b27ad7e2a32a2d036604d18f02b05e3136c62ca3b09", - "sha256:fc36dc566135b5eceec4cf89758fcb719266a019ef07dae1754ae7c9f617ef3e", - "sha256:ffdc76bfcae6b255dff75202c5e7feaf95b40246bc0a17944facc1fecf9f79ab" - ], - "markers": "python_version >= '3.12'", - "version": "==2.5.3" + "sha256:067374eb538c34c745436365cf7b0112595c1d326f21ce4ff340f61230239fbb", + "sha256:0b4724a19de67bea8cfc4970798efa78bcbbe2ac2613cfac16721a42d44de2a5", + "sha256:0f02a46e49cfb6c73bdb7aea1c0d3461dbae9aba613542b65f657cd3d17b9fab", + "sha256:1c2e71b04c6cad90026e544501bbe0ab9290fa8a4d845e7e8c0d124fb429c988", + "sha256:1ef3aa6d7e29bb13677323114280b05acc57607fa2300e66432d665d5418a162", + "sha256:2132418bf8dd124a427ca9e6a1daf9ee1a87185344c95119ceae868b99466da1", + "sha256:2199ed071f460487c8db2c0e5c0b564494190edb4772fe80f9aad88b2604def5", + "sha256:2377da2dd3ba2c1200956acbab2a358c83b8e1f8531191672d1cd6ad83250d53", + "sha256:298eca75243f2cbbfdb460560b9fb2a1792a33cf2ab4286efd43d92e8d3df508", + "sha256:2c2c4afffdeb7920e445028dd71eb932cac3e704792e964bc2a232426d4f1255", + "sha256:2ca144f15135b6212a5c47b1e2aeca6e412f102f95a2d5d88d8aec77eb255de3", + "sha256:2fa3328f784fc8277fc48026f6cad516f5c561c5d8e2e39b3c9e0c8f23223b34", + "sha256:325518d4245b9e331387702aa58c2ce1dc4cdcbb41dfb4ccd5dcbc7e08db1266", + "sha256:332f3378fe077dd850e677ec01bdcc4f22368fb5d50ef10b2c79230b1bf5a592", + "sha256:3573cd22564692a5b899ec344e5d5b9cc4576f2985b96f22af3564ed54f2710f", + "sha256:381a7a3d2e65e64c0ec302795ab9dc12bb1e73f150904699c153716177eebdaf", + "sha256:38f47be9f74ab870d2633b5456ae519c43758a8d1fd05342f0ce4ecc034396ee", + "sha256:4054173604cd8658796053f1f3bc0befb68ec1c0762c57fdad61e199256a8617", + "sha256:468397ba3c64427474706e5c9123fe266395496714dc684294eac75cd4930d1e", + "sha256:4e263278bfb5ee6409db8aedbc4cc32973b1b82bc1e8d3c668551d04d83a7e37", + "sha256:5258bc06526964be5face2fc6f756857a3f24f21ec3e72ca131337a75b165d6c", + "sha256:56733449d2544178beaa4545cee357370440cf056c197f9c7bfb19dbfdd0e86d", + "sha256:5ec3753760c1a6d8bb91200666e545c3a9728e6269dfb5d6ce02340996698aa3", + "sha256:5fbf7141bbfd63aea22f435c9062a032b9ea0082fe9845dad7f021d3f1234e71", + "sha256:64d1c8ac28a4077cf987e0a71a7a0ef7e2df70722f07f0baa42dbb7eb6938647", + "sha256:64f9c9878c1938476365e11ccfb6b770f3b9e5f045ccddc514235041e6959365", + "sha256:6c109eac9cd439193678f69d70733c1108487546ca8eafc107b510ae10c1aecd", + "sha256:6d6a71b9d9a97c03633aa12565ef2825ffa036cc1d99cfd50dacf0f128af4fe2", + "sha256:6ffa07666f8da0eef81d149934a626d0d95fbd6838432a33e66245423a9062c0", + "sha256:7415db95818b39ec475a5eea54d9e3b6bc83e3912158e46da3438cdce399804d", + "sha256:77045a4b175bbf5316ec08003880804336c78f92281a1b72222b274ea85ec5ac", + "sha256:7a14a461d9340f1b46b8648578aed9cdb8b3b018a8fac6c1dde2c9192a01a87f", + "sha256:80d6ef6e8620eb2c2b4c4caad50b5935d6db3cde2d51581b55dcc79e14016d1d", + "sha256:81e3420b27048b65eb14c3acf0c174a8cb0e023277716110347d2dcb26026dad", + "sha256:823874a507a84af050493b622affde94b6f7c3a0dc22cb2801381bc03b871c00", + "sha256:8b4d2fd2d34e5f8c9235ee787de5631a37a28402b15cb80814df973d2be54129", + "sha256:8dddfbee2e68d26d0d7d7d9cb247b1fd4409241cce32d815a11d97ec2cfde179", + "sha256:950ea81d57ef070665581b6e1b5f6a029306423cd1739c5b95fe78aa30db6b9d", + "sha256:956555e0603a4d38019ae6925711cb9dc43195c076a928accf7ea5d50bddfe53", + "sha256:98b053943e5a0474ec0da309d2cb9d3f18ea57f8a2067c2ab7b5f763d1068380", + "sha256:9968ab7e49b93ac6e1c3b2239732183152c9150f16308d30b66a372cffe3483c", + "sha256:9a94cf751c9ad8ebaa835bcd3d40dacf8534ad086b88c38029b65123c7999d2a", + "sha256:9cb18a327b49c5c337f972b03682f6a49855525faaf3c0d3e9c96cd0fd8880a8", + "sha256:a7b1b6353e36a7e50de2973a38d705c88ee93adcf120673cee7f45a4a3fa223a", + "sha256:a813ed7719bf45463c51779e6a98d0385fe905e48447526938a4b8337333d551", + "sha256:aa1cce2ff3f8d953de38b76bf44602caeb69f101430208f64a10067f7cb4b1d3", + "sha256:ad62a416ddcf863bf44bba76fbf6b53366ab0692e294f51cae4b5fbe0d246788", + "sha256:aec3fc4b32ff82421274f5d205c559c51c840c8df66a78efd7f3612dd005a26a", + "sha256:b1185012870173de7ae33d370bd45b1cf5baee747ea4b97036b65f4e93016877", + "sha256:b11e8fda06a7d69f15ebf542660b74466c2e51094800c1fb794f47ad4faeef17", + "sha256:b64a85f40e154983960a4167d4c1d57a50c7f109b3d3264a3a984154e90a8454", + "sha256:b86966fbe4ad7de710422175572bcdc75fdedadfb54bc6fab7deabccddd7780b", + "sha256:b89d0aaae2fe498c648f4c4795c084db535af5bd98ef942b2a3681fb74ce8645", + "sha256:bc39ac66a7a9a3fbd6134fda43136b60ffde99c8f4501e64e0d2b24da137babf", + "sha256:c05ede731b03fb1b7591faca9389ade3267d2bddf1ad8882bb3f2cc5e101694f", + "sha256:c6342f54c67093cae5c0227eb0eb772fdb79f2a2c37a6eb278b9909ee06aa356", + "sha256:c668b2f0d651605b58892644b0e302c7157f7159544227758c896982ef384b18", + "sha256:c9b80cdf5cedba0e90d93fa5f9a333c4d65bd545cd669b71bb97ce2b703c9d73", + "sha256:cfd73180400042a7c532d30c5e287bdd03c59ff9ee1b4c0316af0539e29dfe23", + "sha256:d4cccbbc78717966f764cd3af4fb70276fa01fc7a2688af11c78901fa5c04f05", + "sha256:d549420b8858885cea8838a727842249218b9c1da24dd517e25c9c7a948310a3", + "sha256:d8200f16437b289a5bb927c6e184eccc3e8389bc0070fea4cd5b9e13c1757959", + "sha256:e94aef2c639da4a960ad0db8e06471208d8589974953d78b61d345b4eb99e394", + "sha256:fbde6962867ee75b48b0ee29b2b9372ec5d617799dbaf38e82dc0596f2f7738a", + "sha256:fe4d21ab149f15e4e6043dfb0de87e6e5f34ac176cde83060e9802981fca2ac2", + "sha256:ffa6ce09a1c6a08e9667dd9c97aa0b14184e8d18f2a14b78b2a2328c9147f076" + ], + "markers": "python_version < '3.14'", + "version": "==2.5.4" }, "opentelemetry-api": { "hashes": [ - "sha256:711ede81773c8025c2c03dac0450bc89f3d30aea6eabcc815c570d4e35a963f7", - "sha256:80e068aba7cd56c8b58512d6a36f8d25cb1dfaa0c0a4cc1c938ccf9f362d9cb3" + "sha256:aa38ed19bcc084ba42782a73255b3582283eced7ad6dddbd6695189e69adfb75", + "sha256:b31553efa588ae44bc306f863c785c5333a9ecc091248c6ee68b4b6c87fdedfb" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-exporter-http-transport": { "extras": [ + "requests", + "requests", "urllib3" ], "hashes": [ - "sha256:2c229b6593eaa22c86d9b8a15843dc23b406dbda00fb138339189aab07923b4e", - "sha256:c82689928a11505a2a0a26a04afe0ce06d270d3db984bc16c1a80ffa902db00e" + "sha256:2f95404bdee7f9d2d529c7de56c7bd86d014d774d8fbf137810e0167f8a492bf", + "sha256:443080203bf52586ce0b2ad901e8951c61833eab1aa539ae6f1f16fe9e8e7952" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-exporter-otlp-common": { "hashes": [ - "sha256:35d24c867310f4713a9738b0202b6bade77955418fccb9e2f7eea01b76263916", - "sha256:362268ec6aa705e183776ff938539df1e8ce45bc5509d242538b1d40c26fe6a6" + "sha256:00ff8592c3a7cb729ff3fdc7ffa12372c243bdf2163e80c180994d0c7bd83ee9", + "sha256:6b1403487a2185ac1feb45fd5546fdf8630ce71c36bcefaadf51e2130e9e23f9" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-exporter-otlp-proto-common": { "hashes": [ - "sha256:36495115a0c6a7aa946cfda9d59b6ed4e917b6ab0f75cdaf66bc1b176ec1be1f", - "sha256:7e1410ae6d3ed301f7a74bec96467d519d3f37e52f9d95b309ae125e5a1af863" + "sha256:2e4adcc3a67bcf57804fc49514f0ef64974ca7590aa3491da389852b4a0628f6", + "sha256:2f446183ae7047b036226f1d846c41a834b0e8755ad13b51a51dd38952eb466c" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-exporter-otlp-proto-http": { "hashes": [ - "sha256:2f35496d96809f946f41b8805e6b93aec6c9b71b5fd759b75b6af4c084d992ae", - "sha256:74385f99266dafdefff41f3da4b76f6dba79d237a9d4487e6ff1ee653c74a0a3" + "sha256:24a97cf3753c7fb52fad44a696e452ff371686339e2acf3309e2eda3d0230700", + "sha256:45c218405ce3fd879596924b1874bf9a8f6880206d61065c5a912c8e5c297fb7" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-instrumentation": { "hashes": [ - "sha256:0b32e2fcfec1e4bd48511a3b77ce32bfb1c16dcd5479396b21f9086a4b06c0c9", - "sha256:316715ed7b33a12530c0ae3e8d4cdf26d70e1aad358d7ba256e5dea2d4ceed71" + "sha256:4c4aa14dc9a24a02325a9d4c42c4d0208dbb1374c2b1b8fe6c9392d59f3e1008", + "sha256:e79a510f7d87c72d95e964ddb42193a0d9a75668c027d980eab032ea1322a5ce" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-instrumentation-httpx": { "hashes": [ - "sha256:2735d1868749ca04ce47a3802b0b809e3a00c05a65140e05bac5700e74410539", - "sha256:c89297975f54d67692d3c29e9e33a1bdac47710031cc3ed0d83a0c9765336981" + "sha256:0342a4002c6dbc6c4bf22cc7e698f50f5c8b77f63325c6f40c94ab87e016bf4d", + "sha256:5865a72c68098c85955a271ab8744b480a36e3ee492d35b8cadb93c7c4dbb618" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-instrumentation-requests": { "hashes": [ - "sha256:053dde08fbc1d223058e33d477cf81e2bdcbe7af3893787283339b2b557d4b7a", - "sha256:2f9df08bf99f5da4bcfda70735492b4364bfcc5bd3f48232658e936f97ee1a22" + "sha256:28578f72e68e3a5be3226c618ac9570ed360ef1dd22d5d6e0721c6905a4ccc67", + "sha256:7ba17d984a2bd876b88bf0aafcca27b5e3ff4c1821e0fe07641e380a3cf3a3a2" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-instrumentation-threading": { "hashes": [ - "sha256:4aaf38b96b47a04319b8d96bee4f1daa04e0d6c697525595746aeb61618c002d", - "sha256:4c1c9adf42b83b6f44ca4bb99799e066ccfb1869c2029bc73d862c40a8ef932e" + "sha256:2c217359439d09ca4a4be524db368c05a3cc7f218b85e8086f22664db0a03538", + "sha256:94039c60603060d26524e31aed1181a5d153e43f58462d110dbeb4830687d7d7" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-instrumentation-urllib": { "hashes": [ - "sha256:3eb6d2b9b28bb51188d77092a58eac2ab04852d244acb51333bdf42b0e933c68", - "sha256:a919d8014dcf0065ad42ce5c78dd158c76c7342929f451d726462f7ffa68e367" + "sha256:6f679d785ebcb04b791a889d8a9c0e8edf897a85ab80a7a12b0139c461b14627", + "sha256:f00daa25375fbdf88b7e1a425ef54c704674d8bef639c834de93df9b3f88d7f4" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-proto": { "hashes": [ - "sha256:96ee414f24bc3f61ea8e17dc56b4348d4049d73db3eb17c6b3edf75b5b403300", - "sha256:9731566359d7b8e1ee1e149d8e4ad6865bab965e657ad3387ec2784d16927666" + "sha256:79e0fb95e4616691a469439238aa9224d75779b3e108e895d1aa125ab29ca77c", + "sha256:f38e2a8413053c180cd3d2637fbb279673ec2f6a6e09c995aafa2f452c52b46e" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-sdk": { "hashes": [ - "sha256:20caa5130505e386c67c3da1c76e446c842698ced54c76c6148679539aa97972", - "sha256:5dc634c946546f61b757c5b1781f9fd1a10e96ffaf7357c797e508fe9c57e75e" + "sha256:63d24a6ca645019a631e6a51999c73e93adcac1196ca640b8ae78a7cc4762bf3", + "sha256:c604c11dc429810812348989115fa44bd558772a3d7442afc43d024f2c250ca4" ], "markers": "python_version >= '3.10'", - "version": "==1.45.0" + "version": "==1.45.1" }, "opentelemetry-semantic-conventions": { "hashes": [ - "sha256:175b19dd98c4473f4f43a2b1df59186fd7b4a48cd3f77cbe03438b6d6fda230a", - "sha256:97a77dce484c54861e7eeff7651fd8a806dd3c30e501dc316730215ec36890e6" + "sha256:497ca63bf383723411e8eaf60c8779e9877633c936bb641080adab59d0eb6ec8", + "sha256:d4cddeb4315490b35213f55e2bdc9ac54bb1e4d318927475bed62b35545e581b" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "opentelemetry-util-http": { "hashes": [ - "sha256:7f5e581e94f023b30995f700e41ce319cec82bd542ff1c1c7c9b56d6b10bb687", - "sha256:a2d53859630abe8e5abcc4f867c5a809bb95873033573b1a67f6ef43b57a8627" + "sha256:047dea1a628031f857a5a32261dc0e955bc162d39993ed1cffb8f2cff5ba8a62", + "sha256:8f443d7abcaf29c4a07b373bbd31b5b39132c0ed3c27d015a59dc0323d5b1c58" ], "markers": "python_version >= '3.10'", - "version": "==0.66b0" + "version": "==0.66b1" }, "packaging": { "hashes": [ @@ -2063,73 +2122,69 @@ ], "version": "==0.5.7" }, - "pandarallel": { - "hashes": [ - "sha256:1c2df98ff6441e8ae13ff428ceebaa7ec42d731f7f972c41ce4fdef1d3adf640" - ], - "markers": "python_version >= '3.7'", - "version": "==1.6.5" - }, "pandas": { "hashes": [ - "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", - "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", - "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", - "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791", - "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73", - "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", - "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4", - "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", - "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", - "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", - "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c", - "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", - "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35", - "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250", - "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", - "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826", - "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9", - "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", - "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1", - "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523", - "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", - "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", - "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53", - "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", - "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", - "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", - "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff", - "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45", - "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", - "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", - "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", - "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", - "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", - "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8", - "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", - "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89", - "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66", - "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b", - "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", - "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29", - "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", - "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", - "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2", - "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", - "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa", - "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151", - "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838", - "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", - "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a", - "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", - "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908", - "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", - "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", - "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c", - "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee" + "sha256:0704044b676496b8350e023b09f174a26772456c974a2b11c36bebb558c9490d", + "sha256:085e3786ae6b2e82b406266bce36690f72b9dc1421903ba9296b2981a9fcf586", + "sha256:097090508a1dd335013d39106fc10b20f4fd4a171638e47b77d55798ed9dab6c", + "sha256:1bcb3e9ed29e74a7439cedff9e2aefd3ea65de84d7de9ccb6c194192541bd60e", + "sha256:1e7c0afdcaf6661d795fcefc2f647ddd1136f62cdc153fba177c685d97a87808", + "sha256:1e92d9fa834c7d877130027cddc0cad8dcff97c1f6cca26bd6310f847228b658", + "sha256:22172a92e7ee678ec0140c7af4fc9366b55413834a1cd86af78b3caa0b0574de", + "sha256:253e12cb9081b0afbac607920f6142975966bc315135e09de275fdbaa415d2de", + "sha256:265f562fdd1079f69f3de96dd425c3405224038c0af4f920c54bd240ee2c4640", + "sha256:2a8fc94be2ee5f1d86f97aacd8cc566f81680b6498e76f3007421bb5d98151bf", + "sha256:2e5fa32ff162dfdbc280157d664f44d23049ae414725af9676df339c501d82cd", + "sha256:3ef908d28590b3f42d7070e7ad8f9b34b442b260b7f3c1afb57e0040c58cdb1b", + "sha256:429d9df32731ab01383ed98f2baa7a60368090d1a94fc06019a12062510e8630", + "sha256:47121f9571503f724c9b93e297ab6254ac99c77adf5e9ed085ea419fd585c258", + "sha256:4e25e2e1adee99ddfada6f7206a79ae8e9c8a8861b0e3eaaba165006d3eef18e", + "sha256:4ff44b2cb51cbd691c91f92c4ea6c71e34003f239ebd67c2e857dc898466b49c", + "sha256:50c44cbf5820b6b91a5f74aae04972472aefadd3cd9fbd1010409d85528bd570", + "sha256:569e114072b24fc4970c12e2b4bab252671668a40b324318903380cab0254c0c", + "sha256:583be68728a31d0d750d5b8d9e00f02b153df0d4655f858bde93cb84cfc4227c", + "sha256:5e75072773c1b2f7cb63faa3a6f562aede11f3976f68ed34cb538bc091a28171", + "sha256:5edd0a7abb0986ecce1ac81f56d99b6763f86aa6946dceb6c661224f90af5a19", + "sha256:60d81f9e1799b36f3739e7fff44d1fbb2e8fd5a271b3863e03de9715fccda0fa", + "sha256:62f51d7f651c8054c5e82a69265c98082e795d1442df7ca6edc3a545d61214b1", + "sha256:654aae059295dbba6ecd2328ca12712a2cf1676214c8699f1c29213f7ccf9c34", + "sha256:66b07ef7315a31bfe1089cd3d71a7de781c9dca986762d0b4fe7c0ef17465d10", + "sha256:6ff482fa91fa2bafd92e8fe66ce3645c851824310f295c1f0a2f96e928fc4541", + "sha256:77ccbe5057aece6fc172b9b77f19c04335af6882bc2e10c8f3ee4e6bfb3da553", + "sha256:7dac2d65e9087e8e7b5a45fe15c4920911a221df061ab629943ce016489145c7", + "sha256:83e91d15738d7783c050197cef2f2cf82fc6353dae9865aa87ed1fa16aa4d55a", + "sha256:86fa853a12e0b70927e2b1ee00d56d2224ec9cbb4b9d58348b5ad52d2f21150e", + "sha256:8fe77b408d82e2615674dfed62533b95e18a03610573877422aada4f625d4947", + "sha256:963ca21199097a84c7827c4678b04e30833084fbf8ef44fde3fa7180a29f8fa0", + "sha256:97274c9adf6255bb48c620cd6959805efa7f09ea2167f0e0ae006a448cd2fca7", + "sha256:994a79608263fe1c14cc48ffa7300e2b834b7d1cb406ffe96a08828cb0cdd79b", + "sha256:9ae8073aed8e21d1a7fe263dcdc6840743549722a6738198a0a46000fa9476f2", + "sha256:9dab635a549e58a053c7b0fa054dc0bd7be22f0ed9a720f4a85d5fb993276172", + "sha256:9e492cd4bdba6778de4fe0df7f4590c012161ebcf9902dce01b01dc683105514", + "sha256:a3a22e07fe75347eaacc75b0e85297947af4fba6b4aae23916bd8b6828d0bba3", + "sha256:a4dbd4dc65cbe645b92b8785d0f96dd7311010dc6606cf620e51b07b8788a12a", + "sha256:a77a1a44e4d88f1c6a2a64d3eb12efec8420875722e14279800b173a7c7c2804", + "sha256:b27c8d890e4aa2171437ae2a39de1d215e674158e4865c4023a8b31c932513b2", + "sha256:bd75ed0c840f709fc2ae26ddd9534ac77ca1a48ac0cce521a74acaa85f3340a7", + "sha256:c6e4aae3e9bea26c6c9a20d88d96c86ec4a99b4db5fd516bcb4e829ab2c0ee36", + "sha256:c826e9babb7790142c399f58599d8de679bea059d7b39c5b6efa2096fac37266", + "sha256:cc39303913e2ea129915670de5d1c9fbd647f543bb72e5543bac8baa94e9e42f", + "sha256:d7564d86a94c2eb8ab290b07f63ddaae5c032fa53897c29a2ff2197d43aee8af", + "sha256:d7dcd21238cbb4828ff148481ba01cac8946dc5121457b5aeba28636f8f99a60", + "sha256:db7ec631f26223beee8e5c9e0b8f23c24d8197bbd1d982421d4e3188bea51965", + "sha256:e3dccb584123b399c07562ac4d62543e90ede49ddf8ce3c13ffc64cbe828c281", + "sha256:e7c1905ef02c3d6d43d9dbd5b6ccb4da4870a0b0c821bbc103fbdb6f3ad2707b", + "sha256:eb6900de08ac85f93ac4948aa6b80842eba555875337b8359035ac9c43e92d34", + "sha256:ee913a91669056c1de1a6b733fbfeab711de9e54e3bee2dfa5fe79d9457247d1", + "sha256:ef738d71d1059245b6bb03e312be06d8b3821326a83486c1ad03b9aba3710e44", + "sha256:f3ce8a6968045481e91a3990e797e348ce13db45ee164a7095bbc824e26c09dd", + "sha256:f4e7c52eb108d752e7592268108fd3e98efd76d83a3125cdd06c621c2e44359b", + "sha256:f8029ec0f1f89e4f985929ce1f6626dabf3140d61a4e9c1215afdab34eaf9a5d", + "sha256:fb625f426b375bcc96e3a04c5d5d266cd7be6ae5d6866e0e703382ab5164068c", + "sha256:ff51a4459ed036e93d1eb1bb5e6e7b28685d3cb6b7c12b91c05b31024e234729" ], "markers": "python_version >= '3.9'", - "version": "==2.3.3" + "version": "==3.0.6" }, "paramiko": { "hashes": [ @@ -2149,11 +2204,11 @@ }, "platformdirs": { "hashes": [ - "sha256:29dbf06d96c500bc6bdbce75fb0a14d63279c93b1842f97e72a135b33e856983", - "sha256:eab5f70271a490ef74618bb314fbb86e3c7e82fa3b9c922c2ea0e0a1a155d329" + "sha256:1aa0b0d3f224c1f07c295121e312a5a24a180d6ae5a8425ea1784b3e3863e9c0", + "sha256:3dbcf4cd708f21cf876c4eaa90e58412bc4f033d87143f41b1493ff77c25b7e1" ], - "markers": "python_version >= '3.10'", - "version": "==4.12.2" + "markers": "python_version >= '3.11'", + "version": "==4.13.0" }, "pluggy": { "hashes": [ @@ -2222,11 +2277,11 @@ }, "pycparser": { "hashes": [ - "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", - "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992" + "sha256:51d5a8ba2be0bbe440b99d2112604c95bbbc3c2748a64260186c541e1729cd80", + "sha256:d875f09c3507d00e1aba0eecc6dcadc1352f30fff09dc6bff2f1c2935e97c2bc" ], "markers": "implementation_name != 'PyPy'", - "version": "==3.0" + "version": "==3.11" }, "pyflakes": { "hashes": [ @@ -2246,11 +2301,11 @@ }, "pymdown-extensions": { "hashes": [ - "sha256:4a254b771acfcddc6c110a7f4590d818f1f849e2d5aacf69b4b07c8dd2a9700d", - "sha256:fdb8f47f5d7fd069d10ef2a7d8908e613d7865ff0419d544a0ffd3984e884f11" + "sha256:02da896c362b548d85123e7a377a40024ea6ea938b4e45ca064e408afd994b64", + "sha256:caea66e916b4cfe987b5dabb0a78558e3506988f6353812b0b0288be8f976c16" ], "markers": "python_version >= '3.10'", - "version": "==12.1" + "version": "==12.2" }, "pynacl": { "hashes": [ @@ -2382,11 +2437,11 @@ }, "python-discovery": { "hashes": [ - "sha256:cf87d3627dfb4412437fdd5b13eae402607722998d21567993aedbc59b23c15e", - "sha256:d43fcdef879fe795352bd13ccf8d185ba5a9f86f36cfcd00529f596e737442b3" + "sha256:cd1738ca1d37c86ef9d0b654dd46fcee1e41c97c6add12575e8501ced39afdb4", + "sha256:f0c697f95a3aaec4174a6e5e58f5885e25768684bafc76f1afde384709ebdcf2" ], - "markers": "python_version >= '3.8'", - "version": "==1.6.1" + "markers": "python_version >= '3.9'", + "version": "==1.6.2" }, "pytokens": { "hashes": [ @@ -2436,13 +2491,6 @@ "markers": "python_version >= '3.8'", "version": "==0.4.1" }, - "pytz": { - "hashes": [ - "sha256:464303645bafafd72418898368b2429458f709cf1eb6a15372fbcc396b64da63", - "sha256:9d514388fbc89ca0833203464272ac485b8828568ab73532f5020f17e892a0ff" - ], - "version": "==2026.4" - }, "pyyaml": { "hashes": [ "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", @@ -2556,125 +2604,137 @@ }, "rpds-py": { "hashes": [ - "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5", - "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680", - "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9", - "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538", - "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804", - "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf", - "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", - "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97", - "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6", - "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96", - "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a", - "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187", - "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975", - "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f", - "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703", - "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9", - "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127", - "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f", - "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa", - "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05", - "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171", - "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba", - "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c", - "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223", - "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4", - "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885", - "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698", - "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f", - "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7", - "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed", - "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f", - "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf", - "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e", - "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f", - "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24", - "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a", - "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41", - "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc", - "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d", - "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146", - "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e", - "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e", - "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4", - "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12", - "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7", - "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261", - "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6", - "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5", - "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93", - "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7", - "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda", - "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8", - "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342", - "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c", - "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb", - "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0", - "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77", - "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3", - "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885", - "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826", - "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617", - "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb", - "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577", - "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80", - "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e", - "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945", - "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90", - "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7", - "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0", - "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140", - "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822", - "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba", - "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9", - "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4", - "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a", - "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8", - "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf", - "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4", - "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324", - "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53", - "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b", - "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41", - "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9", - "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca", - "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1", - "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d", - "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690", - "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107", - "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2", - "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76", - "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d", - "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af", - "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6", - "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db", - "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369", - "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd", - "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911", - "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504", - "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a", - "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9", - "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13", - "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc", - "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278", - "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868", - "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2", - "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd", - "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4", - "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6", - "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9", - "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00", - "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f", - "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e", - "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442", - "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da", - "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90", - "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef" + "sha256:00ba2d8c7dd4ee537978ddf4b3fbd712bef2d8751603f7f3146b3f4287768e25", + "sha256:01445c8d194aa032a08e944f16567672da1c62dbdbefd8b6d0693032e290cf68", + "sha256:028ad274ea951dac64491b5d1e65712a4aeabfdbdb9fccf797b57bd899b0c495", + "sha256:0483515261947e4e8b8e1375bf7463e7eb6ccfb3d86e7b554d90cd5285f20f32", + "sha256:068c37bba854ec2fe42f7365c640af11dd9895890ccbf2df5070d0c059bd7f96", + "sha256:074a4d198bc34d9a8ea425114fc3ded6d11ec01f6a314a8db67454a5152d8834", + "sha256:07deecbfce94c78473018bc7d10b337cc651d12df87a1eb2cb3e4024bc9c33d0", + "sha256:08dae4a4095150a7c4545a1fb40b98e1ab1744fbc2770d92c977b9dadaa49ab6", + "sha256:0da298fb372dc192610a4b9ecbc68a0cd8b675bbbd1fc519d01b41cfd658333e", + "sha256:0f045bb053c9057720d72c56dffe30dffdc05997b2897a827b9325f0ab6623fa", + "sha256:10e208f2425d973938afcd56e28a7c4be32e27b6a60b5d381f49fb9d8acf9759", + "sha256:136a1c3fe4402b7008bc81cb62ee538481795b61a7e83df88dff3b3f02b726ff", + "sha256:159a7aab5c5e8b112c8830f54717ce56da1252ebdbb526f5be2df2309280b9e7", + "sha256:172e47169583f46ce118cbec68e6795d0da0f4606b488b6434f8276bca0a058c", + "sha256:1c2d1f6da5128eabf34e963d7163a818846075a52568250d006c4c953b40f903", + "sha256:1d55198263bb51f557550c6ed2e6d1cb6a6fed6eb5c9120b741c5926bef8a45d", + "sha256:1d77b649e6f7cdf12ca5c2a98dad0ad37f9ea9b6f960408a92f0cb12bb3d04d9", + "sha256:1e8d4d79d828299bf44a55db22a9388ab967b49d17132c88eab0f4360b48da8e", + "sha256:22ffd29a63d71fb1b81552c21f2c2b734949b7ac751a9be70675a939a900839b", + "sha256:2693b2728bbcc48d09a981a356954b0c47c53ff25b545856f28a889ea619f69a", + "sha256:270bdcdaac5d5b6f73c5e22e7e135c7f2a50e789f71d9e241d5be8d90026e19a", + "sha256:2711d29b653b3bce48a63d18b9c6b53274669e6d6c4094dddeb4d9a0e45128b2", + "sha256:2c16ab111bc27c646ba8aa005d0527754edc538ebb636f0b1bf8e244b48d1945", + "sha256:306ee1850d8105b5baf977e78d45fcadd12c1a54678d614c9baf217708446e91", + "sha256:3231c4c0e521dafa5be0c9f114ee2c2ad46650836f2d72caa86801950c3e7044", + "sha256:3890a6aa36e6baa53d5258a2a25d3ef8b37ad165a6ab27a892d7c3e3a432cd69", + "sha256:3a72c11530d71abfb66c8d7696a2f86c43e63fca8b948f1a784ac490f4ec688e", + "sha256:3b5a6f40f0a1486b4b36c888123afc67acdbd9f33235927acf5ff295429a0ba3", + "sha256:3c91c210ae7645626c608400e3519b4a642f837cce09ca830db3beb2e9f274d4", + "sha256:3cd182d7291d29b92c521a0069d9c01ba6193628a9a105531d11b40a6d731a33", + "sha256:3e524c7874ac72884d28e16dd5b8d839fd09e0fe76b020d3fbca23212a7b8c52", + "sha256:3e93b2cd69a9830be33e03945cd7cda940a0a8bfcfbff41d6144f0cb0d3d8bd9", + "sha256:3edae8c5ddfdb6985d49ae9d150516e5076888879022f91a26c2de9276ce0bdb", + "sha256:3f0e9ac28fc067d4d34b88ae43c48e9489455c97fee9633d851f7eeed5a05d35", + "sha256:42e75466f83cd43f6026c81eab74246efb2bdadafb307b85700632d06c68f299", + "sha256:44b32a7c4f0da3d28af31c259e38ddcff096f855e205ed0671d02fcf44f1ea1c", + "sha256:457866b85daf5034296666168b84a69e0b2e89dc4f1af102b46f6448a60b9063", + "sha256:45bc6bccf78b20fd834237d18db64965d7ee68ba7f60440a26c7ab71e7b8d51a", + "sha256:46d80bc76b51a6c24f9944368c28d38b8bcbcea1da4f2f8d3ebc31a67e8c6ec6", + "sha256:4793ef7f78268b124b73fa933440f01d258bbae01de9fa53e9080c9ab0425a12", + "sha256:492e5e428cbe126221611f47e068f01660352feec4ad18bc0f5ea9b2ae88fb14", + "sha256:4b26b03d9d2658ee2fa234f8f4f19f38a09773fe5261028025032e26d4d35af0", + "sha256:4c0d2cb595a420b34d5086db0add011e26e2c09d6a024afbac4228bf8f863a30", + "sha256:4cfaf02209061880210819934de2f4f6aa83dc04dafe6770276acc240a56da31", + "sha256:501909f2e4a1e2dee528ef766fe3c469060ebc17e54a8383d404ba07a81a6f02", + "sha256:50906f5aea24b5a865cbd0a589698288631d9f3a54c3a937c83aefa95a0d14af", + "sha256:54ac2158a6f96cfbabff0b2eedaf94b90c5ec7ca8317fcadc61e1c2b2e0ff6ef", + "sha256:56c6952a9b15047466d0c2347c446a761d4527f89976156341e68f0ce5cc08b0", + "sha256:56cd8b3f77d7b6812f533b662186a1f28316931166ddc00fb893b1b0db7e9888", + "sha256:57492a550a1d88d29d003247e5f78dd8cf04a701fac0e4c8db8745a6d2504e0a", + "sha256:5943980471829f6de242a20b109de3111ba6b77e3af0ffc587028ac854b05e6c", + "sha256:5c6ee90dee3e85e055ddfd502d611643d9b0fd94c818220bda84ec3dacd9b27b", + "sha256:5c90e7fa02e8f5de0d10c17595c568ada48c5302e749462c0ea1a4c362111a86", + "sha256:5ce8943f79c2210f7abcc28e86367b03b28d95027fd01c46d2472373ae70c86f", + "sha256:617f59cde379b4f648a09797b7f683d04b90a46344cddab85639da5aff0f5531", + "sha256:6307a0da524939decb8ca4a3933b8ab62525794411d6984fca6726e732804af6", + "sha256:684fd492fff4fead00587544e059be2bbcb6f93454f21fa2a91b66fc7508be82", + "sha256:6b5b393eda5ea42cca1c1a6665f2a4882b4fd5d1777e41ce0545a107fb008c9d", + "sha256:6b723eb406dec5bc9ec516c73ab9c3239a3284e017f7eb89ee2b3258bd504fb7", + "sha256:6b9bf3135b4ad5981df9a73d71a35272d650a2985ae9c2746357b24d59de2448", + "sha256:6beb738155fe8ab8091afdfa5a3226b21c2b1593f1e50ebb90eb25b44dbc0391", + "sha256:6c0dbbcc19735fe5f8b0a54c07659d154a9e69f47e15d0a6ab7299215daf62cb", + "sha256:6cdc537c8633d7fd92a82e2e0d2ab74320a3f63d5e59fb9cf08711e08fe151c4", + "sha256:6eae33003518fd4cb4f83a218d5371469dd3001aa3b87128c005b07762f7fe5e", + "sha256:740d0a99cf9de0b17a3943388e9294a59becf75e7c43421f387bd3c7a9901f7c", + "sha256:75c38c50ab9aca840225d9a9a3810bf11d04bd5c1f186cabbb8aee56db3e9b15", + "sha256:761fdae6728ceb99ab182fad2f0cc1e262f610834dc891aea1d1a2a2e634776f", + "sha256:7664419f27db41d4f1c43a78dccda7dd6e8ef2428df3ee01d0c2a07a6b071297", + "sha256:76d3af9732d2dab69f28179b40ba2d87e2f1d5824b4a694780aa787d685e8f36", + "sha256:78326f4cb4427a56ba4996c0762b63be45f06b85f086526420d2b3a66e40f84d", + "sha256:7868b85224291c6cb6759f9b5adb9745f486d226f62b16a614dd5a2a5ab2b35b", + "sha256:815d26356930846a40c7bc1366e7b1b0320ab8a063e66c11298a208bed0fd237", + "sha256:8171b44a054e5c67fd748ada04187f1250bf35b95f85e52ab64bcf3331a923bb", + "sha256:821b2755db9194409254012f429c56643416fb96ef9be090be82ec8826b7f477", + "sha256:837c6b305e26fe0f75b15c92cf3b2ba29e0ae19dc40b1c557b026cb426347d0c", + "sha256:839dde845559254f34885267c6878f60d61d5205180226d976fe488d45fa128e", + "sha256:84a6ecc0c940169190d2c23bd969debd48c94dbc855acd60188a68d71d421608", + "sha256:8601470267d938bcb7f3ab1a336100af51a4fd5b6ed030ef52461bb3ef5e7e07", + "sha256:88b5268892fde430d5531f95bc560b6efbbd67c929662c586afd729a96e7461c", + "sha256:8aa5dda18d39b6143eb24809d158f9252c88f402749b6f1b62a506cc7d96cc35", + "sha256:926bdd3e3b5998ddf70cc64bc8cf57209571f9044542913afb673799fec77dd0", + "sha256:96beca19ec79de272e8668585380ff9092c47077c1d7a1e098e00bbd921f4785", + "sha256:9a0460d43603d1fd9ef59c30278531e15d78581721ddb538fa560aa7817ea4ad", + "sha256:a03d57b86d2a51d0a66c92177e2be154ad015f357791d306e714569999cdb4cc", + "sha256:a36b70596407634ca82d4b989a3729074a008537a0522e4c8046a67c729103e9", + "sha256:a3a52a3ba86436ab3aef510fbe21512abc2ddd1993005dfe50514bd2284ef025", + "sha256:a3dbc5ed9514908d5046107d7b1346bde71eea61de6e0e4919c19354f97e769f", + "sha256:a431156bb41865fc14cd5d79bb9d7bbed83110b0159e34e62ae30951f96c0009", + "sha256:a575404ebc9cf2e91edd32eaf570ec1430eb900d4f56724ba7dd4bc1fc9c176d", + "sha256:a5cf77eb04f20b720be95265a3e00eb2a14814074255cc27069c551b2db53118", + "sha256:a8763f20692da7df39b0afdd1ba3042b004c50a45994f76c2d9a25641f7673db", + "sha256:ab4b2fda7c2b542f7f9d886cc6a838c5079d2b76f72e6081411faba11adde2c9", + "sha256:addeda51556dac7c1a2f14cda62db8b621cd12afba3091d03a96c72932387eab", + "sha256:b242c27c8f836305a4a72df9cdd564386ac57b807bd252a063223331c9316b37", + "sha256:b4f062343e7ad3fa94f2c66e5ae667dee47ee74dd41a9057c4fbe163236a123d", + "sha256:b5b8b0753718d258fd454283fbd57e14545d3b40583fa672e27cb4f987626bcc", + "sha256:be3e47e2d91aa3942ff9bf4077a505226005abfc39b6f7554a91c1b9393986b9", + "sha256:befc2d6a953e563f8a7bfd87a42c22ebf8a3e980dcb7b6a4d17b70b0e914e8a3", + "sha256:bf35d0568abda97233239ce32896d3ad53fccc537832c104e30c94aa5fb93569", + "sha256:c933c6678c6f116ff8af47a4c6db0868b8ace74af0343016c0ef00f00272ea69", + "sha256:c9d1aca01f49170fdcf5c92761b1fafe97f554b721ca4570c5949fff778f0d4b", + "sha256:cdeaa99ce822dca76cfb1b993e9120c5ea212f2eb66d48950ad63c349668a018", + "sha256:ce4d4f52e2a4324396caddbd45a97d8d7be5f42edd25d2355282a9c34f9b2f7f", + "sha256:d1028417bb44037eb3069c1009bd7b7277212876cda22fbe565b0bca9fab6d2c", + "sha256:d151e148117294133bf8af7eeace085e7e87432db15ab6adf640330298a47f6f", + "sha256:d7841166b7fa64c9c56404617ae4341448847482d45933b13135d26c130519e5", + "sha256:d7fca4eb6df565e2a928f1c7dad92d27db8f9df0f449e76423ed5d7e713ed445", + "sha256:d95a354e02393eada6d7351184671aced9d4cce109dabf927cb7aa99624352a1", + "sha256:d9edf30457d74eebfd76b045535e36f1cd89062566a128a0db2145ca042d787e", + "sha256:dbc2673f9223d420c91145599b3ba45a8a50c207d1976908e5fb5ddb0c9b9429", + "sha256:e01b3c878c8641913e688edd1b3f08658c6783d29cf6b826bd3c0d1ae7a1ffaa", + "sha256:e21c1429e205828ea886a2293a4a2c8e01f4c25d9893ca330e97a6cf73f52e7b", + "sha256:e43d4a1f673e8a1cbd8533e809e02b4bf9d4f2280269bb640436556312121250", + "sha256:e6d198bad4e49dd6732fbd636e2fc5c082f45c8cad0b4acb756b00c82c76072e", + "sha256:e6ea1cda8d8c688278430e4268a42f5e5da3bdd74578dfadc0820c3f1766ce83", + "sha256:ea394a937f17a54c51239348bdbe2e3518124c8d4a8951ba04a311d3095bd18f", + "sha256:eac2f5dbafd585dfe31f86a23ebf0d3ba480a9d49ebc87947267b5608d4ea0cd", + "sha256:eb61be926bb81567c1f48bdc8aa22b9855048dc2efd53871f9f7e6e9a5632346", + "sha256:eba5d173f7d5708b22a93815017a4611873ed54db9f268077c0dd1ed99cfc858", + "sha256:ec450527cbf485e13c8d3602a54f428ab0432fdade0ede75efd74b735421c871", + "sha256:eef6a03b0b6d08d0835ccfa8ec8d1bc70525e3801387567137b50c557695e6da", + "sha256:ef0d8c843e2827d6c120ab4687e9423fb1d893db1df27b7c1506615bcb9734a0", + "sha256:ef6b65b03247c54692ad4fd9ee97cb772781927db72e3cb05e70b3db6d1ff14f", + "sha256:f3d6ed6a98cfd19155996605474982cc470d7601746a6439078f1a5a3fa8b050", + "sha256:fce4b85234a0cbad67bf8e6e1201ee815d172c9aebad75f25645bc4d834f8e31", + "sha256:fda1d96e542c37b6c804547dbf489c129fe7c97183a76a5ec275909ba1a063df", + "sha256:fdcd198979b4ecffcc1beba366a7fbcf4eb41243691a82fe52ceb0b902f09c12", + "sha256:fe5ad0664ec772b02c45859041aa17655709cced7a31005817fbbbd988c25567" ], "markers": "python_version >= '3.11'", - "version": "==2026.6.3" + "version": "==2026.9.1" }, "s3transfer": { "hashes": [ @@ -2735,14 +2795,6 @@ ], "version": "==0.9.0" }, - "tzdata": { - "hashes": [ - "sha256:c2169a8b0a7a5e9674da5a135ccdfb2b3e671b333ed9fed17b41f73c34476e81", - "sha256:f1b8bd365d8d210c55353f4d7f8d6d8561c0ba50d704b700d195a9424bba0d79" - ], - "markers": "python_version >= '2'", - "version": "==2026.4" - }, "urllib3": { "hashes": [ "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", @@ -2753,11 +2805,11 @@ }, "virtualenv": { "hashes": [ - "sha256:2d1a394ef089220b4606408b184433e49417a6e5590a09c7b8a67fb1e013af56", - "sha256:d7f167214b3c4f69df5386677dae5091dbc9c400fc46080187ae28064c9d453d" + "sha256:3769219a308c5d2f093e7729621ad12a6346b5767a7ec4338414e2a0fb0c526b", + "sha256:5f427d56f39eb7e7447d641dd4b7ab1e9c92793f498f35f26da2e4972c5546ae" ], "markers": "python_version >= '3.9'", - "version": "==21.14.4" + "version": "==21.14.7" }, "watchdog": { "hashes": [ diff --git a/setup.cfg b/setup.cfg index 88203ce89..3e9085626 100644 --- a/setup.cfg +++ b/setup.cfg @@ -73,7 +73,7 @@ tests_require = func-timeout~=4.3 pytest-cov~=4.1.0 pytest-html~=4.1.0 - pandas>=1.5,<3.0 + pandas>=1.5,<4.0 [options.extras_require] dev = @@ -90,7 +90,7 @@ dev = black pre-commit filelock>=3.20.3 - pandas>=1.5,<3.0 + pandas>=1.5,<4.0 tests = pytest~=9.0.3 @@ -103,15 +103,14 @@ tests = func-timeout~=4.3 pytest-cov~=4.1.0 pytest-html~=4.1.0 - pandas>=1.5,<3.0 + pandas>=1.5,<4.0 jsonschema>=4.23.0 pandas = - pandas>=1.5,<3.0 + pandas>=1.5,<4.0 curator = %(pandas)s - pandarallel>=1.6.4 inflection>=0.5.1 networkx>=2.2.8 dataclasses-json>=0.6.1 diff --git a/synapseclient/extensions/curator/CLAUDE.md b/synapseclient/extensions/curator/CLAUDE.md index c7402f2ae..f37a97c5d 100644 --- a/synapseclient/extensions/curator/CLAUDE.md +++ b/synapseclient/extensions/curator/CLAUDE.md @@ -1,4 +1,4 @@ - + ## Project @@ -6,7 +6,7 @@ Schema curation tools for data modeling — JSON Schema generation from CSV/JSON ## Stack -Optional dependencies (gated by `[curator]` extras): pandas, pandarallel, networkx, rdflib, inflection, dataclasses-json. +Optional dependencies (gated by `[curator]` extras): pandas, networkx, rdflib, inflection, dataclasses-json. ## Conventions diff --git a/synapseclient/extensions/curator/schema_generation.py b/synapseclient/extensions/curator/schema_generation.py index 720141aad..b92c28be0 100644 --- a/synapseclient/extensions/curator/schema_generation.py +++ b/synapseclient/extensions/curator/schema_generation.py @@ -43,7 +43,6 @@ def check_curator_imports() -> None: try: import inflection # noqa: F401 import networkx # noqa: F401 - import pandarallel # noqa: F401 import pandas # noqa: F401 import rdflib # noqa: F401 except ImportError as exception: @@ -334,27 +333,18 @@ def find_and_convert_ints( """ - from pandarallel import pandarallel from pandas import DataFrame from pandas.api.types import is_integer - large_manifest_cutoff_size = 1000 # Find integers stored as strings and replace with entries of type np.int64 - if ( - dataframe.size < large_manifest_cutoff_size - ): # If small manifest, iterate as normal for improved performance - ints = dataframe.map( # type: ignore - lambda cell: convert_ints(cell), na_action="ignore" - ).fillna(False) - - else: # parallelize iterations for large manifests - pandarallel.initialize(verbose=1) - ints = dataframe.parallel_applymap( # type: ignore - lambda cell: convert_ints(cell), na_action="ignore" - ).fillna(False) + # Series.map is used per column because DataFrame.map needs pandas 2.1 or + # later, and DataFrame.applymap was removed in pandas 3 + ints = dataframe.apply( + lambda col: col.map(lambda cell: convert_ints(cell), na_action="ignore") + ).fillna(False) # Identify cells converted to integers - is_int = ints.map(is_integer) # type: ignore + is_int = ints.apply(lambda col: col.map(is_integer)) assert isinstance(ints, DataFrame) assert isinstance(is_int, DataFrame) @@ -396,7 +386,7 @@ def convert_floats(dataframe: DATA_FRAME_TYPE) -> DATA_FRAME_TYPE: float_df[col] = to_numeric(float_df[col], errors="coerce").astype("object") # replace values that couldn't be converted to float with the original str values - float_df[col].fillna(dataframe[col][float_df[col].isna()], inplace=True) + float_df[col] = float_df[col].fillna(dataframe[col][float_df[col].isna()]) return float_df @@ -459,7 +449,6 @@ def load_df( """ Universal function to load CSVs and return DataFrames Parses string entries to convert as appropriate to type int, float, and pandas timestamp - Pandarallel is used for type inference for large manifests to improve performance Args: file_path (str): path of csv to open diff --git a/synapseclient/models/mixins/table_components.py b/synapseclient/models/mixins/table_components.py index e23af514c..6735af713 100644 --- a/synapseclient/models/mixins/table_components.py +++ b/synapseclient/models/mixins/table_components.py @@ -230,7 +230,9 @@ def _reformat_special_values(obj): return x for col in df.columns: - df[col] = df[col].apply(_serialize_json_value) + # cast to object first so missing values do not turn an Int64 column into + # Float64 (pandas 3), which would write 1 as 1.0 + df[col] = df[col].astype(object).map(_serialize_json_value) # restore the original values of the column especially for the int64 and float64 columns since apply function changes the dtype df[col] = df[col].convert_dtypes() df[col] = df[col].replace({pd.NA: None}).astype(object) @@ -539,23 +541,30 @@ def _rowset_to_pandas_df( import pandas as pd - def construct_rownames(query_result_bundle, offset=0): + def construct_rownames(rowset, offset=0): try: return ( - row_labels_from_rows( - query_result_bundle.query_result.query_results.rows - ) + row_labels_from_rows(rowset.rows) if row_id_and_version_in_index else None ) except KeyError: # if we don't have row id and version, just number the rows # python3 cast range to list for safety - return list(range(offset, offset + len(rowset["rows"]))) + return list(range(offset, offset + len(rowset.rows))) + + def append_page(column_name, data, index=None, verify_integrity=False): + # add the rows from the next page to the end of the column's series + series[column_name] = pd.concat( + [series[column_name], pd.Series(name=column_name, data=data, index=index)], + verify_integrity=verify_integrity, + ) # first page of rows offset = 0 - rownames = construct_rownames(query_result_bundle, offset) + rownames = construct_rownames( + query_result_bundle.query_result.query_results, offset + ) query_result = query_result_bundle.query_result rowset = query_result.query_results @@ -608,38 +617,25 @@ def construct_rownames(query_result_bundle, offset=0): offset += len(rowset.rows) if not row_id_and_version_in_index: - # TODO: Look into why this isn't being assigned - series["ROW_ID"].append( - pd.Series(name="ROW_ID", data=[row.id for row in rowset.rows]) - ) - series["ROW_VERSION"].append( - pd.Series( - name="ROW_VERSION", - data=[row.version_number for row in rowset.rows], - ) - ) + append_page("ROW_ID", [row.row_id for row in rowset.rows]) + append_page("ROW_VERSION", [row.version_number for row in rowset.rows]) if append_etag: - series["ROW_ETAG"] = pd.Series( - name="ROW_ETAG", - data=[row.etag for row in rowset.rows], - ) + append_page("ROW_ETAG", [row.etag for row in rowset.rows]) for i, header in enumerate(rowset.headers): - column_name = header.name - series[column_name] = pd.concat( - [ - series[column_name], - pd.Series( - name=column_name, - data=[row.values[i] for row in rowset.rows], - index=rownames, - ), - ], + append_page( + header.name, + [row.values[i] for row in rowset.rows], + index=rownames, # can't verify integrity when indices are just numbers instead of 'rowid_rowversion' verify_integrity=row_id_and_version_in_index, ) - return pd.DataFrame(data=series) + df = pd.DataFrame(data=series) + if not row_id_and_version_in_index: + # each page numbers its rows from 0, so renumber the rows across all pages + df = df.reset_index(drop=True) + return df @dataclass diff --git a/synapseclient/models/services/manifest.py b/synapseclient/models/services/manifest.py index e0b9dbcc6..9f5ddd408 100644 --- a/synapseclient/models/services/manifest.py +++ b/synapseclient/models/services/manifest.py @@ -535,6 +535,8 @@ def _apply_synapse_store_defaults(df: "DataFrame") -> None: """ if "synapseStore" not in df.columns: df["synapseStore"] = None + # A blank column is read as float64, which cannot hold bool values + df["synapseStore"] = df["synapseStore"].astype(object) df.loc[df["path"].apply(is_url), "synapseStore"] = False df.loc[df["synapseStore"].isnull(), "synapseStore"] = True df["synapseStore"] = df["synapseStore"].astype(bool) @@ -650,6 +652,10 @@ async def _sort_and_fix_provenance(syn: Synapse, df: DataFrame) -> DataFrame: path, a URL, nor a valid Synapse ID. """ df = df.set_index("path").copy() + # Lists are written into these cells, which a str dtype column cannot hold + for col in ("used", "executed"): + if col in df.columns: + df[col] = df[col].astype(object) results = await asyncio.gather( *[_resolve_row(str(path), row, df, syn) for path, row in df.iterrows()] diff --git a/synapseclient/table.py b/synapseclient/table.py index f9bc30d7f..8b2ca0234 100644 --- a/synapseclient/table.py +++ b/synapseclient/table.py @@ -430,8 +430,11 @@ def _convert_df_date_cols_to_datetime( raise ValueError( "Cannot convert epoch time to integer. Please make sure that the date columns that you specified contain valid epoch time value" ) - df[date_columns] = df[date_columns].apply( - lambda x: pd.to_datetime(x, unit="ms", utc=True) + # pandas 3 returns datetime64[ms, UTC] for unit="ms", so force ns resolution + df[date_columns] = ( + df[date_columns] + .apply(lambda x: pd.to_datetime(x, unit="ms", utc=True)) + .astype("datetime64[ns, UTC]") ) return df @@ -2167,22 +2170,33 @@ def construct_rownames(rowset, offset=0): offset += len(self.rowset["rows"]) if not rowIdAndVersionInIndex: - # TODO: Look into why this isn't being assigned - series["ROW_ID"].append( - pd.Series( - name="ROW_ID", data=[row["id"] for row in self.rowset["rows"]] - ) + series["ROW_ID"] = pd.concat( + [ + series["ROW_ID"], + pd.Series( + name="ROW_ID", + data=[row["rowId"] for row in self.rowset["rows"]], + ), + ] ) - series["ROW_VERSION"].append( - pd.Series( - name="ROW_VERSION", - data=[row["version"] for row in self.rowset["rows"]], - ) + series["ROW_VERSION"] = pd.concat( + [ + series["ROW_VERSION"], + pd.Series( + name="ROW_VERSION", + data=[row["versionNumber"] for row in self.rowset["rows"]], + ), + ] ) if append_etag: - series["ROW_ETAG"] = pd.Series( - name="ROW_ETAG", - data=[row.get("etag") for row in self.rowset["rows"]], + series["ROW_ETAG"] = pd.concat( + [ + series["ROW_ETAG"], + pd.Series( + name="ROW_ETAG", + data=[row.get("etag") for row in self.rowset["rows"]], + ), + ] ) for i, header in enumerate(self.rowset["headers"]): @@ -2200,7 +2214,11 @@ def construct_rownames(rowset, offset=0): verify_integrity=rowIdAndVersionInIndex, ) - return pd.DataFrame(data=series) + df = pd.DataFrame(data=series) + if not rowIdAndVersionInIndex: + # each page numbers its rows from 0, so renumber the rows across all pages + df = df.reset_index(drop=True) + return df def asRowSet(self): # Note that as of stack 60, an empty query will omit the headers field diff --git a/synapseutils/describe_functions.py b/synapseutils/describe_functions.py index fe1b7f57b..93a1ff845 100644 --- a/synapseutils/describe_functions.py +++ b/synapseutils/describe_functions.py @@ -71,7 +71,12 @@ def _describe_wrapper(df: DATA_FRAME_TYPE, syn: Synapse) -> dict[str, dict[str, stats[column]["dtype"] = df[column].dtype.name else: stats[column]["mode"] = df[column].mode()[0] - stats[column]["dtype"] = df[column].dtype.name + # pandas 3 reports "str" for text columns; keep "object" + stats[column]["dtype"] = ( + "object" + if pd.api.types.is_string_dtype(df[column].dtype) + else df[column].dtype.name + ) except TypeError: syn.logger.info(f"Invalid column type: {column}") diff --git a/synapseutils/sync.py b/synapseutils/sync.py index 71cdcc9f1..2ea0d02ee 100644 --- a/synapseutils/sync.py +++ b/synapseutils/sync.py @@ -5,6 +5,7 @@ import csv import datetime import io +import math import os import re import sys @@ -982,6 +983,10 @@ def _write_manifest_data(filename: str, keys: List[str], data: List[dict]) -> No def _sortAndFixProvenance(syn, df): df = df.set_index("path") + # Lists are written into these cells, which a str dtype column cannot hold + for col in PROVENANCE_FIELDS: + if col in df.columns: + df[col] = df[col].astype(object) uploadOrder = {} def _checkProvenace(item, path): @@ -1106,6 +1111,8 @@ async def readManifestFile_async(syn: Synapse, manifestFile: str) -> DATA_FRAME_ df = pd.read_csv(manifestFile, sep="\t") if "synapseStore" not in df: df = df.assign(synapseStore=None) + # A blank column is read as float64, which cannot hold bool values + df["synapseStore"] = df["synapseStore"].astype(object) df.loc[df["path"].apply(is_url), "synapseStore"] = ( False # override synapseStore values to False when path is a url ) @@ -1537,8 +1544,8 @@ async def _manifest_upload( item = _SyncUploadItem( file, - row["used"] if "used" in row else [], - row["executed"] if "executed" in row else [], + _missing_to_empty_list(row["used"]) if "used" in row else [], + _missing_to_empty_list(row["executed"]) if "executed" in row else [], activity_name=row["activityName"] if "activityName" in row else None, activity_description=( row["activityDescription"] if "activityDescription" in row else None @@ -1552,6 +1559,20 @@ async def _manifest_upload( return True +def _missing_to_empty_list( + value: Union[Iterable[str], float, None], +) -> Iterable[str]: + """Return an empty list if value is None or NaN, otherwise return value unchanged. + + With pandas 3, iterrows gives a str dtype row when every cell is a string or + missing, and the missing cells are NaN, not None. An empty list keeps the + used and executed values iterable for the upload. + """ + if value is None or (isinstance(value, float) and math.isnan(value)): + return [] + return value + + def _check_file_name(df, syn: Synapse) -> None: compiled = re.compile(r"^[`\w \-\+\.\(\)]{1,256}$") for _, row in df.iterrows(): diff --git a/tests/integration/synapseclient/deprecated/test_tables.py b/tests/integration/synapseclient/deprecated/test_tables.py index 9e81b9a15..d2bfeb665 100644 --- a/tests/integration/synapseclient/deprecated/test_tables.py +++ b/tests/integration/synapseclient/deprecated/test_tables.py @@ -402,11 +402,17 @@ def test_tables_pandas(syn, project, schedule_for_cleanup): # SYNPY-717 # This is a check for windows + # The client returns DATE columns as datetime64[ns, UTC]. pandas 2 and later can + # give other resolutions, so force ns resolution on the expected column if os.name == "nt": - df["datetime64"] = pd.to_datetime(df["datetime64"], utc=True) + df["datetime64"] = pd.to_datetime(df["datetime64"], utc=True).astype( + "datetime64[ns, UTC]" + ) else: df["datetime64"] = df["datetime64"].astype(int) - df["datetime64"] = pd.to_datetime(df["datetime64"], unit="ms", utc=True) + df["datetime64"] = pd.to_datetime(df["datetime64"], unit="ms", utc=True).astype( + "datetime64[ns, UTC]" + ) # df2 == df gives Dataframe of boolean values; first .all() gives a Series object of ANDed booleans of each column; # second .all() gives a bool that is ANDed value of that Series diff --git a/tests/integration/synapseclient/models/async/test_entityview_async.py b/tests/integration/synapseclient/models/async/test_entityview_async.py index cdb3df376..ea0a23661 100644 --- a/tests/integration/synapseclient/models/async/test_entityview_async.py +++ b/tests/integration/synapseclient/models/async/test_entityview_async.py @@ -416,15 +416,19 @@ def csv_wrapper(*args, **kwargs): check_names=True, check_dtype=False, ) + # dtype=object keeps None for missing values, matching the query output, + # on all pandas versions pd.testing.assert_series_equal( query_results["integer_column"], - pd.Series(test_data["integer_column"], name="integer_column"), + pd.Series( + test_data["integer_column"], name="integer_column", dtype=object + ), check_names=True, check_dtype=False, ) pd.testing.assert_series_equal( query_results["float_column"], - pd.Series(test_data["float_column"], name="float_column"), + pd.Series(test_data["float_column"], name="float_column", dtype=object), check_names=True, check_dtype=False, ) diff --git a/tests/integration/synapseclient/models/async/test_table_async.py b/tests/integration/synapseclient/models/async/test_table_async.py index 600a65410..77d5f0633 100644 --- a/tests/integration/synapseclient/models/async/test_table_async.py +++ b/tests/integration/synapseclient/models/async/test_table_async.py @@ -1010,6 +1010,8 @@ async def test_store_rows_from_df_with_datetime_columns( # The DST column expectations are hardcoded to prove each value converts using the # UTC offset in effect on its own date (12:00-08:00 -> 20:00 UTC and # 12:00-07:00 -> 19:00 UTC), independent of the machine running the test + # dtype=object keeps None for missing values, matching the query output, on all + # pandas versions expected_results = pd.DataFrame( { "column_string": ["value1", "value2", "value3"], @@ -1022,7 +1024,8 @@ async def test_store_rows_from_df_with_datetime_columns( utils.to_unix_epoch_time(date) if date else None for date in naive_dates ], - } + }, + dtype=object, ) pd.testing.assert_frame_equal(results, expected_results, check_dtype=False) @@ -1114,6 +1117,8 @@ async def test_store_rows_from_csv_with_date_columns( include_row_id_and_row_version=False, ) + # dtype=object keeps None for missing values, matching the query output, on all + # pandas versions expected_results = pd.DataFrame( { "column_string": ["value1", "value2", "value3"], @@ -1122,7 +1127,8 @@ async def test_store_rows_from_csv_with_date_columns( None, utils.to_unix_epoch_time(datetime(2024, 2, 20)), ], - } + }, + dtype=object, ) pd.testing.assert_frame_equal(results, expected_results, check_dtype=False) @@ -1170,6 +1176,8 @@ async def test_store_rows_from_csv_with_tz_aware_date_columns( include_row_id_and_row_version=False, ) + # dtype=object keeps None for missing values, matching the query output, on all + # pandas versions expected_results = pd.DataFrame( { "column_string": ["value1", "value2", "value3"], @@ -1178,7 +1186,8 @@ async def test_store_rows_from_csv_with_tz_aware_date_columns( None, 1708459200000, ], # date columns are converted to epoch ms - } + }, + dtype=object, ) pd.testing.assert_frame_equal(results, expected_results, check_dtype=False) diff --git a/tests/unit/synapseclient/deprecated/unit_test_tables.py b/tests/unit/synapseclient/deprecated/unit_test_tables.py index 6f3250eda..36b354c7b 100644 --- a/tests/unit/synapseclient/deprecated/unit_test_tables.py +++ b/tests/unit/synapseclient/deprecated/unit_test_tables.py @@ -1524,6 +1524,96 @@ def test_rowset_asDataFrame__with_ROW_ETAG_column(syn: Synapse) -> None: assert expected_indicies == dataframe.index.values.tolist() +def _multi_page_query_results() -> tuple[dict, list[dict]]: + """Return a first page and 2 next pages of a table query, with 5 rows in total.""" + + def make_rowset(start: int, count: int) -> dict: + return { + "concreteType": "org.sagebionetworks.repo.model.table.RowSet", + "etag": "DEFAULT", + "tableId": "syn11363411", + "headers": [ + {"id": "61770", "columnType": "STRING", "name": "annotationColumn1"}, + ], + "rows": [ + { + "values": [f"value{row_id}"], + "etag": f"etag{row_id}", + "rowId": row_id, + "versionNumber": 1, + } + for row_id in range(start, start + count) + ], + } + + query_result = { + "concreteType": "org.sagebionetworks.repo.model.table.QueryResultBundle", + "maxRowsPerPage": 6990, + "selectColumns": [ + {"id": "61770", "columnType": "STRING", "name": "annotationColumn1"}, + ], + "queryCount": 5, + "queryResult": { + "concreteType": "org.sagebionetworks.repo.model.table.QueryResult", + "nextPageToken": "token1", + "queryResults": make_rowset(0, 2), + }, + } + next_pages = [ + { + "concreteType": "org.sagebionetworks.repo.model.table.QueryResult", + "nextPageToken": "token2", + "queryResults": make_rowset(2, 2), + }, + { + "concreteType": "org.sagebionetworks.repo.model.table.QueryResult", + "queryResults": make_rowset(4, 1), + }, + ] + return query_result, next_pages + + +def test_rowset_asDataFrame__multiple_pages_row_id_and_version_not_in_index( + syn: Synapse, +) -> None: + # GIVEN a query result with 3 pages + query_result, next_pages = _multi_page_query_results() + + with ( + patch.object(syn, "_queryTable", return_value=query_result), + patch.object(syn, "_queryTableNext", side_effect=next_pages), + ): + # WHEN I convert the result with row ID and version as columns + table = syn.tableQuery("select something from syn123", resultsAs="rowset") + dataframe = table.asDataFrame(rowIdAndVersionInIndex=False) + + # THEN the DataFrame has one row for each row in all pages + assert 5 == len(dataframe) + assert [0, 1, 2, 3, 4] == list(dataframe["ROW_ID"]) + assert [1, 1, 1, 1, 1] == list(dataframe["ROW_VERSION"]) + assert [f"etag{i}" for i in range(5)] == list(dataframe["ROW_ETAG"]) + assert [f"value{i}" for i in range(5)] == list(dataframe["annotationColumn1"]) + + +def test_rowset_asDataFrame__multiple_pages_row_id_and_version_not_in_index_has_unique_index( + syn: Synapse, +) -> None: + # GIVEN a query result with 3 pages + query_result, next_pages = _multi_page_query_results() + + with ( + patch.object(syn, "_queryTable", return_value=query_result), + patch.object(syn, "_queryTableNext", side_effect=next_pages), + ): + # WHEN I convert the result with row ID and version as columns + table = syn.tableQuery("select something from syn123", resultsAs="rowset") + dataframe = table.asDataFrame(rowIdAndVersionInIndex=False) + + # THEN the index is unique and numbers the rows across all pages + assert dataframe.index.is_unique + assert [0, 1, 2, 3, 4] == dataframe.index.tolist() + + def test_RowSetTable_len() -> None: schema = Schema( parentId="syn123", id="syn456", columns=[Column(name="column_name", id="123")] diff --git a/tests/unit/synapseclient/extensions/unit_test_curator.py b/tests/unit/synapseclient/extensions/unit_test_curator.py index fbce627f9..8fc4d1e6d 100644 --- a/tests/unit/synapseclient/extensions/unit_test_curator.py +++ b/tests/unit/synapseclient/extensions/unit_test_curator.py @@ -16,6 +16,7 @@ from typing import Any, Callable from unittest.mock import Mock, mock_open, patch +import numpy as np import pandas as pd import pytest @@ -45,6 +46,8 @@ project_id_from_entity_id, ) from synapseclient.extensions.curator.schema_generation import ( + convert_floats, + find_and_convert_ints, generate_jsonld, generate_jsonschema, ) @@ -1967,6 +1970,215 @@ def test_error_names_every_duplicate_once(self): validate_column_order_list(["patientId", "patientId", "patientId"]) +class TestFindAndConvertInts: + """Test cases for find_and_convert_ints in curator.schema_generation.""" + + def test_converts_digit_strings_to_ints(self) -> None: + """Strings of digits become numpy int64 values and are marked as ints.""" + # GIVEN a dataframe where every cell is a string of digits + df = pd.DataFrame({"a": ["1", "22"], "b": ["0", "333"]}) + + # WHEN the integers are found and converted + ints, is_int = find_and_convert_ints(df) + + # THEN every cell is converted to an int64 and marked as an int + assert ints.to_dict("list") == {"a": [1, 22], "b": [0, 333]} + assert all(isinstance(value, np.int64) for value in ints.to_numpy().flatten()) + assert is_int.to_numpy().all() + + @pytest.mark.parametrize( + "value", + ["abc", "1.5", "-1", "1e3", " 1", "", 5, 1.0], + ids=[ + "text", + "float string", + "negative string", + "scientific notation", + "leading space", + "empty string", + "int", + "float", + ], + ) + def test_does_not_convert_other_values(self, value: any) -> None: + """Values that are not strings of digits become False.""" + # GIVEN a dataframe with a value that is not a string of digits + df = pd.DataFrame({"a": [value]}, dtype=object) + + # WHEN the integers are found and converted + ints, is_int = find_and_convert_ints(df) + + # THEN the value is replaced with False and is not marked as an int + # (pandas can give a numpy bool when the whole column is False) + assert isinstance(ints.loc[0, "a"], (bool, np.bool_)) + assert not ints.loc[0, "a"] + assert not is_int.loc[0, "a"] + + def test_missing_values_become_false(self) -> None: + """Missing values become False and are not marked as ints.""" + # GIVEN a dataframe with missing values + df = pd.DataFrame({"a": ["x", None, np.nan]}, dtype=object) + + # WHEN the integers are found and converted + ints, is_int = find_and_convert_ints(df) + + # THEN the missing values are replaced with False + assert ints["a"].tolist() == [False, False, False] + assert is_int["a"].tolist() == [False, False, False] + + def test_mixed_columns(self) -> None: + """Each cell is checked on its own, so a column can be partly converted.""" + # GIVEN a dataframe that mixes digit strings, text, and floats + df = pd.DataFrame( + { + "id": ["1", "2", "3"], + "name": ["x", "10", "y"], + "score": ["1.5", "2", "abc"], + } + ) + + # WHEN the integers are found and converted + ints, is_int = find_and_convert_ints(df) + + # THEN only the digit strings are converted and marked as ints + assert ints.to_dict("list") == { + "id": [1, 2, 3], + "name": [False, 10, False], + "score": [False, 2, False], + } + assert is_int.to_dict("list") == { + "id": [True, True, True], + "name": [False, True, False], + "score": [False, True, False], + } + + def test_returns_dataframes_with_same_shape_and_labels(self) -> None: + """Both results keep the index and columns of the input dataframe.""" + # GIVEN a dataframe with a custom index + df = pd.DataFrame({"a": ["1", "x"], "b": ["y", "2"]}, index=["r1", "r2"]) + + # WHEN the integers are found and converted + ints, is_int = find_and_convert_ints(df) + + # THEN both results are dataframes with the same labels as the input + for result in (ints, is_int): + assert isinstance(result, pd.DataFrame) + assert result.index.tolist() == ["r1", "r2"] + assert result.columns.tolist() == ["a", "b"] + + def test_empty_dataframe(self) -> None: + """An empty dataframe gives empty results.""" + # GIVEN an empty dataframe + df = pd.DataFrame({"a": []}, dtype=object) + + # WHEN the integers are found and converted + ints, is_int = find_and_convert_ints(df) + + # THEN both results are empty + assert ints.empty + assert is_int.empty + + +class TestConvertFloats: + """Test cases for convert_floats in curator.schema_generation.""" + + @pytest.mark.parametrize( + "value, expected", + [ + ("1.5", 1.5), + ("-0.5", -0.5), + ("1e3", 1000.0), + (" 3", 3.0), + ], + ids=["float", "negative", "scientific notation", "leading space"], + ) + def test_converts_numeric_strings_to_floats( + self, value: str, expected: float + ) -> None: + """Strings that represent numbers become floats.""" + # GIVEN a dataframe with a numeric string and a text value + df = pd.DataFrame({"a": [value, "abc"]}, dtype=object) + + # WHEN the floats are converted + float_df = convert_floats(df) + + # THEN the numeric string is converted to a float + assert isinstance(float_df.loc[0, "a"], float) + assert float_df.loc[0, "a"] == expected + + @pytest.mark.parametrize( + "value", + ["abc", "", "nan"], + ids=["text", "empty string", "nan string"], + ) + def test_keeps_non_numeric_strings(self, value: str) -> None: + """Strings that are not numbers keep their original value.""" + # GIVEN a dataframe with a numeric string and a non-numeric string + df = pd.DataFrame({"a": ["1.5", value]}, dtype=object) + + # WHEN the floats are converted + float_df = convert_floats(df) + + # THEN the non-numeric string is not changed + assert float_df.loc[1, "a"] == value + assert isinstance(float_df.loc[1, "a"], str) + + def test_missing_values_stay_missing(self) -> None: + """Missing values are not converted.""" + # GIVEN a dataframe with a missing value + df = pd.DataFrame({"a": ["1.5", None]}, dtype=object) + + # WHEN the floats are converted + float_df = convert_floats(df) + + # THEN the missing value is still missing + # (pandas 2 gives NaN and pandas 3 gives None) + assert float_df.loc[0, "a"] == 1.5 + assert pd.isna(float_df.loc[1, "a"]) + + def test_mixed_columns(self) -> None: + """Each cell is checked on its own, so a column can be partly converted.""" + # GIVEN a dataframe that mixes numeric strings and text + df = pd.DataFrame( + {"a": ["1", "x"], "b": ["y", "2.5"]}, + index=["r1", "r2"], + ) + + # WHEN the floats are converted + float_df = convert_floats(df) + + # THEN only the numeric strings are converted + assert float_df.to_dict("list") == {"a": [1.0, "x"], "b": ["y", 2.5]} + # AND the columns are object dtype, with the same labels as the input + assert all(dtype == object for dtype in float_df.dtypes) + assert float_df.index.tolist() == ["r1", "r2"] + assert float_df.columns.tolist() == ["a", "b"] + + def test_does_not_change_input(self) -> None: + """The input dataframe is not changed.""" + # GIVEN a dataframe with numeric strings + df = pd.DataFrame({"a": ["1.5", "x"]}) + original = df.copy() + + # WHEN the floats are converted + convert_floats(df) + + # THEN the input dataframe is not changed + pd.testing.assert_frame_equal(df, original) + + def test_empty_dataframe(self) -> None: + """An empty dataframe gives an empty result.""" + # GIVEN an empty dataframe + df = pd.DataFrame({"a": []}, dtype=object) + + # WHEN the floats are converted + float_df = convert_floats(df) + + # THEN the result is empty + assert float_df.empty + assert float_df.columns.tolist() == ["a"] + + class TestResolveColumnOrderList: """Test cases for resolve_column_order_list in curator.utils.""" diff --git a/tests/unit/synapseclient/mixins/unit_test_table_components.py b/tests/unit/synapseclient/mixins/unit_test_table_components.py index a14a18bb3..714c42bb2 100644 --- a/tests/unit/synapseclient/mixins/unit_test_table_components.py +++ b/tests/unit/synapseclient/mixins/unit_test_table_components.py @@ -3,7 +3,7 @@ import tempfile from collections import OrderedDict from dataclasses import dataclass, field -from datetime import date, datetime +from datetime import date, datetime, timedelta from io import BytesIO from typing import Any, Dict, List, Optional from unittest.mock import AsyncMock, MagicMock, patch @@ -61,6 +61,7 @@ _query_table_csv, _query_table_next_page, _query_table_row_set, + _rowset_to_pandas_df, _upsert_rows_async, _validate_primary_keys, convert_dtypes_to_json_serializable, @@ -4931,6 +4932,129 @@ async def test_query_table_next_page_basic_functionality( assert result.select_columns[0].id == "12345" +class TestRowsetToPandasDf: + """Test suite for the _rowset_to_pandas_df function with more than one page.""" + + @pytest.fixture(autouse=True, scope="function") + def init_syn(self, syn: Synapse) -> None: + self.syn = syn + + def _make_bundle( + self, start: int, count: int, next_page_token: Optional[QueryNextPageToken] + ) -> QueryResultBundle: + """Make a QueryResultBundle with count rows, starting at row ID start.""" + rows = [ + Row( + row_id=row_id, + version_number=1, + etag=f"etag{row_id}", + values=[f"value{row_id}", str(row_id * 10)], + ) + for row_id in range(start, start + count) + ] + rowset = RowSet( + table_id="syn123", + headers=[ + SelectColumn(name="col1", column_type=ColumnType.STRING), + SelectColumn(name="col2", column_type=ColumnType.INTEGER), + ], + rows=rows, + ) + return QueryResultBundle( + query_result=QueryResult( + query_results=rowset, next_page_token=next_page_token + ) + ) + + def test_multiple_pages_row_id_and_version_not_in_index(self) -> None: + # GIVEN a query result with 3 pages + first_page = self._make_bundle(0, 2, QueryNextPageToken(token="token1")) + next_pages = [ + self._make_bundle(2, 2, QueryNextPageToken(token="token2")), + self._make_bundle(4, 1, None), + ] + + with patch( + "synapseclient.models.mixins.table_components._query_table_next_page", + side_effect=next_pages, + ) as mock_next_page: + # WHEN I convert the result with row ID and version as columns + df = _rowset_to_pandas_df( + query_result_bundle=first_page, + synapse_client=self.syn, + row_id_and_version_in_index=False, + ) + + # THEN all pages are fetched + assert mock_next_page.call_count == 2 + + # AND the DataFrame has one row for each row in all pages + assert len(df) == 5 + assert list(df["ROW_ID"]) == [0, 1, 2, 3, 4] + assert list(df["ROW_VERSION"]) == [1, 1, 1, 1, 1] + assert list(df["ROW_ETAG"]) == [f"etag{i}" for i in range(5)] + assert list(df["col1"]) == [f"value{i}" for i in range(5)] + assert list(df["col2"]) == [str(i * 10) for i in range(5)] + + def test_multiple_pages_row_id_and_version_not_in_index_has_unique_index( + self, + ) -> None: + # GIVEN a query result with 3 pages + first_page = self._make_bundle(0, 2, QueryNextPageToken(token="token1")) + next_pages = [ + self._make_bundle(2, 2, QueryNextPageToken(token="token2")), + self._make_bundle(4, 1, None), + ] + + with patch( + "synapseclient.models.mixins.table_components._query_table_next_page", + side_effect=next_pages, + ): + # WHEN I convert the result with row ID and version as columns + df = _rowset_to_pandas_df( + query_result_bundle=first_page, + synapse_client=self.syn, + row_id_and_version_in_index=False, + ) + + # THEN the index is unique and numbers the rows across all pages + assert df.index.is_unique + assert df.index.tolist() == [0, 1, 2, 3, 4] + + def test_multiple_pages_row_id_and_version_in_index(self) -> None: + # GIVEN a query result with 3 pages + first_page = self._make_bundle(0, 2, QueryNextPageToken(token="token1")) + next_pages = [ + self._make_bundle(2, 2, QueryNextPageToken(token="token2")), + self._make_bundle(4, 1, None), + ] + + with patch( + "synapseclient.models.mixins.table_components._query_table_next_page", + side_effect=next_pages, + ) as mock_next_page: + # WHEN I convert the result with row ID and version in the index + df = _rowset_to_pandas_df( + query_result_bundle=first_page, + synapse_client=self.syn, + row_id_and_version_in_index=True, + ) + + # THEN all pages are fetched + assert mock_next_page.call_count == 2 + + # AND the index has the row ID, version and etag of each row in all pages + assert df.index.tolist() == [f"{i}_1_etag{i}" for i in range(5)] + + # AND the DataFrame has one row for each row in all pages + assert len(df) == 5 + assert "ROW_ID" not in df.columns + assert "ROW_VERSION" not in df.columns + assert "ROW_ETAG" not in df.columns + assert list(df["col1"]) == [f"value{i}" for i in range(5)] + assert list(df["col2"]) == [str(i * 10) for i in range(5)] + + class TestCsvToPandasDf: """Test suite for csv_to_pandas_df function focusing on date and list columns.""" @@ -4972,7 +5096,7 @@ def test_csv_to_pandas_df_with_date_columns(self, csv_with_date_columns): expected_dates = pd.to_datetime( [1609459200000, 1609545600000, 1609632000000], unit="ms", utc=True - ) + ).astype("datetime64[ns, UTC]") # THEN assert the create_date column is equal to the expected dates pd.testing.assert_series_equal( df["created_date"], pd.Series(expected_dates), check_names=False @@ -5049,7 +5173,7 @@ def test_csv_to_pandas_df_with_date_and_list_columns( "name": ["Alice", "Bob", "Charlie"], "created_date": pd.to_datetime( [1609459200000, 1609545600000, 1609632000000], unit="ms", utc=True - ), + ).astype("datetime64[ns, UTC]"), "number": [42, 10, 99], "bool": [True, False, True], "string": ["hello", "world", "test"], @@ -5134,7 +5258,7 @@ def test_csv_to_pandas_df_all_list_types_with_na_in_items_and_date_columns( "string": ["hello", "world", "test"], "created_date": pd.to_datetime( [1609459200000, 1609545600000, 1609632000000], unit="ms", utc=True - ), + ).astype("datetime64[ns, UTC]"), "number_list": [ [1, None, 3], [None, 5], @@ -5207,7 +5331,7 @@ def test_csv_pandas_df_with_row_id_and_version_etag_in_index( "string": ["hello", "world", "test"], "created_date": pd.to_datetime( [1609459200000, 1609545600000, 1609632000000], unit="ms", utc=True - ), + ).astype("datetime64[ns, UTC]"), "number_list": [[1, None, 3], [], [6, None, None, 9]], "bool_list": [[True, None, False], [None, True], [None, None, False]], "string_list": [["tag1", "", "tag3"], ["", "tag2"], ["", "tag4", ""]], @@ -5327,6 +5451,57 @@ def test_convert_na_and_columns_to_object(self): assert list(result["int_col"]) == [1, 2, None, 4] assert list(result["float_col"]) == [1.1, 2.2, None, 4.4] + @pytest.mark.parametrize( + "values, expected_types", + [ + # nullable Int64 with missing values, as made by convert_dtypes() + (pd.array([1, 2, pd.NA, 4], dtype="Int64"), [int, int, type(None), int]), + # a list of ints with None, as given by a user + (pd.Series([1, None, 3]).convert_dtypes(), [int, type(None), int]), + # int64 with no missing values + (pd.Series([1, 2, 3]), [int, int, int]), + # Float64 with missing values stays float + (pd.array([1.5, pd.NA, 3.0], dtype="Float64"), [float, type(None), float]), + ], + ids=["Int64_with_NA", "list_with_None", "int64", "Float64_with_NA"], + ) + def test_number_columns_keep_python_type(self, values, expected_types): + """Test that each value keeps its int or float type. The == check alone + does not catch an int that changed to a float, because 1.0 == 1.""" + # GIVEN a dataframe with a number column + df = pd.DataFrame({"col": values}) + + # WHEN convert_dtypes_to_json_serializable is called + result = convert_dtypes_to_json_serializable(df) + + # THEN each value should have the expected Python type + assert [type(value) for value in result["col"]] == expected_types + + def test_int_column_with_na_is_written_to_csv_as_int(self): + """Test that an int column with missing values is written to CSV without a + decimal part. Synapse rejects "1.0" for an INTEGER column and + "1609502400000.0" for a DATE column.""" + # GIVEN a dataframe with INTEGER and DATE (epoch ms) values and a missing value + df = pd.DataFrame( + { + "int_col": [1, None, 3], + "date_col": [1609502400000, None, 1708459200000], + } + ).convert_dtypes() + + # WHEN convert_dtypes_to_json_serializable is called and the result is + # written to CSV with the same arguments as the upload + result = convert_dtypes_to_json_serializable(df) + csv_text = result.to_csv(index=False, float_format="%.12g") + + # THEN the values should be written as integers + assert csv_text.splitlines() == [ + "int_col,date_col", + "1,1609502400000", + ",", + "3,1708459200000", + ] + def test_row_columns_remain_int(self): """Test that ROW_ID, ROW_VERSION, and ROW_ID.1 columns remain as int while other columns become object""" # GIVEN a dataframe with special columns (ROW_ID, ROW_VERSION, ROW_ID.1) and a regular column @@ -7090,7 +7265,15 @@ def test_uniform_utc_offsets_parsed_as_tz_aware(self): ] } ).convert_dtypes() - pd.testing.assert_frame_equal(result, expected_result) + # pandas 1.5 gives a pytz.FixedOffset timezone and pandas 2+ gives a + # datetime.timezone, so check the offset and compare the values in UTC + assert result["date_col"].dt.tz.utcoffset(None) == timedelta(hours=-8) + pd.testing.assert_frame_equal( + result.assign(date_col=result["date_col"].dt.tz_convert("UTC")), + expected_result.assign( + date_col=expected_result["date_col"].dt.tz_convert("UTC") + ), + ) mock_logger.info.assert_not_called() def test_mixed_utc_offsets_normalized_to_utc(self): diff --git a/tests/unit/synapseclient/models/async/unit_test_manifest_async.py b/tests/unit/synapseclient/models/async/unit_test_manifest_async.py index 63577acfd..e8d848da8 100644 --- a/tests/unit/synapseclient/models/async/unit_test_manifest_async.py +++ b/tests/unit/synapseclient/models/async/unit_test_manifest_async.py @@ -443,6 +443,27 @@ def test_column_is_bool_dtype(self) -> None: _apply_synapse_store_defaults(df) assert df["synapseStore"].dtype == bool + def test_blank_column_read_from_csv(self, tmp_path: Path) -> None: + """A synapseStore column with only blank cells is read as float64. + Local paths default to True and URL paths are set to False.""" + # GIVEN a manifest CSV with a local path and a URL path + manifest = tmp_path / "manifest.csv" + manifest.write_text( + "path,parentId,synapseStore\n/a.txt,syn1,\nhttps://example.com/f.csv,syn1,\n" + ) + + # AND a DataFrame read from the CSV, where the synapseStore column is blank + df = pd.read_csv(manifest) + + # WHEN I apply the synapseStore defaults + _apply_synapse_store_defaults(df) + + # THEN the local path is True and the URL path is False + assert list(df["synapseStore"]) == [True, False] + + # AND the column has the bool dtype + assert df["synapseStore"].dtype == bool + class TestCheckPathAndNormalize: @pytest.fixture(autouse=True) diff --git a/tests/unit/synapseutils/unit_test_synapseutils_sync.py b/tests/unit/synapseutils/unit_test_synapseutils_sync.py index 52f5a5d2f..58c60953d 100644 --- a/tests/unit/synapseutils/unit_test_synapseutils_sync.py +++ b/tests/unit/synapseutils/unit_test_synapseutils_sync.py @@ -210,6 +210,36 @@ def test_read_manifest_file_synapse_store_values_not_set(syn: Synapse) -> None: assert expected_synapseStore == actual_synapseStore +def test_read_manifest_file_synapse_store_values_all_blank(syn: Synapse) -> None: + # GIVEN a manifest with a local path and a URL path, and no synapseStore values + project_id = SYN_123 + header = "path\tparent\tsynapseStore\n" + path1 = os.path.abspath(os.path.expanduser("~/file1.txt")) + path2 = SYNAPSE_URL + row1 = "%s\t%s\t\n" % (path1, project_id) + row2 = "%s\t%s\t\n" % (path2, project_id) + + expected_synapseStore = { + str(path1): True, + str(path2): False, + } + + manifest = StringIO(header + row1 + row2) + with ( + patch.object(syn, "get_async", return_value=Project()), + patch.object(os.path, "isfile", return_value=True), + patch.object(sync, "_check_size_each_file", return_value=Mock()), + ): # side effect mocks values for: file1.txt + # WHEN I read the manifest file + manifest_dataframe = synapseutils.sync.readManifestFile(syn, manifest) + + # THEN the local path is True and the URL path is False + actual_synapseStore = manifest_dataframe.set_index("path")[ + "synapseStore" + ].to_dict() + assert expected_synapseStore == actual_synapseStore + + def test_read_manifest_file_synapse_store_values_are_set(syn: Synapse) -> None: project_id = SYN_123 header = "path\tparent\tsynapseStore\n" @@ -1162,8 +1192,9 @@ def mock_uploader_constructor(*args, **kwargs): expected_path = data["path"][i] expected_parent = data["parent"][i] expected_name = data["name"][i] - expected_used = data["used"][i] - expected_executed = data["executed"][i] + # missing provenance values are given to the upload item as empty lists + expected_used = data["used"][i] or [] + expected_executed = data["executed"][i] or [] expected_annos = expected_anno_data[i] upload_items.append(upload_item_init.return_value) @@ -1180,6 +1211,69 @@ def mock_uploader_constructor(*args, **kwargs): mock_uploader.upload.assert_called_once_with(upload_items) +@patch("os.path.isfile") +async def test_manifest_upload_missing_provenance_builds_dependency_graph( + mock_isfile: MagicMock, syn: Synapse +) -> None: + """Verify that a missing used or executed value in the manifest is treated as + no provenance, and does not break the real dependency graph build.""" + # GIVEN local files that exist + mock_isfile.side_effect = lambda path: path.startswith("/tmp") + + # AND a manifest where one executed value is missing + df = pd.DataFrame( + data={ + "path": ["/tmp/foo", "/tmp/bar"], + "parent": [SYN_123, SYN_123], + "used": [[], ["/tmp/foo"]], + "executed": [math.nan, []], + } + ) + + with patch.object( + _SyncUploader, "_build_tasks_from_dependency_graph", return_value=[] + ) as mock_build_tasks: + # WHEN I upload the manifest + await synapseutils.sync._manifest_upload(syn, df) + + # THEN the dependency graph has no dependencies for the missing value + dependency_graph = mock_build_tasks.call_args.kwargs["dependency_graph"] + assert dependency_graph.path_to_dependencies == { + "/tmp/foo": [], + "/tmp/bar": ["/tmp/foo"], + } + + +@pytest.mark.parametrize( + "value, expected", + [ + (None, []), + (math.nan, []), + (float("nan"), []), + ([], []), + (["/tmp/foo", SYN_123], ["/tmp/foo", SYN_123]), + ("/tmp/foo", "/tmp/foo"), + ("", ""), + ], + ids=[ + "none", + "math_nan", + "float_nan", + "empty_list", + "list", + "str", + "empty_str", + ], +) +def test_missing_to_empty_list(value: Any, expected: Any) -> None: + # GIVEN a used or executed value from a manifest row + # WHEN I convert the value + result = synapseutils.sync._missing_to_empty_list(value) + + # THEN a missing value becomes an empty list, and other values are unchanged + assert result == expected + + class TestSyncUploader: @patch("os.path.isfile") def test_order_items(self, mock_isfile: MagicMock, syn: Synapse) -> None: From d767b03b0faf6403ea628ee66a6fc871212d1fdc Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Wed, 28 Oct 2026 15:46:54 -0700 Subject: [PATCH 11/15] [SYNPY-1926] Added support for python 3.15 (#1470) * updated pandas to use 3.x * fix tests that do not work in pandas 3.x * added support for python3.15 * made arg positional * made arg positional * ran black * fix issue with duplicated df indeces * fix nan to none helper * construct_rownames now takes a RowSet * fix issue with duplicated df indeces * fix nan to none helper * construct_rownames now takes a RowSet * added comments to tests * updated dockerfile * updated pandas to use 3.x * fix tests that do not work in pandas 3.x * fix issue with duplicated df indeces * fix nan to none helper * construct_rownames now takes a RowSet * added comments to tests * cast columns to objects * pinned numpy versiosn for specific pandas versions * added unit tests * added helper function * add type hints and unit tests --- .github/workflows/build.yml | 16 ++++++++-------- .github/workflows/validate-release.yml | 2 +- CLAUDE.md | 4 ++-- CONTRIBUTING.md | 12 ++++++------ Dockerfile | 2 +- README.md | 2 +- docs/tutorials/installation.md | 6 +++--- setup.cfg | 3 ++- .../core/download/download_functions.py | 4 ++-- .../synapseclient/core/unit_test_download.py | 4 +--- 10 files changed, 27 insertions(+), 28 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f134759d9..c9d385318 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,7 +55,7 @@ jobs: # if changing the below change the run-integration-tests versions and the check-deploy versions # Make sure that we are running the integration tests on the first and last versions of the matrix - python: ['3.11', '3.12', '3.13', '3.14'] + python: ['3.11', '3.12', '3.13', '3.14', '3.15'] runs-on: ${{ matrix.os }} @@ -109,7 +109,7 @@ jobs: pytest -sv --cov-append --cov=. --cov-report xml tests/unit - name: Check for Secret availability id: secret-check - if: ${{ contains(fromJSON('["3.11"]'), matrix.python) || contains(fromJSON('["3.14"]'), matrix.python) }} + if: ${{ contains(fromJSON('["3.11"]'), matrix.python) || contains(fromJSON('["3.15"]'), matrix.python) }} # perform secret check & put boolean result as an output shell: bash run: | @@ -126,7 +126,7 @@ jobs: fi - name: Download Failed Tests from Previous Attempt - if: ${{ github.run_attempt > 1 && (contains(fromJSON('["3.11"]'), matrix.python) || contains(fromJSON('["3.14"]'), matrix.python)) && steps.secret-check.outputs.secrets_available == 'true'}} + if: ${{ github.run_attempt > 1 && (contains(fromJSON('["3.11"]'), matrix.python) || contains(fromJSON('["3.15"]'), matrix.python)) && steps.secret-check.outputs.secrets_available == 'true'}} uses: actions/download-artifact@v4 with: name: failed-tests-${{ matrix.os }}-${{ matrix.python }} @@ -142,25 +142,25 @@ jobs: shell: bash # keep versions consistent with the first and last from the strategy matrix - if: ${{ (contains(fromJSON('["3.11"]'), matrix.python) || contains(fromJSON('["3.14"]'), matrix.python)) && steps.secret-check.outputs.secrets_available == 'true' && github.event_name != 'release'}} + if: ${{ (contains(fromJSON('["3.11"]'), matrix.python) || contains(fromJSON('["3.15"]'), matrix.python)) && steps.secret-check.outputs.secrets_available == 'true' && github.event_name != 'release'}} run: | # Set SYNAPSE_PROFILE based on OS and Python version if [ "${{ startsWith(matrix.os, 'ubuntu') }}" == "true" ]; then if [ "${{ matrix.python }}" == "3.11" ]; then export SYNAPSE_PROFILE="TestUbuntuMinimumPython" - elif [ "${{ matrix.python }}" == "3.14" ]; then + elif [ "${{ matrix.python }}" == "3.15" ]; then export SYNAPSE_PROFILE="TestUbuntuMaximumPython" fi elif [ "${{ startsWith(matrix.os, 'windows') }}" == "true" ]; then if [ "${{ matrix.python }}" == "3.11" ]; then export SYNAPSE_PROFILE="TestWindowsMinimumPython" - elif [ "${{ matrix.python }}" == "3.14" ]; then + elif [ "${{ matrix.python }}" == "3.15" ]; then export SYNAPSE_PROFILE="TestWindowsMaximumPython" fi elif [ "${{ startsWith(matrix.os, 'macos') }}" == "true" ]; then if [ "${{ matrix.python }}" == "3.11" ]; then export SYNAPSE_PROFILE="TestMacosMinimumPython" - elif [ "${{ matrix.python }}" == "3.14" ]; then + elif [ "${{ matrix.python }}" == "3.15" ]; then export SYNAPSE_PROFILE="TestMacosMaximumPython" fi fi @@ -547,7 +547,7 @@ jobs: os: [ubuntu-24.04, macos-15-intel, windows-2022] # python versions should be consistent with the strategy matrix and the runs-integration-tests versions - python: ['3.11', '3.12', '3.13', '3.14'] + python: ['3.11', '3.12', '3.13', '3.14', '3.15'] runs-on: ${{ matrix.os }} diff --git a/.github/workflows/validate-release.yml b/.github/workflows/validate-release.yml index 04f4492d2..2d6bc1a31 100644 --- a/.github/workflows/validate-release.yml +++ b/.github/workflows/validate-release.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: '3.14' + python-version: '3.15' - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/CLAUDE.md b/CLAUDE.md index a19452b19..4b1560669 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ Synapse Python Client — official Python SDK and CLI for Synapse (synapse.org), ## Stack -- Python 3.11–3.14 (`setup.cfg`: `python_requires = >=3.11, <3.15`) +- Python 3.11–3.15 (`setup.cfg`: `python_requires = >=3.11, <3.16`) - HTTP: httpx (async), requests (sync/legacy) - Models: stdlib dataclasses (NOT Pydantic) - pandas (optional): `pandas>=1.5,<4.0` (`setup.cfg`, 4 places) @@ -132,7 +132,7 @@ Code must work on every pandas version from 1.5 to 3.x. Use one code path that w - Integration tests use `--reruns 3` for flaky retries and `-n 4 --dist loadscope` for parallelism - Integration fixtures create per-worker Synapse projects; use `schedule_for_cleanup()` for teardown - Auth env vars: `SYNAPSE_AUTH_TOKEN` (bearer token), `SYNAPSE_PROFILE` (config file profile, default: `"default"`), `SYNAPSE_TOKEN_AWS_SSM_PARAMETER_NAME` (AWS SSM path) -- CI runs integration tests only on Python 3.11 and 3.14 (oldest + newest) to limit Synapse server load +- CI runs integration tests only on Python 3.11 and 3.15 (oldest + newest) to limit Synapse server load - CI job `test-pandas-versions` (`.github/workflows/build.yml`) runs the unit tests on older pandas versions: 1.5.3 on Python 3.11, 2.1.4 on Python 3.12, 2.2.3 on Python 3.13 (ubuntu only). The `package` job needs it. pandas < 2.2.2 requires `numpy<2`, so each matrix entry pins its own numpy version (1.26.4, 1.26.4, 2.5.4). ## Maintenance diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 06ecb2736..a16981469 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -93,7 +93,7 @@ copied to forks). #### Installing the Python Client in a virtual environment with pipenv Perform the following one-time steps to set up your local environment. -1. This package uses Python, if you have not already, please install [pyenv](https://github.com/pyenv/pyenv#installation) to manage your Python versions. Versions supported by this package are all versions >=3.11 and <=3.14. If you do not install `pyenv` make sure that Python and `pip` are installed correctly and have been added to your PATH by running `python3 --version` and `pip3 --version`. If your installation was successful, your terminal will return the versions of Python and `pip` that you installed. **Note**: If you have `pyenv` it will install a specific version of Python for you. +1. This package uses Python, if you have not already, please install [pyenv](https://github.com/pyenv/pyenv#installation) to manage your Python versions. Versions supported by this package are all versions >=3.11 and <=3.15. If you do not install `pyenv` make sure that Python and `pip` are installed correctly and have been added to your PATH by running `python3 --version` and `pip3 --version`. If your installation was successful, your terminal will return the versions of Python and `pip` that you installed. **Note**: If you have `pyenv` it will install a specific version of Python for you. 2. Install `pipenv` by running `pip install pipenv`. - If you already have `pipenv` installed, ensure that the version is >=2023.9.8 to avoid compatibility issues. @@ -271,18 +271,18 @@ When adding support for a new Python version or dropping support for an old vers #### Adding a new Python version -When adding support for a new Python version (e.g., adding Python 3.15), update the following: +When adding support for a new Python version (e.g., adding Python 3.16), update the following: **Code configuration files:** 1. **`setup.cfg`**: - - Add the new version to the `classifiers` list under `[metadata]` (e.g., `Programming Language :: Python :: 3.15`) - - Update the `python_requires` constraint under `[options]` to include the new version (e.g., `>=3.11, <3.16`) + - Add the new version to the `classifiers` list under `[metadata]` (e.g., `Programming Language :: Python :: 3.16`) + - Update the `python_requires` constraint under `[options]` to include the new version (e.g., `>=3.11, <3.17`) 2. **`pyproject.toml`**: - Update the `target-version` list in the `[tool.black]` section to include the new version if needed 3. **`Dockerfile`**: - - Update the base image to use the new Python version (e.g., `FROM python:3.15-slim`) + - Update the base image to use the new Python version (e.g., `FROM python:3.16-slim`) **CI/CD configuration files:** 1. **`.github/workflows/build.yml`**: @@ -301,7 +301,7 @@ When dropping support for an old Python version (e.g., removing Python 3.11), up **Code configuration files:** 1. **`setup.cfg`**: - Remove the old version from the `classifiers` list under `[metadata]` - - Update the `python_requires` constraint under `[options]` to reflect the new minimum version (e.g., `>=3.12, <3.15`) + - Update the `python_requires` constraint under `[options]` to reflect the new minimum version (e.g., `>=3.12, <3.16`) 2. **`pyproject.toml`**: - Update the `target-version` list in the `[tool.black]` section to remove the old version diff --git a/Dockerfile b/Dockerfile index 99b8ffdaa..19d51d148 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.14-slim +FROM python:3.15-slim RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections RUN apt-get update \ diff --git a/README.md b/README.md index de9d91023..443392b97 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ flowchart TD Installation ------------ -We test the client on Python 3.11, 3.12, 3.13, and 3.14. It runs on Mac OS X, Linux, and Windows. +We test the client on Python 3.11, 3.12, 3.13, 3.14, and 3.15. It runs on Mac OS X, Linux, and Windows. **Version 3.0 and later needs Python 3.10 or higher. Version 4.15.0 and later needs Python 3.11 or higher.** diff --git a/docs/tutorials/installation.md b/docs/tutorials/installation.md index ca4f2e932..2581f9978 100644 --- a/docs/tutorials/installation.md +++ b/docs/tutorials/installation.md @@ -21,7 +21,7 @@ The [synapseclient](https://pypi.python.org/pypi/synapseclient/) package is avai - conda: Please follow instructions [here](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html) to manage environments: ```bash -conda create -n synapseclient python=3.14 +conda create -n synapseclient python=3.15 conda activate synapseclient # Here are a few ways to install the client. Choose the one that fits your use-case @@ -43,8 +43,8 @@ to the `/usr/local/lib` directory. [See here](https://github.com/conda/conda/iss - pyenv: Use [virtualenv](https://virtualenv.pypa.io/en/latest/) to manage your python environment: ```bash -pyenv install -v 3.14.0 -pyenv global 3.14.0 +pyenv install -v 3.15.0 +pyenv global 3.15.0 python -m venv env source env/bin/activate diff --git a/setup.cfg b/setup.cfg index 3e9085626..4cc209800 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,6 +26,7 @@ classifiers = Programming Language :: Python :: 3.12 Programming Language :: Python :: 3.13 Programming Language :: Python :: 3.14 + Programming Language :: Python :: 3.15 Operating System :: MacOS Operating System :: Microsoft :: Windows Operating System :: Unix @@ -41,7 +42,7 @@ classifiers = zip_safe = False include_package_data = True packages = find: -python_requires = >=3.11, <3.15 +python_requires = >=3.11, <3.16 install_requires = requests>=2.34.0,<3.0 urllib3>=2.8.0 diff --git a/synapseclient/core/download/download_functions.py b/synapseclient/core/download/download_functions.py index 14d211f99..71d83d54f 100644 --- a/synapseclient/core/download/download_functions.py +++ b/synapseclient/core/download/download_functions.py @@ -973,7 +973,7 @@ def _ftp_report_hook( destination=destination, file_handle_id=file_handle_id ) range_header = ( - {"Range": f"bytes={os.path.getsize(filename=temp_destination)}-"} + {"Range": f"bytes={os.path.getsize(temp_destination)}-"} if os.path.exists(temp_destination) else {} ) @@ -1103,7 +1103,7 @@ def _ftp_report_hook( # Servers that respect the Range header return 206 Partial Content if response.status_code == 206: mode = "ab" - previously_transferred = os.path.getsize(filename=temp_destination) + previously_transferred = os.path.getsize(temp_destination) to_be_transferred += previously_transferred transferred += previously_transferred increment_progress_bar_total( diff --git a/tests/unit/synapseclient/core/unit_test_download.py b/tests/unit/synapseclient/core/unit_test_download.py index 826a3c8dc..8b18a1798 100644 --- a/tests/unit/synapseclient/core/unit_test_download.py +++ b/tests/unit/synapseclient/core/unit_test_download.py @@ -986,9 +986,7 @@ async def test_download_end_early_retry(self, syn: Synapse) -> None: # assert getsize() called 2 times # once because exists()=True and another time because response status code = 206 - assert [ - call(filename=temp_destination) - ] * 2 == mocked_getsize.call_args_list + assert [call(temp_destination)] * 2 == mocked_getsize.call_args_list # assert shutil.move() called 1 time mocked_move.assert_called_once_with(temp_destination, destination) From dc3c2ff63aa7f872f699e823bdcfcbca03170f52 Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Tue, 3 Nov 2026 13:07:55 -0800 Subject: [PATCH 12/15] [SYNPY-1942] Fix Security alerts (#1475) * update dependencies * fixed issue with unchecked strings --- Pipfile.lock | 36 ++++----- synapseclient/core/version_check.py | 32 ++++++-- .../core/unit_test_version_check.py | 77 +++++++++++++++++++ 3 files changed, 121 insertions(+), 24 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 5164fb2fb..4659ea631 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -42,11 +42,11 @@ }, "certifi": { "hashes": [ - "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", - "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" + "sha256:73191c47aaa79da394e8fee2dbc2ec827432cab56311122c9e47abf79e390f62", + "sha256:b9995d97b64d0431a5af837d8ca8cd6238104d1f319f04bd93ea43124d6c861e" ], "markers": "python_version >= '3.7'", - "version": "==2026.7.22" + "version": "==2026.10.18" }, "cffi": { "hashes": [ @@ -637,11 +637,11 @@ }, "setuptools": { "hashes": [ - "sha256:51a52592b3b99e102b609654876bd65f19f999935166d1352678931132b0c670", - "sha256:f4695c21257f0d9b537ec2692c941d02ee143b7cc1276941349a546573b2ef73" + "sha256:23657205b63d4d31395ab917815247f694aafad28cd21316bf5fd45a51048ea0", + "sha256:5231689c6ac8156cd155cfb98c3fd6fb252c3e7e9bd3d78b64d3c55f132624c9" ], "markers": "python_version >= '3.10'", - "version": "==84.0.0" + "version": "==84.1.0" }, "synapseclient": { "markers": "python_version >= '3.10' and python_version < '3.15'", @@ -953,11 +953,11 @@ }, "certifi": { "hashes": [ - "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", - "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" + "sha256:73191c47aaa79da394e8fee2dbc2ec827432cab56311122c9e47abf79e390f62", + "sha256:b9995d97b64d0431a5af837d8ca8cd6238104d1f319f04bd93ea43124d6c861e" ], "markers": "python_version >= '3.7'", - "version": "==2026.7.22" + "version": "==2026.10.18" }, "cffi": { "hashes": [ @@ -1495,11 +1495,11 @@ }, "filelock": { "hashes": [ - "sha256:3f4a557945a7b0f95efeb1f432267affe5d45ac8ddde2aed1b97ebb62382c089", - "sha256:7ba0927482c5a814b0a7f391d029ccdb8010f576f0a74c0dcde1811e8bc4c1b6" + "sha256:7be2662e9e826b9bba28afc0f843a123280d799a2ea44bb5d35ccec67905ae44", + "sha256:c4c937ccac2a813cee448e662a56366cfb374c0f8702e75f295c412cc1c5d5a3" ], "markers": "python_version >= '3.10'", - "version": "==4.1.1" + "version": "==4.2.1" }, "flake8": { "hashes": [ @@ -2746,11 +2746,11 @@ }, "setuptools": { "hashes": [ - "sha256:51a52592b3b99e102b609654876bd65f19f999935166d1352678931132b0c670", - "sha256:f4695c21257f0d9b537ec2692c941d02ee143b7cc1276941349a546573b2ef73" + "sha256:23657205b63d4d31395ab917815247f694aafad28cd21316bf5fd45a51048ea0", + "sha256:5231689c6ac8156cd155cfb98c3fd6fb252c3e7e9bd3d78b64d3c55f132624c9" ], "markers": "python_version >= '3.10'", - "version": "==84.0.0" + "version": "==84.1.0" }, "six": { "hashes": [ @@ -2805,11 +2805,11 @@ }, "virtualenv": { "hashes": [ - "sha256:3769219a308c5d2f093e7729621ad12a6346b5767a7ec4338414e2a0fb0c526b", - "sha256:5f427d56f39eb7e7447d641dd4b7ab1e9c92793f498f35f26da2e4972c5546ae" + "sha256:4d1bee354cd81c820da3bee56e38be3426490f8d1fc54e10ea5b2072ebad8ef8", + "sha256:ac51744da66ae56ff814b087d65096c94de698ec520adc624b108b679655809b" ], "markers": "python_version >= '3.9'", - "version": "==21.14.7" + "version": "==21.14.9" }, "watchdog": { "hashes": [ diff --git a/synapseclient/core/version_check.py b/synapseclient/core/version_check.py index cd4adb885..bf94fa3c6 100644 --- a/synapseclient/core/version_check.py +++ b/synapseclient/core/version_check.py @@ -24,6 +24,9 @@ _PYPI_JSON_URL = "https://pypi.org/pypi/synapseclient/json" _RELEASE_NOTES_URL = "https://python-docs.synapse.org/news/" +# Accepts release, pre-release, post-release, and dev versions such as +# 1.0, 4.14.0, 4.14.0rc1, 4.14.0.post1, and 0.5.1.dev200 +_VERSION_PATTERN = re.compile(r"\d+(\.\d+)*((a|b|rc)\d+)?(\.post\d+)?(\.dev\d+)?") def version_check( @@ -88,7 +91,7 @@ def check_for_updates(logger: logging.Logger = None): logger: a logger for logging output """ - current_version = synapseclient.__version__ + current_version = _validate_version(synapseclient.__version__) latest_version = _get_version_info_from_pypi() msg = ( @@ -154,12 +157,11 @@ def _version_check( """ if not current_version: current_version = synapseclient.__version__ - assert isinstance(current_version, str) + current_version = _validate_version(current_version) if use_local_metadata: metadata = _get_local_package_metadata() - latest_version = metadata["latestVersion"] - assert isinstance(latest_version, str) + latest_version = _validate_version(metadata["latestVersion"]) else: latest_version = _get_version_info_from_pypi() @@ -198,8 +200,26 @@ def _get_version_info_from_pypi() -> str: """ content = httpx.get(_PYPI_JSON_URL) data = json.load(content) - version = data["info"]["version"] - assert isinstance(version, str) + return _validate_version(data["info"]["version"]) + + +def _validate_version(version: Any) -> str: + """ + Makes sure that a version is a string in a known version format. + This prevents untrusted data, such as newline characters, from getting + into log messages. + + Arguments: + version: The version to validate + + Raises: + ValueError: If the version is not a string in a known version format + + Returns: + str: The version, if it is valid + """ + if not isinstance(version, str) or not _VERSION_PATTERN.fullmatch(version): + raise ValueError(f"Invalid version: {version!r}") return version diff --git a/tests/unit/synapseclient/core/unit_test_version_check.py b/tests/unit/synapseclient/core/unit_test_version_check.py index 958304f07..93b784db2 100644 --- a/tests/unit/synapseclient/core/unit_test_version_check.py +++ b/tests/unit/synapseclient/core/unit_test_version_check.py @@ -6,9 +6,12 @@ from synapseclient.core.version_check import ( _get_local_package_metadata, + _get_version_info_from_pypi, _is_current_version_behind, + _validate_version, _version_check, _version_tuple, + check_for_updates, ) @@ -130,3 +133,77 @@ def test_version_tuple( def test_get_local_files() -> None: """Tests for _get_local_package_metadata function""" assert _get_local_package_metadata() + + +FORGED_VERSION = "1.2.3\nFORGED LOG ENTRY" + +INVALID_VERSIONS = [ + "", + "abc", + "1.2.3\n", + FORGED_VERSION, + "1.2.3.4\nFORGED LOG ENTRY", + "1.2.3\r\n", + " 1.2.3", + "1..2", + None, + 123, +] + + +@pytest.mark.parametrize( + "version", + ["1", "1.0", "4.14.0", "0.5.1.dev200", "4.14.0rc1", "4.14.0a1", "4.14.0.post1"], +) +async def test_validate_version_valid(version: str) -> None: + """Tests that _validate_version returns valid versions unchanged""" + assert _validate_version(version) == version + + +@pytest.mark.parametrize("version", INVALID_VERSIONS) +async def test_validate_version_invalid(version) -> None: + """Tests that _validate_version raises an error for invalid versions""" + with pytest.raises(ValueError, match="Invalid version"): + _validate_version(version) + + +@pytest.mark.parametrize("version", INVALID_VERSIONS) +async def test_get_version_info_from_pypi_invalid(version) -> None: + """Tests that an invalid version from PyPI is not returned""" + with ( + patch("synapseclient.core.version_check.httpx.get"), + patch( + "synapseclient.core.version_check.json.load", + return_value={"info": {"version": version}}, + ), + ): + with pytest.raises(ValueError, match="Invalid version"): + _get_version_info_from_pypi() + + +async def test_version_check_invalid_local_metadata() -> None: + """Tests that an invalid local latest version is not used""" + with patch( + "synapseclient.core.version_check._get_local_package_metadata", + return_value={"latestVersion": FORGED_VERSION}, + ): + with pytest.raises(ValueError, match="Invalid version"): + _version_check("1.0.0", use_local_metadata=True) + + +async def test_check_for_updates_invalid_current_version() -> None: + """Tests that an invalid current version is not logged""" + with ( + patch( + "synapseclient.core.version_check.synapseclient.__version__", + FORGED_VERSION, + ), + patch( + "synapseclient.core.version_check._get_version_info_from_pypi", + return_value="1.2.3", + ), + patch("synapseclient.core.version_check.sys.stdout") as mock_stdout, + ): + with pytest.raises(ValueError, match="Invalid version"): + check_for_updates() + mock_stdout.write.assert_not_called() From 9ca5214240db370244cf3b8fb318edd8e7ee0f50 Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Tue, 3 Nov 2026 13:10:29 -0800 Subject: [PATCH 13/15] update version v4.15.0 --- synapseclient/synapsePythonClient | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapseclient/synapsePythonClient b/synapseclient/synapsePythonClient index d914c4735..f244cef7d 100644 --- a/synapseclient/synapsePythonClient +++ b/synapseclient/synapsePythonClient @@ -1,6 +1,6 @@ { "client": "synapsePythonClient", - "latestVersion": "4.14.0", + "latestVersion": "4.15.0", "blacklist": [ "0.0.0", "0.4.1", From ffd3f7caf84b38b11655a62b74b6ed2e6747bfec Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Tue, 3 Nov 2026 13:14:41 -0800 Subject: [PATCH 14/15] update release notes v4.15.0 --- docs/news.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/news.md b/docs/news.md index 79f3efe4d..50bbd4cdf 100644 --- a/docs/news.md +++ b/docs/news.md @@ -9,6 +9,37 @@ detailing some of the changes. the 4.x.x versions hidden behind optional feature flags or different import paths. Any breaking changes will not be included until v5.0. +## 4.15.0 + +## Highlights + +- The Synapse Python Client now supports Python 3.15 and pandas 3.x. +- **Breaking change:** Support for Python 3.10 is removed. Python 3.11 or newer is now necessary. +- When you store a JSON schema, the client now records its version information. +- If you can read a file but cannot download it (for example, because of an unmet access requirement), you can now move or update it. The client no longer loses the file handle ID. +- The schema registry functions in the curator extension are deprecated. Use the Organization and JSONSchema models instead. +- Many security fixes from dependency updates. + +## Features + +- [SYNPY-1926] Added support for Python 3.15 by @andrewelamb in #1470 +- [SYNPY-1933] Added support for pandas 3.x (pandas>=1.5,<4.0). The curator extension no longer depends on pandarallel. by @andrewelamb in #1471 +- [SYNPY-1910] Removed support for Python 3.10 by @andrewelamb in #1464 +- [SYNPY-1795] JSONSchema now saves version information when it is stored by @andrewelamb in #1463 +- [SYNPY-1913] Added the source_entity_version_number field to the Grid and GridSession models by @andrewelamb in #1465 + +## Bug Fixes + +- [SYNPY-1941] Kept data_file_handle_id when Synapse withholds the file handle (for example, unmet access requirements), so that store() works for these files by @thomasyu888 in #1474 + +## Tech Debt + +- [SYNPY-1930] Deprecated the query_schema_registry and get_latest_schema_uri functions (to be removed in 5.0.0). Use the Organization and JSONSchema models instead. by @andrewelamb in #1467 +- [SYNPY-1928] Fixed security issues by updating packages by @andrewelamb in #1466 +- [SYNPY-1942] Fixed critical and high security and code scanning alerts by @andrewelamb in #1475 +- Fixed Trivy failures that blocked Docker image publishing by @BryanFauble in #1468 +- [SYNPY-1924] Disabled agent integration tests that timed out in CI by @linglp in #1460 + ## 4.14.0 ## Highlights From 4d992408ce2c653cc833597184824d3fbd47743f Mon Sep 17 00:00:00 2001 From: andrewelamb Date: Wed, 4 Nov 2026 08:36:32 -0800 Subject: [PATCH 15/15] Update synapsePythonClient version to 4.15.0 --- synapseclient/synapsePythonClient | 1 - 1 file changed, 1 deletion(-) diff --git a/synapseclient/synapsePythonClient b/synapseclient/synapsePythonClient index cebdffe3e..f244cef7d 100644 --- a/synapseclient/synapsePythonClient +++ b/synapseclient/synapsePythonClient @@ -1,7 +1,6 @@ { "client": "synapsePythonClient", "latestVersion": "4.15.0", - "latestVersion": "4.14.0", "blacklist": [ "0.0.0", "0.4.1",