nested-mapping 0.11__tar.gz → 0.12.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. nested_mapping-0.12.0/.flake8 +5 -0
  2. nested_mapping-0.12.0/.gitignore +146 -0
  3. nested_mapping-0.12.0/.gitlab-ci.yml +38 -0
  4. nested_mapping-0.12.0/CHANGELOG.md +23 -0
  5. nested_mapping-0.12.0/CONTRIBUTING.md +145 -0
  6. {nested_mapping-0.11 → nested_mapping-0.12.0}/PKG-INFO +8 -11
  7. nested_mapping-0.12.0/README.md +12 -0
  8. nested_mapping-0.12.0/conftest.py +1 -0
  9. {nested_mapping-0.11 → nested_mapping-0.12.0}/pyproject.toml +9 -3
  10. nested_mapping-0.12.0/pytest.ini +4 -0
  11. nested_mapping-0.12.0/src/nested_mapping/__version__.py +24 -0
  12. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/nested_mapping.py +43 -32
  13. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/tools/map.py +2 -2
  14. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/tools/match.py +1 -1
  15. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping.egg-info/PKG-INFO +8 -11
  16. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping.egg-info/SOURCES.txt +10 -0
  17. nested_mapping-0.12.0/src/nested_mapping.egg-info/scm_file_list.json +32 -0
  18. nested_mapping-0.12.0/src/nested_mapping.egg-info/scm_version.json +8 -0
  19. {nested_mapping-0.11 → nested_mapping-0.12.0}/tests/test_nested_mapping.py +43 -18
  20. nested_mapping-0.11/README.md +0 -16
  21. {nested_mapping-0.11 → nested_mapping-0.12.0}/LICENSE +0 -0
  22. {nested_mapping-0.11 → nested_mapping-0.12.0}/setup.cfg +0 -0
  23. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/__init__.py +0 -0
  24. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/class_wrapper.py +0 -0
  25. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/ipython.py +0 -0
  26. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/nested_mapping_access.py +0 -0
  27. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/tools/__init__.py +0 -0
  28. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/tools/filter.py +0 -0
  29. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/tools/reorder_key.py +0 -0
  30. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/typing.py +0 -0
  31. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping/visitor.py +0 -0
  32. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping.egg-info/dependency_links.txt +0 -0
  33. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping.egg-info/requires.txt +0 -0
  34. {nested_mapping-0.11 → nested_mapping-0.12.0}/src/nested_mapping.egg-info/top_level.txt +0 -0
  35. {nested_mapping-0.11 → nested_mapping-0.12.0}/tests/test_filter.py +0 -0
  36. {nested_mapping-0.11 → nested_mapping-0.12.0}/tests/test_map.py +0 -0
  37. {nested_mapping-0.11 → nested_mapping-0.12.0}/tests/test_match.py +0 -0
  38. {nested_mapping-0.11 → nested_mapping-0.12.0}/tests/test_nested_mapping_update.py +0 -0
  39. {nested_mapping-0.11 → nested_mapping-0.12.0}/tests/test_visitor.py +0 -0
