From f1fc918d7b4a9e830afc11af76b8af8f6f4e3bc9 Mon Sep 17 00:00:00 2001 From: echan5 Date: Fri, 26 Sep 2025 12:12:54 -0400 Subject: [PATCH 1/7] enable callable group_by --- deepdiff/diff.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/deepdiff/diff.py b/deepdiff/diff.py index 43ccd00..2f34605 100755 --- a/deepdiff/diff.py +++ b/deepdiff/diff.py @@ -157,7 +157,7 @@ def __init__(self, exclude_regex_paths: Union[str, List[str], Pattern[str], List[Pattern[str]], None]=None, exclude_types: Optional[List[type]]=None, get_deep_distance: bool=False, - group_by: Union[str, Tuple[str, str], None]=None, + group_by: Union[str, Tuple[str, str], Callable, None]=None, group_by_sort_key: Union[str, Callable, None]=None, hasher: Optional[Callable]=None, hashes: Optional[Dict[Any, Any]]=None, @@ -1834,7 +1834,32 @@ def _get_view_results(self, view): @staticmethod def _get_key_for_group_by(row, group_by, item_name): + """ + Get the key value to group a row by, using the specified group_by parameter. + + Example + >>> row = {'first': 'John', 'middle': 'Joe', 'last': 'Smith'} + >>> group_by_key = DeepDiff._get_key_for_group_by(row, 'first', 't1') + 'John' + >>> nested_row = {'id': 123, 'demographics': {'names': {'first': 'John', 'middle': 'Joe', 'last': 'Smith'}}} + >>> group_by_key = DeepDiff._get_key_for_group_by(nested_row, + lambda x: x['demographics']['names']['first'], 't1') + 'John' + + Args: + row (dict): The dictionary (row) to extract the group by key from. + group_by (str or callable): The key name or function to call to get to the key value to group by. + item_name (str): The name of the item, used for error messages. + + Returns: + str: The key value to group by. + + Raises: + KeyError: If the specified key is not found in the row. + """ try: + if callable(group_by): + return group_by(row) return row.pop(group_by) except KeyError: logger.error("Unable to group {} by {}. The key is missing in {}".format(item_name, group_by, row)) From 0265184e18bbb61a82df09ecd8bd8f6f7cbcc5e5 Mon Sep 17 00:00:00 2001 From: echan5 Date: Fri, 26 Sep 2025 12:13:12 -0400 Subject: [PATCH 2/7] fix docstring examples for doctest errors --- deepdiff/diff.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/deepdiff/diff.py b/deepdiff/diff.py index 2f34605..37099c4 100755 --- a/deepdiff/diff.py +++ b/deepdiff/diff.py @@ -943,7 +943,7 @@ def _diff_by_forming_pairs_and_comparing_one_by_one( t2_from_index=None, t2_to_index=None, ): for (i, j), (x, y) in self._get_matching_pairs( - level, + level, t1_from_index=t1_from_index, t1_to_index=t1_to_index, t2_from_index=t2_from_index, t2_to_index=t2_to_index ): @@ -1939,13 +1939,13 @@ def affected_paths(self): Whether a value was changed or they were added or removed. Example + >>> from pprint import pprint >>> t1 = {1: 1, 2: 2, 3: [3], 4: 4} >>> t2 = {1: 1, 2: 4, 3: [3, 4], 5: 5, 6: 6} >>> ddiff = DeepDiff(t1, t2) - >>> ddiff >>> pprint(ddiff, indent=4) - { 'dictionary_item_added': [root[5], root[6]], - 'dictionary_item_removed': [root[4]], + { 'dictionary_item_added': ['root[5]', 'root[6]'], + 'dictionary_item_removed': ['root[4]'], 'iterable_item_added': {'root[3][1]': 4}, 'values_changed': {'root[2]': {'new_value': 4, 'old_value': 2}}} >>> ddiff.affected_paths @@ -1971,13 +1971,13 @@ def affected_root_keys(self): Whether a value was changed or they were added or removed. Example + >>> from pprint import pprint >>> t1 = {1: 1, 2: 2, 3: [3], 4: 4} >>> t2 = {1: 1, 2: 4, 3: [3, 4], 5: 5, 6: 6} >>> ddiff = DeepDiff(t1, t2) - >>> ddiff >>> pprint(ddiff, indent=4) - { 'dictionary_item_added': [root[5], root[6]], - 'dictionary_item_removed': [root[4]], + { 'dictionary_item_added': ['root[5]', 'root[6]'], + 'dictionary_item_removed': ['root[4]'], 'iterable_item_added': {'root[3][1]': 4}, 'values_changed': {'root[2]': {'new_value': 4, 'old_value': 2}}} >>> ddiff.affected_paths From 82d1b4b28e900ba3f428c6b81a3993f577572d8c Mon Sep 17 00:00:00 2001 From: echan5 Date: Fri, 26 Sep 2025 12:13:40 -0400 Subject: [PATCH 3/7] add callable group_by tests --- tests/test_diff_group_by.py | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tests/test_diff_group_by.py diff --git a/tests/test_diff_group_by.py b/tests/test_diff_group_by.py new file mode 100644 index 0000000..8c6e1dd --- /dev/null +++ b/tests/test_diff_group_by.py @@ -0,0 +1,59 @@ +"""Tests for the group_by parameter of Deepdiff""" + +import pytest + +from deepdiff import DeepDiff + + +class TestGetKeyForGroupBy: + def test_group_by_string(self): + """Test where group_by is a single key (string).""" + row = {'first': 'John', 'middle': 'Joe', 'last': 'Smith'} + group_by = 'first' + item_name = 't1' + actual = DeepDiff._get_key_for_group_by(row, group_by, item_name) + expected = 'John' + + assert actual == expected + + def test_group_by_callable(self): + """Test where group_by is callable.""" + row = {'id': 123, 'demographics': {'names': {'first': 'John', 'middle': 'Joe', 'last': 'Smith'}}} + group_by = lambda x: x['demographics']['names']['first'] + item_name = 't1' + actual = DeepDiff._get_key_for_group_by(row, group_by, item_name) + expected = 'John' + assert actual == expected + + def test_group_by_key_error(self): + """Test where group_by is a key that is not in the row.""" + row = {'id': 123, 'demographics': {'names': {'first': 'John', 'middle': 'Joe', 'last': 'Smith'}}} + group_by = 'someotherkey' + item_name = 't1' + with pytest.raises(KeyError): + DeepDiff._get_key_for_group_by(row, group_by, item_name) + + +class TestGroupBy: + def test_group_by_callable(self): + """Test where group_by is a callable.""" + t1 = [ + {'id': 'AA', 'demographics': {'names': {'first': 'Joe', 'middle': 'John', 'last': 'Nobody'}}}, + {'id': 'BB', 'demographics': {'names': {'first': 'James', 'middle': 'Joyce', 'last': 'Blue'}}}, + {'id': 'CC', 'demographics': {'names': {'first': 'Mike', 'middle': 'Mark', 'last': 'Apple'}}}, + ] + + t2 = [ + {'id': 'AA', 'demographics': {'names': {'first': 'Joe', 'middle': 'John', 'last': 'Nobody'}}}, + {'id': 'BB', 'demographics': {'names': {'first': 'James', 'middle': 'Joyce', 'last': 'Brown'}}}, + {'id': 'CC', 'demographics': {'names': {'first': 'Mike', 'middle': 'Charles', 'last': 'Apple'}}}, + ] + + actual = DeepDiff(t1, t2, group_by=lambda x: x['demographics']['names']['first']) + expected = { + 'values_changed': { + "root['James']['demographics']['names']['last']": {'new_value': 'Brown', 'old_value': 'Blue'}, + "root['Mike']['demographics']['names']['middle']": {'new_value': 'Charles', 'old_value': 'Mark'}, + }, + } + assert actual == expected From 6140d2c7f53377651fe5cfa4a7f1f501d1826df4 Mon Sep 17 00:00:00 2001 From: echan5 Date: Fri, 26 Sep 2025 12:14:09 -0400 Subject: [PATCH 4/7] callable group_by documentation --- docs/basics.rst | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/docs/basics.rst b/docs/basics.rst index c944d28..6eba550 100644 --- a/docs/basics.rst +++ b/docs/basics.rst @@ -89,8 +89,8 @@ String difference 2 >>> >>> print (ddiff['values_changed']["root[4]['b']"]["diff"]) - --- - +++ + --- + +++ @@ -1,5 +1,4 @@ -world! -Goodbye! @@ -172,7 +172,7 @@ Datetime Group By -------- -group_by can be used when dealing with the list of dictionaries. It converts them from lists to a single dictionary with the key defined by group_by. The common use case is when reading data from a flat CSV, and the primary key is one of the columns in the CSV. We want to use the primary key instead of the CSV row number to group the rows. The group_by can do 2D group_by by passing a list of 2 keys. +group_by can be used when dealing with the list of dictionaries. It converts them from lists to a single dictionary with the key defined by group_by. The common use case is when reading data from a flat CSV, and the primary key is one of the columns in the CSV. We want to use the primary key instead of the CSV row number to group the rows. The group_by can do 2D group_by by passing a list of 2 keys. It is also possible to have a callable group_by, which can be used to access keys in more nested data structures. For example: >>> [ @@ -249,6 +249,28 @@ Now we use group_by='id': 'values_changed': {"root['BB']['James']['last_name']": {'new_value': 'Brown', 'old_value': 'Blue'}}} +Callable group_by Example: + >>> from deepdiff import DeepDiff + >>> + >>> t1 = [ + ... {'id': 'AA', 'demographics': {'names': {'first': 'Joe', 'middle': 'John', 'last': 'Nobody'}}}, + ... {'id': 'BB', 'demographics': {'names': {'first': 'James', 'middle': 'Joyce', 'last': 'Blue'}}}, + ... {'id': 'CC', 'demographics': {'names': {'first': 'Mike', 'middle': 'Mark', 'last': 'Apple'}}}, + ... ] + >>> + >>> t2 = [ + ... {'id': 'AA', 'demographics': {'names': {'first': 'Joe', 'middle': 'John', 'last': 'Nobody'}}}, + ... {'id': 'BB', 'demographics': {'names': {'first': 'James', 'middle': 'Joyce', 'last': 'Brown'}}}, + ... {'id': 'CC', 'demographics': {'names': {'first': 'Mike', 'middle': 'Charles', 'last': 'Apple'}}}, + ... ] + >>> + >>> diff = DeepDiff(t1, t2, group_by=lambda x: x['demographics']['names']['first']) + >>> pprint(diff) + {'values_changed': {"root['James']['demographics']['names']['last']": {'new_value': 'Brown', + 'old_value': 'Blue'}, + "root['Mike']['demographics']['names']['middle']": {'new_value': 'Charles', + 'old_value': 'Mark'}}} + .. _group_by_sort_key_label: Group By - Sort Key @@ -256,7 +278,7 @@ Group By - Sort Key group_by_sort_key is used to define how dictionaries are sorted if multiple ones fall under one group. When this parameter is used, group_by converts the lists of dictionaries into a dictionary of keys to lists of dictionaries. Then, group_by_sort_key is used to sort between the list. -For example, there are duplicate id values. If we only use group_by='id', one of the dictionaries with id of 'BB' will overwrite the other. However, if we also set group_by_sort_key='name', we keep both dictionaries with the id of 'BB'. +For example, there are duplicate id values. If we only use group_by='id', one of the dictionaries with id of 'BB' will overwrite the other. However, if we also set group_by_sort_key='name', we keep both dictionaries with the id of 'BB'. Example: >>> [{'id': 'AA', 'int_id': 2, 'last_name': 'Nobody', 'name': 'Joe'}, From c30287775fd558e466a47725a46ee31c319e78a2 Mon Sep 17 00:00:00 2001 From: echan5 Date: Fri, 26 Sep 2025 12:40:59 -0400 Subject: [PATCH 5/7] fix doctest example --- deepdiff/diff.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deepdiff/diff.py b/deepdiff/diff.py index 37099c4..dec2fdf 100755 --- a/deepdiff/diff.py +++ b/deepdiff/diff.py @@ -1839,11 +1839,11 @@ def _get_key_for_group_by(row, group_by, item_name): Example >>> row = {'first': 'John', 'middle': 'Joe', 'last': 'Smith'} - >>> group_by_key = DeepDiff._get_key_for_group_by(row, 'first', 't1') + >>> DeepDiff._get_key_for_group_by(row, 'first', 't1') 'John' >>> nested_row = {'id': 123, 'demographics': {'names': {'first': 'John', 'middle': 'Joe', 'last': 'Smith'}}} - >>> group_by_key = DeepDiff._get_key_for_group_by(nested_row, - lambda x: x['demographics']['names']['first'], 't1') + >>> group_by = lambda x: x['demographics']['names']['first'] + >>> DeepDiff._get_key_for_group_by(nested_row, group_by, 't1') 'John' Args: From eec4a5402810784c8f1ba15c6a749841b4c70db5 Mon Sep 17 00:00:00 2001 From: echan5 Date: Fri, 26 Sep 2025 13:08:49 -0400 Subject: [PATCH 6/7] fix depedencies for testing --- pyproject.toml | 8 ++++++-- uv.lock | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index dff03fa..3cae53b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,8 @@ name = "deepdiff" version = "8.5.0" dependencies = [ "orderly-set>=5.4.1,<6", + "numpy~=2.2.0; python_version >= '3.10'", + "numpy~=2.0; python_version < '3.10'", ] requires-python = ">=3.9" authors = [ @@ -46,8 +48,6 @@ dev = [ "bump2version~=1.0.0", "jsonpickle~=4.0.0", "ipdb~=0.13.0", - "numpy~=2.2.0; python_version >= '3.10'", - "numpy~=2.0; python_version < '3.10'", "python-dateutil~=2.9.0", "orjson~=3.10.0", "tomli~=2.2.0", @@ -73,6 +73,10 @@ test = [ "pytest-benchmark~=5.1.0", "pytest-cov~=6.0.0", "python-dotenv~=1.0.0", + "pydantic~=2.10.0", + "pytz~=2025.2", + "click~=8.1.0", + "uuid6~=2025.0.1", ] optimize = [ "orjson", diff --git a/uv.lock b/uv.lock index adac038..2b6fac4 100644 --- a/uv.lock +++ b/uv.lock @@ -276,6 +276,8 @@ name = "deepdiff" version = "8.5.0" source = { editable = "." } dependencies = [ + { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "orderly-set" }, ] @@ -292,8 +294,6 @@ dev = [ { name = "ipdb" }, { name = "jsonpickle" }, { name = "nox" }, - { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "orjson" }, { name = "pandas" }, { name = "polars" }, @@ -316,35 +316,42 @@ static = [ { name = "pydantic" }, ] test = [ + { name = "click" }, + { name = "pydantic" }, { name = "pytest" }, { name = "pytest-benchmark" }, { name = "pytest-cov" }, { name = "python-dotenv" }, + { name = "pytz" }, + { name = "uuid6" }, ] [package.metadata] requires-dist = [ { name = "bump2version", marker = "extra == 'dev'", specifier = "~=1.0.0" }, { name = "click", marker = "extra == 'cli'", specifier = "~=8.1.0" }, + { name = "click", marker = "extra == 'test'", specifier = "~=8.1.0" }, { name = "coverage", marker = "extra == 'coverage'", specifier = "~=7.6.0" }, { name = "flake8", marker = "extra == 'static'", specifier = "~=7.1.0" }, { name = "flake8-pyproject", marker = "extra == 'static'", specifier = "~=1.2.3" }, { name = "ipdb", marker = "extra == 'dev'", specifier = "~=0.13.0" }, { name = "jsonpickle", marker = "extra == 'dev'", specifier = "~=4.0.0" }, { name = "nox", marker = "extra == 'dev'", specifier = "==2025.5.1" }, - { name = "numpy", marker = "python_full_version >= '3.10' and extra == 'dev'", specifier = "~=2.2.0" }, - { name = "numpy", marker = "python_full_version < '3.10' and extra == 'dev'", specifier = "~=2.0" }, + { name = "numpy", marker = "python_full_version < '3.10'", specifier = "~=2.0" }, + { name = "numpy", marker = "python_full_version >= '3.10'", specifier = "~=2.2.0" }, { name = "orderly-set", specifier = ">=5.4.1,<6" }, { name = "orjson", marker = "extra == 'dev'", specifier = "~=3.10.0" }, { name = "orjson", marker = "extra == 'optimize'" }, { name = "pandas", marker = "extra == 'dev'", specifier = "~=2.2.0" }, { name = "polars", marker = "extra == 'dev'", specifier = "~=1.21.0" }, { name = "pydantic", marker = "extra == 'static'", specifier = "~=2.10.0" }, + { name = "pydantic", marker = "extra == 'test'", specifier = "~=2.10.0" }, { name = "pytest", marker = "extra == 'test'", specifier = "~=8.3.0" }, { name = "pytest-benchmark", marker = "extra == 'test'", specifier = "~=5.1.0" }, { name = "pytest-cov", marker = "extra == 'test'", specifier = "~=6.0.0" }, { name = "python-dateutil", marker = "extra == 'dev'", specifier = "~=2.9.0" }, { name = "python-dotenv", marker = "extra == 'test'", specifier = "~=1.0.0" }, + { name = "pytz", marker = "extra == 'test'", specifier = "~=2025.2" }, { name = "pyyaml", marker = "extra == 'cli'", specifier = "~=6.0.0" }, { name = "sphinx", marker = "extra == 'docs'", specifier = "~=6.2.0" }, { name = "sphinx-sitemap", marker = "extra == 'docs'", specifier = "~=2.6.0" }, @@ -352,6 +359,7 @@ requires-dist = [ { name = "tomli", marker = "extra == 'dev'", specifier = "~=2.2.0" }, { name = "tomli-w", marker = "extra == 'dev'", specifier = "~=1.2.0" }, { name = "uuid6", marker = "extra == 'dev'", specifier = "==2025.0.1" }, + { name = "uuid6", marker = "extra == 'test'", specifier = "~=2025.0.1" }, ] provides-extras = ["coverage", "cli", "dev", "docs", "static", "test", "optimize"] From 9a673feadf3e201e003e5b34eca5638661ca84a7 Mon Sep 17 00:00:00 2001 From: echan5 Date: Mon, 29 Sep 2025 21:32:20 -0400 Subject: [PATCH 7/7] wqRevert "fix depedencies for testing" This reverts commit eec4a5402810784c8f1ba15c6a749841b4c70db5. --- pyproject.toml | 8 ++------ uv.lock | 16 ++++------------ 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3cae53b..dff03fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,8 +7,6 @@ name = "deepdiff" version = "8.5.0" dependencies = [ "orderly-set>=5.4.1,<6", - "numpy~=2.2.0; python_version >= '3.10'", - "numpy~=2.0; python_version < '3.10'", ] requires-python = ">=3.9" authors = [ @@ -48,6 +46,8 @@ dev = [ "bump2version~=1.0.0", "jsonpickle~=4.0.0", "ipdb~=0.13.0", + "numpy~=2.2.0; python_version >= '3.10'", + "numpy~=2.0; python_version < '3.10'", "python-dateutil~=2.9.0", "orjson~=3.10.0", "tomli~=2.2.0", @@ -73,10 +73,6 @@ test = [ "pytest-benchmark~=5.1.0", "pytest-cov~=6.0.0", "python-dotenv~=1.0.0", - "pydantic~=2.10.0", - "pytz~=2025.2", - "click~=8.1.0", - "uuid6~=2025.0.1", ] optimize = [ "orjson", diff --git a/uv.lock b/uv.lock index 2b6fac4..adac038 100644 --- a/uv.lock +++ b/uv.lock @@ -276,8 +276,6 @@ name = "deepdiff" version = "8.5.0" source = { editable = "." } dependencies = [ - { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "orderly-set" }, ] @@ -294,6 +292,8 @@ dev = [ { name = "ipdb" }, { name = "jsonpickle" }, { name = "nox" }, + { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "orjson" }, { name = "pandas" }, { name = "polars" }, @@ -316,42 +316,35 @@ static = [ { name = "pydantic" }, ] test = [ - { name = "click" }, - { name = "pydantic" }, { name = "pytest" }, { name = "pytest-benchmark" }, { name = "pytest-cov" }, { name = "python-dotenv" }, - { name = "pytz" }, - { name = "uuid6" }, ] [package.metadata] requires-dist = [ { name = "bump2version", marker = "extra == 'dev'", specifier = "~=1.0.0" }, { name = "click", marker = "extra == 'cli'", specifier = "~=8.1.0" }, - { name = "click", marker = "extra == 'test'", specifier = "~=8.1.0" }, { name = "coverage", marker = "extra == 'coverage'", specifier = "~=7.6.0" }, { name = "flake8", marker = "extra == 'static'", specifier = "~=7.1.0" }, { name = "flake8-pyproject", marker = "extra == 'static'", specifier = "~=1.2.3" }, { name = "ipdb", marker = "extra == 'dev'", specifier = "~=0.13.0" }, { name = "jsonpickle", marker = "extra == 'dev'", specifier = "~=4.0.0" }, { name = "nox", marker = "extra == 'dev'", specifier = "==2025.5.1" }, - { name = "numpy", marker = "python_full_version < '3.10'", specifier = "~=2.0" }, - { name = "numpy", marker = "python_full_version >= '3.10'", specifier = "~=2.2.0" }, + { name = "numpy", marker = "python_full_version >= '3.10' and extra == 'dev'", specifier = "~=2.2.0" }, + { name = "numpy", marker = "python_full_version < '3.10' and extra == 'dev'", specifier = "~=2.0" }, { name = "orderly-set", specifier = ">=5.4.1,<6" }, { name = "orjson", marker = "extra == 'dev'", specifier = "~=3.10.0" }, { name = "orjson", marker = "extra == 'optimize'" }, { name = "pandas", marker = "extra == 'dev'", specifier = "~=2.2.0" }, { name = "polars", marker = "extra == 'dev'", specifier = "~=1.21.0" }, { name = "pydantic", marker = "extra == 'static'", specifier = "~=2.10.0" }, - { name = "pydantic", marker = "extra == 'test'", specifier = "~=2.10.0" }, { name = "pytest", marker = "extra == 'test'", specifier = "~=8.3.0" }, { name = "pytest-benchmark", marker = "extra == 'test'", specifier = "~=5.1.0" }, { name = "pytest-cov", marker = "extra == 'test'", specifier = "~=6.0.0" }, { name = "python-dateutil", marker = "extra == 'dev'", specifier = "~=2.9.0" }, { name = "python-dotenv", marker = "extra == 'test'", specifier = "~=1.0.0" }, - { name = "pytz", marker = "extra == 'test'", specifier = "~=2025.2" }, { name = "pyyaml", marker = "extra == 'cli'", specifier = "~=6.0.0" }, { name = "sphinx", marker = "extra == 'docs'", specifier = "~=6.2.0" }, { name = "sphinx-sitemap", marker = "extra == 'docs'", specifier = "~=2.6.0" }, @@ -359,7 +352,6 @@ requires-dist = [ { name = "tomli", marker = "extra == 'dev'", specifier = "~=2.2.0" }, { name = "tomli-w", marker = "extra == 'dev'", specifier = "~=1.2.0" }, { name = "uuid6", marker = "extra == 'dev'", specifier = "==2025.0.1" }, - { name = "uuid6", marker = "extra == 'test'", specifier = "~=2025.0.1" }, ] provides-extras = ["coverage", "cli", "dev", "docs", "static", "test", "optimize"]