Skip to content

Commit ec3f332

Browse files
committed
Merge branch 'master' into dev
2 parents f240a58 + 724938d commit ec3f332

20 files changed

+222
-169
lines changed

setup.cfg renamed to .bumpversion.cfg

+1-8
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,7 @@ commit = True
44
tag = True
55
tag_name = {new_version}
66

7-
[flake8]
8-
max-line-length = 120
9-
builtins = json
10-
statistics = true
11-
ignore = E202
12-
exclude = ./data,./src,.svn,CVS,.bzr,.hg,.git,__pycache__
13-
14-
[bumpversion:file:setup.py]
7+
[bumpversion:file:pyproject.toml]
158

169
[bumpversion:file:README.md]
1710

.github/workflows/main.yaml

+11-33
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ on:
88

99
jobs:
1010
build:
11-
11+
env:
12+
DEFAULT_PYTHON: 3.12
1213
runs-on: ubuntu-latest
1314
strategy:
1415
matrix:
15-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
16+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
1617
architecture: ["x64"]
1718
steps:
1819
- uses: actions/checkout@v2
@@ -21,59 +22,36 @@ jobs:
2122
with:
2223
python-version: ${{ matrix.python-version }}
2324
architecture: ${{ matrix.architecture }}
24-
- name: Cache pip 3.8
25-
if: matrix.python-version == 3.8
26-
uses: actions/cache@v4
27-
with:
28-
# This path is specific to Ubuntu
29-
path: ~/.cache/pip
30-
# Look to see if there is a cache hit for the corresponding requirements file
31-
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements-dev3.8.txt') }}
32-
restore-keys: |
33-
${{ runner.os }}-pip-
34-
${{ runner.os }}-
3525
- name: Cache pip
36-
if: matrix.python-version != 3.8
3726
env:
3827
PYO3_USE_ABI3_FORWARD_COMPATIBILITY: "1"
3928
uses: actions/cache@v4
4029
with:
41-
# This path is specific to Ubuntu
42-
path: ~/.cache/pip
43-
# Look to see if there is a cache hit for the corresponding requirements file
44-
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements-dev.txt') }}
4530
restore-keys: |
46-
${{ runner.os }}-pip-
4731
${{ runner.os }}-
4832
- name: Upgrade setuptools
4933
if: matrix.python-version >= 3.12
5034
run: |
5135
# workaround for 3.12, SEE: https://github.com/pypa/setuptools/issues/3661#issuecomment-1813845177
5236
pip install --upgrade setuptools
53-
- name: Install dependencies
54-
if: matrix.python-version > 3.9
55-
run: pip install -r requirements-dev.txt
56-
- name: Install dependencies
57-
if: matrix.python-version <= 3.9
58-
run: pip install -r requirements-dev3.8.txt
5937
- name: Lint with flake8
60-
if: matrix.python-version == 3.12
38+
if: matrix.python-version == ${{ env.DEFAULT_PYTHON }}
6139
run: |
6240
# stop the build if there are Python syntax errors or undefined names
63-
flake8 deepdiff --count --select=E9,F63,F7,F82 --show-source --statistics
41+
nox -e flake8 -- deepdiff --count --select=E9,F63,F7,F82 --show-source --statistics
6442
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
65-
flake8 deepdiff --count --exit-zero --max-complexity=26 --max-line-lengt=250 --statistics
43+
nox -e flake8 -- deepdiff --count --exit-zero --max-complexity=26 --max-line-length=250 --statistics
6644
- name: Test with pytest and get the coverage
67-
if: matrix.python-version == 3.12
45+
if: matrix.python-version == ${{ env.DEFAULT_PYTHON }}
6846
run: |
69-
pytest --benchmark-disable --cov-report=xml --cov=deepdiff tests/ --runslow
47+
nox -e pytest -s -- --benchmark-disable --cov-report=xml --cov=deepdiff tests/ --runslow
7048
- name: Test with pytest and no coverage report
71-
if: matrix.python-version != 3.12
49+
if: matrix.python-version != ${{ env.DEFAULT_PYTHON }}
7250
run: |
73-
pytest --benchmark-disable
51+
nox -e pytest -s -- --benchmark-disable tests/
7452
- name: Upload coverage to Codecov
7553
uses: codecov/codecov-action@v4
76-
if: matrix.python-version == 3.12
54+
if: matrix.python-version == ${{ env.DEFAULT_PYTHON }}
7755
env:
7856
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
7957
with:

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
- [Extract](https://zepworks.com/deepdiff/current/extract.html): Extract an item from a nested Python object using its path.
1616
- [commandline](https://zepworks.com/deepdiff/current/commandline.html): Use DeepDiff from commandline.
1717

18-
Tested on Python 3.8+ and PyPy3.
18+
Tested on Python 3.9+ and PyPy3.
1919

2020
- **[Documentation](https://zepworks.com/deepdiff/8.4.2/)**
2121

deepdiff/base.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from typing import Any
21
from deepdiff.helper import strings, numbers, SetOrdered
32

43

deepdiff/delta.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import copy
22
import logging
3-
from typing import List, Dict, IO, Callable, Set, Union, Optional
3+
from typing import List, Dict, IO, Callable, Set, Union, Optional, Any
44
from functools import partial, cmp_to_key
55
from collections.abc import Mapping
66
from copy import deepcopy
@@ -86,6 +86,7 @@ def __init__(
8686
always_include_values: bool=False,
8787
iterable_compare_func_was_used: Optional[bool]=None,
8888
force: bool=False,
89+
fill: Any=not_found,
8990
):
9091
# for pickle deserializer:
9192
if hasattr(deserializer, '__code__') and 'safe_to_import' in set(deserializer.__code__.co_varnames):
@@ -158,6 +159,7 @@ def _deserializer(obj, safe_to_import=None):
158159
self.serializer = serializer
159160
self.deserializer = deserializer
160161
self.force = force
162+
self.fill = fill
161163
if force:
162164
self.get_nested_obj = _get_nested_obj_and_force
163165
else:
@@ -286,6 +288,13 @@ def _simple_set_elem_value(self, obj, path_for_err_reporting, elem=None, value=N
286288
except IndexError:
287289
if elem == len(obj):
288290
obj.append(value)
291+
elif self.fill is not not_found and elem > len(obj):
292+
while len(obj) < elem:
293+
if callable(self.fill):
294+
obj.append(self.fill(obj, value, path_for_err_reporting))
295+
else:
296+
obj.append(self.fill)
297+
obj.append(value)
289298
else:
290299
self._raise_or_log(ELEM_NOT_FOUND_TO_ADD_MSG.format(elem, path_for_err_reporting))
291300
elif action == GETATTR:

deepdiff/serialization.py

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
pydantic_base_model_type,
3333
PydanticBaseModel,
3434
NotPresent,
35-
ipranges,
3635
)
3736
from deepdiff.model import DeltaResult
3837

docs/delta.rst

+4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ force : Boolean, default=False
6868
always_include_values : Boolean, default=False
6969
:ref:`always_include_values_label` is used to make sure the delta objects includes the values that were changed. Sometime Delta tries to be efficient not include the values when it can get away with it. By setting this parameter to True, you ensure that the Delta object will include the values.
7070

71+
fill : Any, default=No Fill
72+
:ref:`delta_fill` This is only relevant if `force` is set. This parameter only applies when force is set and trying to fill an existing array. If the index of the array being applied is larger than the length of the array this value will be used to fill empty spaces of the array to extend it in order to add the new value. If this parameter is not set, the items will get dropped and the array not extended. If this parameter is set with a callable function, it will get called each time a fill item is needed. It will be provided with three arguments: first argument is the array being filled, second argument is the value that is being added to the array, the third argument is the path that is being added.
73+
Example function: `def fill(obj, value, path): return "Camry" if "car" in path else None`
74+
7175

7276
**Returns**
7377

noxfile.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""nox configuration file."""
2+
3+
# ruff: noqa: ANN001, D401
4+
5+
import nox
6+
7+
8+
@nox.session
9+
def flake8(session) -> None:
10+
"""Run flake8."""
11+
posargs = session.posargs if session.posargs else ["deepdiff"]
12+
session.install(".[cli,dev,static]")
13+
session.run(
14+
"python",
15+
"-m",
16+
"flake8",
17+
*posargs,
18+
)
19+
20+
21+
@nox.session
22+
def mypy(session) -> None:
23+
"""Run mypy."""
24+
posargs = session.posargs if session.posargs else ["deepdiff"]
25+
session.install(".[cli,dev,static]")
26+
session.run(
27+
"python",
28+
"-m",
29+
"mypy",
30+
"--install-types",
31+
"--non-interactive",
32+
*posargs,
33+
)
34+
35+
36+
@nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13"])
37+
def pytest(session) -> None:
38+
"""Test with pytest."""
39+
posargs = session.posargs if session.posargs else ["-vv", "tests"]
40+
session.install(".[cli,dev,static,test]")
41+
session.run(
42+
"python",
43+
"-m",
44+
"pytest",
45+
"--cov=deepdiff",
46+
"--cov-report",
47+
"term-missing",
48+
*posargs,
49+
)

pyproject.toml

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
[build-system]
2+
requires = ["flit_core >=3.11,<4"]
3+
build-backend = "flit_core.buildapi"
4+
5+
[project]
6+
name = "deepdiff"
7+
version = "8.4.2"
8+
dependencies = [
9+
"orderly-set>=5.3.0,<6",
10+
]
11+
requires-python = ">=3.9"
12+
authors = [
13+
{ name = "Seperman", email = "[email protected]" }
14+
]
15+
maintainers = [
16+
{ name = "Seperman", email = "[email protected]" }
17+
]
18+
description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other."
19+
readme = "README.md"
20+
license = {file = "LICENSE"}
21+
keywords = []
22+
classifiers = [
23+
"Intended Audience :: Developers",
24+
"Operating System :: OS Independent",
25+
"Topic :: Software Development",
26+
"Programming Language :: Python :: 3.9",
27+
"Programming Language :: Python :: 3.10",
28+
"Programming Language :: Python :: 3.11",
29+
"Programming Language :: Python :: 3.12",
30+
"Programming Language :: Python :: 3.13",
31+
"Programming Language :: Python :: Implementation :: PyPy",
32+
"Development Status :: 5 - Production/Stable",
33+
"License :: OSI Approved :: MIT License"
34+
]
35+
36+
# `dependency-groups` would make this a lot cleaner, in theory.
37+
[project.optional-dependencies]
38+
coverage = [
39+
"coverage~=7.6.0"
40+
]
41+
cli = [
42+
"click~=8.1.0",
43+
"pyyaml~=6.0.0"
44+
]
45+
dev = [
46+
"bump2version~=1.0.0",
47+
"jsonpickle~=4.0.0",
48+
"ipdb~=0.13.0",
49+
"numpy~=2.2.0; python_version >= '3.10'",
50+
"numpy~=2.0; python_version < '3.10'",
51+
"python-dateutil~=2.9.0",
52+
"orjson~=3.10.0",
53+
"tomli~=2.2.0",
54+
"tomli-w~=1.2.0",
55+
"pandas~=2.2.0",
56+
"polars~=1.21.0",
57+
]
58+
docs = [
59+
# We use the html style that is not supported in Sphinx 7 anymore.
60+
"Sphinx~=6.2.0",
61+
"sphinx-sitemap~=2.6.0",
62+
"sphinxemoji~=0.3.0"
63+
]
64+
static = [
65+
"flake8~=7.1.0",
66+
"flake8-pyproject~=1.2.3",
67+
"pydantic~=2.10.0",
68+
"types-setuptools~=75.8.0",
69+
]
70+
test = [
71+
"pytest~=8.3.0",
72+
"pytest-benchmark~=5.1.0",
73+
"pytest-cov~=6.0.0",
74+
"python-dotenv~=1.0.0",
75+
]
76+
77+
[project.scripts]
78+
deep = "deepdiff.commands:cli"
79+
80+
[project.urls]
81+
Homepage = "https://zepworks.com/deepdiff/"
82+
Documentation = "https://zepworks.com/deepdiff/"
83+
Repository = "https://github.com/seperman/deepdiff"
84+
Issues = "https://github.com/seperman/deepdiff/issues"
85+
86+
[tool.coverage.run]
87+
branch = true
88+
source = ["."]
89+
90+
[tool.flake8]
91+
max-line-length = 120
92+
builtins = "json"
93+
statistics = true
94+
ignore = "E202"
95+
exclude = "./data,./src,.svn,CVS,.bzr,.hg,.git,__pycache__"
96+
97+
[tool.pytest.ini_options]
98+
addopts = "--pdbcls=IPython.terminal.debugger:Pdb"
99+
100+
[tool.setuptools]
101+
packages = ["deepdiff"]
102+
103+
[tool.setuptools.package-metadata]
104+
deepdiff = ["py.typed"]

pytest.ini

-2
This file was deleted.

requirements-cli.txt

-2
This file was deleted.

requirements-dev.txt

-22
This file was deleted.

requirements-dev3.8.txt

-20
This file was deleted.

requirements-docs.txt

-3
This file was deleted.

requirements-optimize.txt

-1
This file was deleted.

requirements.txt

-1
This file was deleted.

run_tests.sh

-1
This file was deleted.

0 commit comments

Comments
 (0)