@@ -0,0 +1,5 @@
1
+ [flake8]
2
+ extend-ignore = E731, W503
3
+ max-line-length = 100
4
+ max-complexity = 18
5
+ select = B, C, E, F, W
@@ -0,0 +1,146 @@
1
+
2
+ # Created by https://www.toptal.com/developers/gitignore/api/python
3
+ # Edit at https://www.toptal.com/developers/gitignore?templates=python
4
+
5
+ ### Python ###
6
+ # Byte-compiled / optimized / DLL files
7
+ __pycache__/
8
+ *.py[cod]
9
+ *$py.class
10
+ src/nested_mapping/__version__.py
11
+
12
+ # C extensions
13
+ *.so
14
+
15
+ # Distribution / packaging
16
+ .Python
17
+ build/
18
+ develop-eggs/
19
+ dist/
20
+ downloads/
21
+ eggs/
22
+ .eggs/
23
+ lib/
24
+ lib64/
25
+ parts/
26
+ sdist/
27
+ var/
28
+ wheels/
29
+ share/python-wheels/
30
+ *.egg-info/
31
+ .installed.cfg
32
+ *.egg
33
+ MANIFEST
34
+
35
+ # PyInstaller
36
+ # Usually these files are written by a python script from a template
37
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
38
+ *.manifest
39
+ *.spec
40
+
41
+ # Installer logs
42
+ pip-log.txt
43
+ pip-delete-this-directory.txt
44
+
45
+ # Unit test / coverage reports
46
+ htmlcov/
47
+ .tox/
48
+ .nox/
49
+ .coverage
50
+ .coverage.*
51
+ .cache
52
+ nosetests.xml
53
+ coverage.xml
54
+ *.cover
55
+ *.py,cover
56
+ .hypothesis/
57
+ .pytest_cache/
58
+ cover/
59
+
60
+ # Translations
61
+ *.mo
62
+ *.pot
63
+
64
+ # Django stuff:
65
+ *.log
66
+ local_settings.py
67
+ db.sqlite3
68
+ db.sqlite3-journal
69
+
70
+ # Flask stuff:
71
+ instance/
72
+ .webassets-cache
73
+
74
+ # Scrapy stuff:
75
+ .scrapy
76
+
77
+ # Sphinx documentation
78
+ docs/_build/
79
+
80
+ # PyBuilder
81
+ .pybuilder/
82
+ target/
83
+
84
+ # Jupyter Notebook
85
+ .ipynb_checkpoints
86
+
87
+ # IPython
88
+ profile_default/
89
+ ipython_config.py
90
+
91
+ # pyenv
92
+ # For a library or package, you might want to ignore these files since the code is
93
+ # intended to run in multiple environments; otherwise, check them in:
94
+ # .python-version
95
+
96
+ # pipenv
97
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
98
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
99
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
100
+ # install all needed dependencies.
101
+ #Pipfile.lock
102
+
103
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
104
+ __pypackages__/
105
+
106
+ # Celery stuff
107
+ celerybeat-schedule
108
+ celerybeat.pid
109
+
110
+ # SageMath parsed files
111
+ *.sage.py
112
+
113
+ # Environments
114
+ .env
115
+ .venv
116
+ env/
117
+ venv/
118
+ ENV/
119
+ env.bak/
120
+ venv.bak/
121
+
122
+ # Spyder project settings
123
+ .spyderproject
124
+ .spyproject
125
+
126
+ # Rope project settings
127
+ .ropeproject
128
+
129
+ # mkdocs documentation
130
+ /site
131
+
132
+ # mypy
133
+ .mypy_cache/
134
+ .dmypy.json
135
+ dmypy.json
136
+
137
+ # Pyre type checker
138
+ .pyre/
139
+
140
+ # pytype static type analyzer
141
+ .pytype/
142
+
143
+ # Cython debug symbols
144
+ cython_debug/
145
+
146
+ # End of https://www.toptal.com/developers/gitignore/api/python
@@ -0,0 +1,38 @@
1
+ stages:
2
+ - tests
3
+ - publish
4
+
5
+ tests:
6
+ image: 'python:3.12.14-bookworm'
7
+ stage: tests
8
+
9
+ script:
10
+ - python3 -m venv venv
11
+ - source venv/bin/activate
12
+ - pip install --upgrade wheel setuptools pip
13
+ - pip install cython
14
+ - pip install -e ".[test]"
15
+ - coverage run --source=. -m pytest
16
+ - coverage report
17
+ - coverage xml
18
+ coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
19
+ artifacts:
20
+ reports:
21
+ coverage_report:
22
+ coverage_format: cobertura
23
+ path: coverage.xml
24
+ only:
25
+ - master
26
+ - main
27
+ - merge_requests
28
+
29
+ pypi:
30
+ image: 'python:3.12.14-bookworm'
31
+ stage: publish
32
+ script:
33
+ - pip install twine build
34
+ - python -m build
35
+ - twine upload --non-interactive --repository pypi -u ${PYPI_TWINE_USERNAME} -p ${PYPI_TWINE_PASSWORD} dist/*
36
+ rules:
37
+ # Run task only if tag looks like semver
38
+ - if: $CI_COMMIT_TAG =~ /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
@@ -0,0 +1,23 @@
1
+
2
+ # Change Log
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/).
7
+
8
+ ## [0.12.0] - 2026-10-01
9
+
10
+ - add `skip_fcn` argument for `walk*` methods to skip items from iteration.
11
+ - remove support of Python 3.11.
12
+
13
+ ## [0.11.0] - 2025-07-29
14
+
15
+ - First PYPI version.
16
+
17
+ ## [0.10.0] - 2025-07-23
18
+
19
+ - Merge upstream changes.
20
+
21
+ ## [0.9.0] - 2025-04-07
22
+
23
+ - The prerelease version.
@@ -0,0 +1,145 @@
1
+ # Contributing
2
+
3
+ When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other means with the owners of this repository before committing.
4
+
5
+ Please note that we have a code of conduct, please follow it in all your interactions with the project.
6
+
7
+ ## The Pull Request Process
8
+
9
+ 1. Ensure that the new functionality does not conflict with existing features, is comprehensively tested, sufficiently documented, and that all temporary files have been removed.
10
+
11
+ 2. Update CHANGELOG.md and README.md with details of the changes. Increment the version numbers in all necessary files to the new version that this pull request will represent. We use the [SemVer](http://semver.org/) versioning scheme.
12
+
13
+ 3. You can merge the pull request once you have approval from two other developers, or if you don't have permission to do so, you can ask the second reviewer to merge it for you.
14
+
15
+ # Contributor Covenant Code of Conduct
16
+
17
+ ## Our Pledge
18
+
19
+ We as members, contributors, and leaders pledge to make participation in our
20
+ community a harassment-free experience for everyone, regardless of age, body
21
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
22
+ identity and expression, level of experience, education, socio-economic status,
23
+ nationality, personal appearance, race, caste, color, religion, or sexual
24
+ identity and orientation.
25
+
26
+ We pledge to act and interact in ways that contribute to an open, welcoming,
27
+ diverse, inclusive, and healthy community.
28
+
29
+ ## Our Standards
30
+
31
+ Examples of behavior that contributes to a positive environment for our
32
+ community include:
33
+
34
+ * Demonstrating empathy and kindness toward other people
35
+ * Being respectful of differing opinions, viewpoints, and experiences
36
+ * Giving and gracefully accepting constructive feedback
37
+ * Accepting responsibility and apologizing to those affected by our mistakes,
38
+ and learning from the experience
39
+ * Focusing on what is best not just for us as individuals, but for the overall
40
+ community
41
+
42
+ Examples of unacceptable behavior include:
43
+
44
+ * The use of sexualized language or imagery, and sexual attention or advances of
45
+ any kind
46
+ * Trolling, insulting or derogatory comments, and personal or political attacks
47
+ * Public or private harassment
48
+ * Publishing others' private information, such as a physical or email address,
49
+ without their explicit permission
50
+ * Other conduct which could reasonably be considered inappropriate in a
51
+ professional setting
52
+
53
+ ## Enforcement Responsibilities
54
+
55
+ Community leaders are responsible for clarifying and enforcing our standards of
56
+ acceptable behavior and will take appropriate and fair corrective action in
57
+ response to any behavior that they deem inappropriate, threatening, offensive,
58
+ or harmful.
59
+
60
+ Community leaders have the right and responsibility to remove, edit, or reject
61
+ comments, commits, code, wiki edits, issues, and other contributions that are
62
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
63
+ decisions when appropriate.
64
+
65
+ ## Scope
66
+
67
+ This Code of Conduct applies within all community spaces, and also applies when
68
+ an individual is officially representing the community in public spaces.
69
+ Examples of representing our community include using an official email address,
70
+ posting via an official social media account, or acting as an appointed
71
+ representative at an online or offline event.
72
+
73
+ ## Enforcement
74
+
75
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
76
+ reported to the community leaders responsible for enforcement via emails.
77
+ All complaints will be reviewed and investigated promptly and fairly.
78
+
79
+ All community leaders are obligated to respect the privacy and security of the
80
+ reporter of any incident.
81
+
82
+ ## Enforcement Guidelines
83
+
84
+ Community leaders will follow these Community Impact Guidelines in determining
85
+ the consequences for any action they deem in violation of this Code of Conduct:
86
+
87
+ ### 1. Correction
88
+
89
+ **Community Impact**: Use of inappropriate language or other behavior deemed
90
+ unprofessional or unwelcome in the community.
91
+
92
+ **Consequence**: A private, written warning from community leaders, providing
93
+ clarity around the nature of the violation and an explanation of why the
94
+ behavior was inappropriate. A public apology may be requested.
95
+
96
+ ### 2. Warning
97
+
98
+ **Community Impact**: A violation through a single incident or series of
99
+ actions.
100
+
101
+ **Consequence**: A warning with consequences for continued behavior. No
102
+ interaction with the people involved, including unsolicited interaction with
103
+ those enforcing the Code of Conduct, for a specified period of time. This
104
+ includes avoiding interactions in community spaces as well as external channels
105
+ like social media. Violating these terms may lead to a temporary or permanent
106
+ ban.
107
+
108
+ ### 3. Temporary Ban
109
+
110
+ **Community Impact**: A serious violation of community standards, including
111
+ sustained inappropriate behavior.
112
+
113
+ **Consequence**: A temporary ban from any sort of interaction or public
114
+ communication with the community for a specified period of time. No public or
115
+ private interaction with the people involved, including unsolicited interaction
116
+ with those enforcing the Code of Conduct, is allowed during this period.
117
+ Violating these terms may lead to a permanent ban.
118
+
119
+ ### 4. Permanent Ban
120
+
121
+ **Community Impact**: Demonstrating a pattern of violation of community
122
+ standards, including sustained inappropriate behavior, harassment of an
123
+ individual, or aggression toward or disparagement of classes of individuals.
124
+
125
+ **Consequence**: A permanent ban from any sort of public interaction within the
126
+ community.
127
+
128
+ ## Attribution
129
+
130
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
131
+ version 2.1, available at
132
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
133
+
134
+ Community Impact Guidelines were inspired by
135
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
136
+
137
+ For answers to common questions about this code of conduct, see the FAQ at
138
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
139
+ [https://www.contributor-covenant.org/translations][translations].
140
+
141
+ [homepage]: https://www.contributor-covenant.org
142
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
143
+ [Mozilla CoC]: https://github.com/mozilla/diversity
144
+ [FAQ]: https://www.contributor-covenant.org/faq
145
+ [translations]: https://www.contributor-covenant.org/translations
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nested-mapping
3
- Version: 0.11
4
- Summary: Package to work with nested dictionaries supporing list/set as keys
3
+ Version: 0.12.0
4
+ Summary: A wrapper and a toolkit for working with nested mappings in Python
5
5
  Author-email: DAGModelling Team <dagflow@jinr.ru>
6
6
  Maintainer-email: DAGModelling Team <dagflow@jinr.ru>
7
7
  License-Expression: MIT
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
14
14
  Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
17
18
  Requires-Python: >=3.11
18
19
  Description-Content-Type: text/markdown
19
20
  License-File: LICENSE
@@ -30,14 +31,10 @@ Dynamic: license-file
30
31
  [![python](https://img.shields.io/badge/python-3.11-purple.svg)](https://www.python.org/)
31
32
  [![pipeline](https://git.jinr.ru/dagflow-team/nested-mapping/badges/master/pipeline.svg)](https://git.jinr.ru/dagflow-team/nested-mapping/commits/master)
32
33
  [![coverage report](https://git.jinr.ru/dagflow-team/nested-mapping/badges/master/coverage.svg)](https://git.jinr.ru/dagflow-team/nested-mapping/-/commits/master)
33
- <!--- Uncomment here after adding docs!
34
- [![pages](https://img.shields.io/badge/pages-link-white.svg)](http://dagflow-team.pages.jinr.ru/nested-mapping)
35
- -->
34
+ [![github](https://img.shields.io/badge/github-public-blue?logo=github)](https://github.com/dagflow-team/nested-mapping)
35
+ [![gitlab](https://img.shields.io/badge/gitlab-dev-blue?logo=gitlab)](https://git.jinr.ru/dagflow-team/nested-mapping)
36
+ [![pypi-release](https://img.shields.io/badge/pypi-release-blue?logo=pypi&logoColor=green)](https://pypi.org/project/nested-mapping)
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
36
38
 
37
- A package to work with nested dictionaries.
39
+ A wrapper and a toolkit for working with nested mappings in Python.
38
40
 
39
- # Repositories
40
-
41
- - Development/CI: https://git.jinr.ru/dagflow-team/nested-mapping
42
- - Contact/pypi/mirror: https://github.com/dagflow-team/nested-mapping
43
- - PYPI: https://pypi.org/project/nested-mapping
@@ -0,0 +1,12 @@
1
+ # Summary
2
+
3
+ [![python](https://img.shields.io/badge/python-3.11-purple.svg)](https://www.python.org/)
4
+ [![pipeline](https://git.jinr.ru/dagflow-team/nested-mapping/badges/master/pipeline.svg)](https://git.jinr.ru/dagflow-team/nested-mapping/commits/master)
5
+ [![coverage report](https://git.jinr.ru/dagflow-team/nested-mapping/badges/master/coverage.svg)](https://git.jinr.ru/dagflow-team/nested-mapping/-/commits/master)
6
+ [![github](https://img.shields.io/badge/github-public-blue?logo=github)](https://github.com/dagflow-team/nested-mapping)
7
+ [![gitlab](https://img.shields.io/badge/gitlab-dev-blue?logo=gitlab)](https://git.jinr.ru/dagflow-team/nested-mapping)
8
+ [![pypi-release](https://img.shields.io/badge/pypi-release-blue?logo=pypi&logoColor=green)](https://pypi.org/project/nested-mapping)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
+
11
+ A wrapper and a toolkit for working with nested mappings in Python.
12
+
@@ -0,0 +1 @@
1
+ # The file is needed in order to setup the CWD
@@ -1,12 +1,11 @@
1
1
  [build-system]
2
2
  build-backend = "setuptools.build_meta"
3
3
 
4
- requires = [ "packaging", "setuptools", "wheel" ]
4
+ requires = [ "packaging", "setuptools", "setuptools-scm", "wheel" ]
5
5
 
6
6
  [project]
7
7
  name = "nested-mapping"
8
- version = "0.11"
9
- description = "Package to work with nested dictionaries supporing list/set as keys"
8
+ description = "A wrapper and a toolkit for working with nested mappings in Python"
10
9
  readme = "README.md"
11
10
  license = "MIT"
12
11
  maintainers = [ { name = "DAGModelling Team", email = "dagflow@jinr.ru" } ]
@@ -17,7 +16,9 @@ classifiers = [
17
16
  "Programming Language :: Python :: 3.11",
18
17
  "Programming Language :: Python :: 3.12",
19
18
  "Programming Language :: Python :: 3.13",
19
+ "Programming Language :: Python :: 3.14",
20
20
  ]
21
+ dynamic = [ "version" ]
21
22
  dependencies = [ "numpy", "ordered-set" ]
22
23
 
23
24
  optional-dependencies.test = [ "coverage", "pytest", "pytest-cov" ]
@@ -33,6 +34,11 @@ exclude = [
33
34
  "tests*",
34
35
  ]
35
36
 
37
+ [tool.setuptools_scm]
38
+ write_to = "src/nested_mapping/__version__.py"
39
+ version_scheme = "no-guess-dev"
40
+ local_scheme = "no-local-version"
41
+
36
42
  [tool.black]
37
43
  line-length = 100
38
44
 
@@ -0,0 +1,4 @@
1
+ [pytest]
2
+ testpaths=tests/
3
+ ; uncomment below to include coverage into default pytest run
4
+ ; addopts= --cov-report term --cov=./ --cov-report xml:cov.xml
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.12.0'
22
+ __version_tuple__ = version_tuple = (0, 12, 0)
23
+
24
+ __commit_id__ = commit_id = 'gd3a44dafb'
@@ -5,9 +5,11 @@ from contextlib import suppress
5
5
  from typing import TYPE_CHECKING
6
6
 
7
7
  if TYPE_CHECKING:
8
- from typing import Any, Self
8
+ from typing import Any, Self, Callable
9
9
  from collections.abc import Generator, Iterable
10
10
 
11
+ from .typing import TupleKey
12
+
11
13
  from .class_wrapper import ClassWrapper
12
14
  from .ipython import repr_pretty
13
15
  from .nested_mapping_access import NestedMappingAccess
@@ -219,9 +221,7 @@ class NestedMapping(ClassWrapper):
219
221
  if rest:
220
222
  sub = self._wrap(sub, parent=self)
221
223
  if self._not_recursive_to_others and not isinstance(sub, NestedMapping):
222
- raise TypeError(
223
- f"Expect non-mapping as value for {key}, got {type(sub).__name__}"
224
- )
224
+ raise TypeError(f"Expect non-mapping as value for {key}, got {type(sub).__name__}")
225
225
 
226
226
  return sub.get(rest, default)
227
227
 
@@ -246,9 +246,7 @@ class NestedMapping(ClassWrapper):
246
246
  if rest:
247
247
  sub = self._wrap(sub, parent=self)
248
248
  if self._not_recursive_to_others and not isinstance(sub, NestedMapping):
249
- raise TypeError(
250
- f"Expect non-mapping as value for {key}, got {type(sub).__name__}"
251
- )
249
+ raise TypeError(f"Expect non-mapping as value for {key}, got {type(sub).__name__}")
252
250
 
253
251
  try:
254
252
  return sub.get_value(rest)
@@ -256,15 +254,11 @@ class NestedMapping(ClassWrapper):
256
254
  failed_rest = getattr(e, "rest", rest)
257
255
  error = KeyError(f"{key}: {failed_rest}")
258
256
  with suppress(RuntimeError):
259
- error.rest = ( # pyright: ignore [reportAttributeAccessIssue]
260
- failed_rest
261
- )
257
+ error.rest = failed_rest # pyright: ignore [reportAttributeAccessIssue]
262
258
  raise error from e
263
259
 
264
260
  if isinstance(sub, (ClassWrapper, self._types)):
265
- raise TypeError(
266
- f"Invalid value type {type(sub)} for key {key}. Expect non-mapping."
267
- )
261
+ raise TypeError(f"Invalid value type {type(sub)} for key {key}. Expect non-mapping.")
268
262
  return sub
269
263
 
270
264
  def get_any(self, key, *, unwrap: bool = False) -> Any:
@@ -446,6 +440,7 @@ class NestedMapping(ClassWrapper):
446
440
  include_dicts: bool = False,
447
441
  appendstartkey: bool = False,
448
442
  maxdepth: int | None = None,
443
+ skip_fcn: Callable[[TupleKey], bool] = lambda _: False,
449
444
  ):
450
445
  v0 = self.get_any(startfromkey)
451
446
  k0 = tuple(self.iterkey(startfromkey))
@@ -457,9 +452,11 @@ class NestedMapping(ClassWrapper):
457
452
 
458
453
  if maxdepth == 0 or not isinstance(v0, self._wrapper_class):
459
454
  if appendstartkey:
460
- yield k0, v0
455
+ if not skip_fcn(k0):
456
+ yield k0, v0
461
457
  else:
462
- yield (), v0
458
+ if not skip_fcn(()):
459
+ yield (), v0
463
460
  return
464
461
 
465
462
  if not appendstartkey:
@@ -470,22 +467,37 @@ class NestedMapping(ClassWrapper):
470
467
  if isinstance(v, self._wrapper_class):
471
468
  if include_dicts:
472
469
  yield k, v
473
- for k1, v1 in v.walkitems(
474
- include_dicts=include_dicts, maxdepth=nextdepth
475
- ):
476
- yield k + k1, v1
470
+ for k1, v1 in v.walkitems(include_dicts=include_dicts, maxdepth=nextdepth):
471
+ k2 = k + k1
472
+ if skip_fcn(k2):
473
+ continue
474
+ yield k2, v1
477
475
  elif not self._not_recursive_to_others and isinstance(v, Mapping):
478
476
  if include_dicts:
479
- yield k, v
477
+ if not skip_fcn(k):
478
+ yield k, v
480
479
  for k1, v1 in v.items():
481
480
  if isinstance(k1, tuple):
482
- yield k + k1, v1
481
+ k2 = k + k1
482
+ if skip_fcn(k2):
483
+ continue
484
+ yield k2, v1
483
485
  else:
484
- yield k + (k1,), v1
486
+ k2 = k + (k1,)
487
+ if skip_fcn(k2):
488
+ continue
489
+ yield k2, v1
485
490
  else:
486
- yield k, v
491
+ if not skip_fcn(k):
492
+ yield k, v
487
493
 
488
- def walkdicts(self, *, yieldself=False, ignorekeys: Sequence = ()):
494
+ def walkdicts(
495
+ self,
496
+ *,
497
+ yieldself=False,
498
+ ignorekeys: Sequence = (),
499
+ skip_fcn: Callable[[TupleKey], bool] = lambda _: False,
500
+ ):
489
501
  for k, v in self.items():
490
502
  if k in ignorekeys:
491
503
  continue
@@ -493,16 +505,17 @@ class NestedMapping(ClassWrapper):
493
505
  if isinstance(v, self._wrapper_class):
494
506
  yieldself = False
495
507
  for k1, v1 in v.walkdicts(yieldself=True, ignorekeys=ignorekeys):
496
- yield k + k1, v1
497
- if yieldself:
508
+ k2 = k + k1
509
+ if skip_fcn(k2):
510
+ continue
511
+ yield k2, v1
512
+ if yieldself and not skip_fcn(()):
498
513
  yield (), self
499
514
 
500
515
  def keysmap(self) -> NestedMapping:
501
516
  """Return a nested dictionary instance with similar structure, but
502
517
  dictionaries are replaced with tuples of their keys."""
503
- return NestedMapping.from_flatdict(
504
- {k: tuple(dct.keys()) for k, dct in self.walkdicts()}
505
- )
518
+ return NestedMapping.from_flatdict({k: tuple(dct.keys()) for k, dct in self.walkdicts()})
506
519
 
507
520
  def unique_key_parts(self) -> set[str]:
508
521
  """Return a set with all the unique set parts."""
@@ -515,9 +528,7 @@ class NestedMapping(ClassWrapper):
515
528
  for k, _ in self.walkitems(*args, **kwargs):
516
529
  yield k
517
530
 
518
- def walkjoinedkeys(
519
- self, *args, sep: str | None = None, **kwargs
520
- ) -> Generator[str, None, None]:
531
+ def walkjoinedkeys(self, *args, sep: str | None = None, **kwargs) -> Generator[str, None, None]:
521
532
  if sep is None:
522
533
  sep = self._sep
523
534
  if sep is None:
@@ -156,11 +156,11 @@ def make_reorder_function(
156
156
  case _:
157
157
  raise ValueError(f"Invalid order specification: {reorder_indices}")
158
158
 
159
- def reorder_indices(key: Sequence):
159
+ def reorder_indices_fcn(key: Sequence):
160
160
  if not allow_skip_items and len(key) != len_from:
161
161
  raise ValueError(
162
162
  f"inconsistent index length: {len(index_order)} vs required {len(key)}"
163
163
  )
164
164
  return key.__class__(key[idx] for idx in index_order)
165
165
 
166
- return reorder_indices
166
+ return reorder_indices_fcn
@@ -46,7 +46,7 @@ def match_keys(
46
46
  return right.issubset(left)
47
47
 
48
48
  else:
49
- raise RuntimeError("Either right_in_left or left_in_right should be True")
49
+ raise RuntimeError("At least on of the flags should be true: right_in_left or left_in_right")
50
50
 
51
51
  skipped_right_keys = []
52
52
  processed_left_keys = set()
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nested-mapping
3
- Version: 0.11
4
- Summary: Package to work with nested dictionaries supporing list/set as keys
3
+ Version: 0.12.0
4
+ Summary: A wrapper and a toolkit for working with nested mappings in Python
5
5
  Author-email: DAGModelling Team <dagflow@jinr.ru>
6
6
  Maintainer-email: DAGModelling Team <dagflow@jinr.ru>
7
7
  License-Expression: MIT
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
14
14
  Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
17
18
  Requires-Python: >=3.11
18
19
  Description-Content-Type: text/markdown
19
20
  License-File: LICENSE
@@ -30,14 +31,10 @@ Dynamic: license-file
30
31
  [![python](https://img.shields.io/badge/python-3.11-purple.svg)](https://www.python.org/)
31
32
  [![pipeline](https://git.jinr.ru/dagflow-team/nested-mapping/badges/master/pipeline.svg)](https://git.jinr.ru/dagflow-team/nested-mapping/commits/master)
32
33
  [![coverage report](https://git.jinr.ru/dagflow-team/nested-mapping/badges/master/coverage.svg)](https://git.jinr.ru/dagflow-team/nested-mapping/-/commits/master)
33
- <!--- Uncomment here after adding docs!
34
- [![pages](https://img.shields.io/badge/pages-link-white.svg)](http://dagflow-team.pages.jinr.ru/nested-mapping)
35
- -->
34
+ [![github](https://img.shields.io/badge/github-public-blue?logo=github)](https://github.com/dagflow-team/nested-mapping)
35
+ [![gitlab](https://img.shields.io/badge/gitlab-dev-blue?logo=gitlab)](https://git.jinr.ru/dagflow-team/nested-mapping)
36
+ [![pypi-release](https://img.shields.io/badge/pypi-release-blue?logo=pypi&logoColor=green)](https://pypi.org/project/nested-mapping)
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
36
38
 
37
- A package to work with nested dictionaries.
39
+ A wrapper and a toolkit for working with nested mappings in Python.
38
40
 
39
- # Repositories
40
-
41
- - Development/CI: https://git.jinr.ru/dagflow-team/nested-mapping
42
- - Contact/pypi/mirror: https://github.com/dagflow-team/nested-mapping
43
- - PYPI: https://pypi.org/project/nested-mapping
@@ -1,7 +1,15 @@
1
+ .flake8
2
+ .gitignore
3
+ .gitlab-ci.yml
4
+ CHANGELOG.md
5
+ CONTRIBUTING.md
1
6
  LICENSE
2
7
  README.md
8
+ conftest.py
3
9
  pyproject.toml
10
+ pytest.ini
4
11
  src/nested_mapping/__init__.py
12
+ src/nested_mapping/__version__.py
5
13
  src/nested_mapping/class_wrapper.py
6
14
  src/nested_mapping/ipython.py
7
15
  src/nested_mapping/nested_mapping.py
@@ -12,6 +20,8 @@ src/nested_mapping.egg-info/PKG-INFO
12
20
  src/nested_mapping.egg-info/SOURCES.txt
13
21
  src/nested_mapping.egg-info/dependency_links.txt
14
22
  src/nested_mapping.egg-info/requires.txt
23
+ src/nested_mapping.egg-info/scm_file_list.json
24
+ src/nested_mapping.egg-info/scm_version.json
15
25
  src/nested_mapping.egg-info/top_level.txt
16
26
  src/nested_mapping/tools/__init__.py
17
27
  src/nested_mapping/tools/filter.py
@@ -0,0 +1,32 @@
1
+ {
2
+ "files": [
3
+ ".flake8",
4
+ ".gitignore",
5
+ ".gitlab-ci.yml",
6
+ "CHANGELOG.md",
7
+ "CONTRIBUTING.md",
8
+ "LICENSE",
9
+ "README.md",
10
+ "conftest.py",
11
+ "pyproject.toml",
12
+ "pytest.ini",
13
+ "src/nested_mapping/__init__.py",
14
+ "src/nested_mapping/class_wrapper.py",
15
+ "src/nested_mapping/ipython.py",
16
+ "src/nested_mapping/nested_mapping.py",
17
+ "src/nested_mapping/nested_mapping_access.py",
18
+ "src/nested_mapping/tools/__init__.py",
19
+ "src/nested_mapping/tools/filter.py",
20
+ "src/nested_mapping/tools/map.py",
21
+ "src/nested_mapping/tools/match.py",
22
+ "src/nested_mapping/tools/reorder_key.py",
23
+ "src/nested_mapping/typing.py",
24
+ "src/nested_mapping/visitor.py",
25
+ "tests/test_filter.py",
26
+ "tests/test_map.py",
27
+ "tests/test_match.py",
28
+ "tests/test_nested_mapping.py",
29
+ "tests/test_nested_mapping_update.py",
30
+ "tests/test_visitor.py"
31
+ ]
32
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.12.0",
3
+ "distance": 0,
4
+ "node": "gd3a44dafbff671eed953cc02a3c6d1c668155314",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-10-01"
8
+ }
@@ -1,6 +1,7 @@
1
1
  from pytest import mark, raises
2
2
 
3
3
  from nested_mapping import NestedMapping, walkitems, walkkeys, walkvalues
4
+ from nested_mapping.typing import TupleKey
4
5
 
5
6
 
6
7
  def test_nested_mapping_01():
@@ -214,9 +215,7 @@ def test_nested_mapping_04_del(sep):
214
215
 
215
216
 
216
217
  def test_nested_mapping_06_inheritance():
217
- dct = dict(
218
- [("a", 1), ("b", 2), ("c", 3), ("d", dict(e=4)), ("f", dict(g=dict(h=5, i=6)))]
219
- )
218
+ dct = dict([("a", 1), ("b", 2), ("c", 3), ("d", dict(e=4)), ("f", dict(g=dict(h=5, i=6)))])
220
219
  dct["z.z.z"] = 0
221
220
 
222
221
  dw = NestedMapping(dct, sep=".")
@@ -345,9 +344,7 @@ def test_nested_mapping_07c_pop():
345
344
 
346
345
 
347
346
  def test_nested_mapping_08_create():
348
- dct = dict(
349
- [("a", 1), ("b", 2), ("c", 3), ("d", dict(e=4)), ("f", dict(g=dict(h=5)))]
350
- )
347
+ dct = dict([("a", 1), ("b", 2), ("c", 3), ("d", dict(e=4)), ("f", dict(g=dict(h=5)))])
351
348
  dct["z.z.z"] = 0
352
349
  dw = NestedMapping(dct, sep=".")
353
350
 
@@ -359,9 +356,7 @@ def test_nested_mapping_08_create():
359
356
 
360
357
 
361
358
  def test_nested_mapping_09_dictcopy():
362
- dct = dict(
363
- [("a", 1), ("b", 2), ("c", 3), ("d", dict(e=4)), ("f", dict(g=dict(h=5)))]
364
- )
359
+ dct = dict([("a", 1), ("b", 2), ("c", 3), ("d", dict(e=4)), ("f", dict(g=dict(h=5)))])
365
360
  dct["z"] = {}
366
361
  dw = NestedMapping(dct, sep=".")
367
362
 
@@ -408,17 +403,51 @@ def test_nested_mapping_09_walkitems():
408
403
  assert wkeys == list(dw.walkjoinedkeys(sep="/"))
409
404
  assert wkeys == list(dws.walkjoinedkeys(sep="/"))
410
405
 
406
+ def skip_fcn1(key: TupleKey) -> bool:
407
+ return key == (
408
+ "c1",
409
+ "i",
410
+ "j",
411
+ "k",
412
+ "l",
413
+ )
414
+
415
+ wkeys = ["a", "b", "c", "d.e", "f.g.h"]
416
+ assert wkeys == list(dw.walkjoinedkeys(skip_fcn=skip_fcn1))
417
+
418
+ def skip_fcn2(key: TupleKey) -> bool:
419
+ return "i" in key or "e" in key or "a" in key
420
+
421
+ wkeys = ["b", "c", "f.g.h"]
422
+ assert wkeys == list(dw.walkjoinedkeys(skip_fcn=skip_fcn2))
423
+
424
+ def skip_fcn3(key: TupleKey) -> bool:
425
+ return len(key) == 1
426
+
427
+ wkeys = ["c1.i.j.k.l", "d.e", "f.g.h"]
428
+ assert wkeys == list(dw.walkjoinedkeys(skip_fcn=skip_fcn3))
429
+
411
430
  wkeys = [tuple(s.split(".")) for s in ("c1.i.j.k", "d", "f.g", "z")]
412
431
  assert wkeys == [k for k, _ in dw.walkdicts()]
413
432
 
414
433
  wkeys = [tuple(s.split(".")) for s in ("c1.i", "d", "f.g")]
415
434
  assert wkeys == [k for k, _ in dw.walkdicts(ignorekeys=("z", "j"))]
416
435
 
436
+ def skip_fcn4(key: TupleKey) -> bool:
437
+ return "i" in key or "e" in key or "a" in key
438
+
439
+ wkeys = [tuple(s.split(".")) for s in ("d", "f.g", "z")]
440
+ assert wkeys == [k for k, _ in dw.walkdicts(skip_fcn=skip_fcn4)]
441
+
442
+ def skip_fcn5(key: TupleKey) -> bool:
443
+ return "i" in key or "d" in key
444
+
445
+ wkeys = [tuple(s.split(".")) for s in ("f.g", "z")]
446
+ assert wkeys == [k for k, _ in dw.walkdicts(skip_fcn=skip_fcn5)]
447
+
417
448
 
418
449
  def test_nested_mapping_09_walk():
419
- dct = dict(
420
- [("a", 1), ("b", 2), ("c", 3), ("d", dict(e=4)), ("f", dict(g=dict(h=5)))]
421
- )
450
+ dct = dict([("a", 1), ("b", 2), ("c", 3), ("d", dict(e=4)), ("f", dict(g=dict(h=5)))])
422
451
  dw = NestedMapping(dct)
423
452
 
424
453
  keys0 = [("a",), ("b",), ("c",), ("d", "e"), ("f", "g", "h")]
@@ -436,16 +465,12 @@ def test_nested_mapping_09_walk():
436
465
 
437
466
  assert [(k, v) for k, v in dw.walkitems("a", appendstartkey=True)] == [(("a",), 1)]
438
467
  assert [(k, v) for k, v in dw.walkitems("a", appendstartkey=False)] == [((), 1)]
439
- assert [(k, v) for k, v in dw.walkitems("d", appendstartkey=True)] == [
440
- (("d", "e"), 4)
441
- ]
468
+ assert [(k, v) for k, v in dw.walkitems("d", appendstartkey=True)] == [(("d", "e"), 4)]
442
469
  assert [(k, v) for k, v in dw.walkitems("d", appendstartkey=False)] == [(("e",), 4)]
443
470
  assert [(k, v) for k, v in dw.walkitems(("f", "g"), appendstartkey=True)] == [
444
471
  (("f", "g", "h"), 5)
445
472
  ]
446
- assert [(k, v) for k, v in dw.walkitems(("f", "g"), appendstartkey=False)] == [
447
- (("h",), 5)
448
- ]
473
+ assert [(k, v) for k, v in dw.walkitems(("f", "g"), appendstartkey=False)] == [(("h",), 5)]
449
474
 
450
475
 
451
476
  def test_nested_mapping_10_iterkey():
@@ -1,16 +0,0 @@
1
- # Summary
2
-
3
- [![python](https://img.shields.io/badge/python-3.11-purple.svg)](https://www.python.org/)
4
- [![pipeline](https://git.jinr.ru/dagflow-team/nested-mapping/badges/master/pipeline.svg)](https://git.jinr.ru/dagflow-team/nested-mapping/commits/master)
5
- [![coverage report](https://git.jinr.ru/dagflow-team/nested-mapping/badges/master/coverage.svg)](https://git.jinr.ru/dagflow-team/nested-mapping/-/commits/master)
6
- <!--- Uncomment here after adding docs!
7
- [![pages](https://img.shields.io/badge/pages-link-white.svg)](http://dagflow-team.pages.jinr.ru/nested-mapping)
8
- -->
9
-
10
- A package to work with nested dictionaries.
11
-
12
- # Repositories
13
-
14
- - Development/CI: https://git.jinr.ru/dagflow-team/nested-mapping
15
- - Contact/pypi/mirror: https://github.com/dagflow-team/nested-mapping
16
- - PYPI: https://pypi.org/project/nested-mapping
File without changes
File without changes