dotted-notation 0.51.1__tar.gz → 0.51.2__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 (48) hide show
  1. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/CHANGELOG.md +13 -0
  2. {dotted_notation-0.51.1/dotted_notation.egg-info → dotted_notation-0.51.2}/PKG-INFO +12 -1
  3. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/README.md +11 -0
  4. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/__init__.py +2 -2
  5. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/api.py +43 -1
  6. {dotted_notation-0.51.1 → dotted_notation-0.51.2/dotted_notation.egg-info}/PKG-INFO +12 -1
  7. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/pyproject.toml +1 -1
  8. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/LICENSE +0 -0
  9. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/MANIFEST.in +0 -0
  10. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/__main__.py +0 -0
  11. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/access.pxd +0 -0
  12. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/access.py +0 -0
  13. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/base.pxd +0 -0
  14. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/base.py +0 -0
  15. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/cli/__init__.py +0 -0
  16. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/cli/_compat.py +0 -0
  17. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/cli/formats.py +0 -0
  18. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/cli/main.py +0 -0
  19. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/containers.py +0 -0
  20. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/engine.pxd +0 -0
  21. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/engine.py +0 -0
  22. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/filters.pxd +0 -0
  23. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/filters.py +0 -0
  24. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/grammar.py +0 -0
  25. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/groups.pxd +0 -0
  26. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/groups.py +0 -0
  27. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/matchers.pxd +0 -0
  28. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/matchers.py +0 -0
  29. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/native.py +0 -0
  30. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/predicates.py +0 -0
  31. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/recursive.pxd +0 -0
  32. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/recursive.py +0 -0
  33. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/results.py +0 -0
  34. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/sql/__init__.py +0 -0
  35. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/sql/core.py +0 -0
  36. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/sql/pg.py +0 -0
  37. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/transforms.py +0 -0
  38. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/utils.py +0 -0
  39. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/utypes.py +0 -0
  40. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/wrappers.pxd +0 -0
  41. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted/wrappers.py +0 -0
  42. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted_notation.egg-info/SOURCES.txt +0 -0
  43. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted_notation.egg-info/dependency_links.txt +0 -0
  44. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted_notation.egg-info/entry_points.txt +0 -0
  45. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted_notation.egg-info/requires.txt +0 -0
  46. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/dotted_notation.egg-info/top_level.txt +0 -0
  47. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/setup.cfg +0 -0
  48. {dotted_notation-0.51.1 → dotted_notation-0.51.2}/setup.py +0 -0
@@ -3,6 +3,19 @@
3
3
  All notable changes to `dotted` are recorded here. Versions prior to
4
4
  the ones listed are omitted — browse git history for earlier entries.
5
5
 
6
+ ## [0.51.2]
7
+
8
+ ### Added
9
+ - `getter(path, ...)`: a read of `path` as a callable `obj -> value`,
10
+ returning what `get(obj, path, ...)` would, with the parse, the
11
+ resolver's `lex`, `fold` and `literals` and the fast-path decision
12
+ settled once when it is made, so repeated reads skip `get`'s setup.
13
+
14
+ ### Fixed
15
+ - On `get`'s fast path, a resolver answering a reference in a trailing
16
+ transform's argument saw `settings.strict` as `False` whatever the
17
+ call's `strict`.
18
+
6
19
  ## [0.51.1]
7
20
 
8
21
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dotted_notation
3
- Version: 0.51.1
3
+ Version: 0.51.2
4
4
  Summary: Dotted notation for safe nested data traversal with optional chaining, pattern matching, and transforms
5
5
  Author-email: Frey Waid <logophage1@gmail.com>
6
6
  License-Expression: MIT
@@ -437,6 +437,17 @@ Get the value at a dotted path. See the Paths, Patterns, and Operators sections
437
437
  >>> dotted.get({'a': {'b': {'c': {'d': 'nested'}}}}, 'a.b.c.d')
438
438
  'nested'
439
439
 
440
+ A path read many times can be made into a **getter** once: a callable
441
+ `obj -> value` that returns what `get` would, with the parse, the resolver's
442
+ hooks and the fast-path decision settled when it is made, against the
443
+ resolver in force then. It takes `get`'s arguments, the object aside.
444
+
445
+ >>> d_of = dotted.getter('a.b.c.d', default='none')
446
+ >>> d_of({'a': {'b': {'c': {'d': 'nested'}}}})
447
+ 'nested'
448
+ >>> d_of({})
449
+ 'none'
450
+
440
451
  <a id="update"></a>
441
452
  ### Update
442
453
 
@@ -389,6 +389,17 @@ Get the value at a dotted path. See the Paths, Patterns, and Operators sections
389
389
  >>> dotted.get({'a': {'b': {'c': {'d': 'nested'}}}}, 'a.b.c.d')
390
390
  'nested'
391
391
 
392
+ A path read many times can be made into a **getter** once: a callable
393
+ `obj -> value` that returns what `get` would, with the parse, the resolver's
394
+ hooks and the fast-path decision settled when it is made, against the
395
+ resolver in force then. It takes `get`'s arguments, the object aside.
396
+
397
+ >>> d_of = dotted.getter('a.b.c.d', default='none')
398
+ >>> d_of({'a': {'b': {'c': {'d': 'nested'}}}})
399
+ 'nested'
400
+ >>> d_of({})
401
+ 'none'
402
+
392
403
  <a id="update"></a>
393
404
  ### Update
394
405
 
@@ -71,7 +71,7 @@ from .api import \
71
71
  expand, expand_multi, \
72
72
  match, match_multi, replace, overlaps, translate, translate_multi, \
73
73
  apply, apply_multi, \
74
- get, get_multi, \
74
+ get, get_multi, getter, \
75
75
  has, setdefault, setdefault_multi, \
76
76
  update, update_multi, pack, update_if, update_if_multi, \
77
77
  remove, remove_multi, remove_if, remove_if_multi, \
@@ -82,7 +82,7 @@ from .base import Resolver as ReferenceResolver, UnresolvedReference
82
82
 
83
83
  __all__ = [
84
84
  # Core
85
- 'get', 'update', 'remove', 'has', 'setdefault',
85
+ 'get', 'getter', 'update', 'remove', 'has', 'setdefault',
86
86
  'ReferenceResolver', 'UnresolvedReference', 'set_resolver', 'get_resolver',
87
87
  # Multi
88
88
  'get_multi', 'update_multi', 'pack', 'update_if', 'update_if_multi', 'remove_multi', 'remove_if', 'remove_if_multi', 'setdefault_multi',
@@ -511,8 +511,25 @@ def get(obj, path, default=None, pattern_default=(), apply_transforms=True, stri
511
511
  >>> get({'a': {'b': 7, 'c': 3}}, '**=7')
512
512
  (7,)
513
513
  """
514
+ ops, chain = _get_setup(path, bindings, resolver)
515
+ return _get_read(obj, ops, chain, default, pattern_default, apply_transforms, strict, resolver)
516
+
517
+
518
+ def _get_setup(path, bindings, resolver):
519
+ """
520
+ What a read of path settles before it sees an object: the parsed path,
521
+ with its resolver's lex and fold, and the fast path's chain, None when
522
+ the read takes the full traversal.
523
+ """
514
524
  ops = _prepare(parse(path, bindings=bindings, partial=False, resolver=resolver), resolver)
515
525
  chain = ops.simple_chain if _SIMPLE_FASTPATH and not _literals(resolver) else None
526
+ return ops, chain
527
+
528
+
529
+ def _get_read(obj, ops, chain, default, pattern_default, apply_transforms, strict, resolver):
530
+ """
531
+ A read of obj through ops, set up by _get_setup.
532
+ """
516
533
  if chain is not None:
517
534
  val = engine.simple_get(chain, obj, strict=strict)
518
535
  if val is not engine.SIMPLE_BAIL:
@@ -521,7 +538,7 @@ def get(obj, path, default=None, pattern_default=(), apply_transforms=True, stri
521
538
  if not (apply_transforms and ops.transforms):
522
539
  return val
523
540
  try:
524
- return ops.apply(val, base.Settings(obj, resolver=resolver))
541
+ return ops.apply(val, base.Settings(obj, strict, resolver=resolver))
525
542
  except base.UnresolvedReference:
526
543
  return default
527
544
  found = tuple(engine.values(ops, obj, strict=strict, resolver=resolver, transforms=apply_transforms))
@@ -530,6 +547,31 @@ def get(obj, path, default=None, pattern_default=(), apply_transforms=True, stri
530
547
  return found if found else pattern_default
531
548
 
532
549
 
550
+ def getter(path, default=None, pattern_default=(), apply_transforms=True, strict=False, bindings=None, resolver=None):
551
+ """
552
+ A read of path as a callable obj -> value, as get(obj, path, ...)
553
+ returns it. The parse, the resolver's lex, fold and literals and the
554
+ fast-path decision are settled once, here, against the resolver in
555
+ force now, so a call is the read and nothing else.
556
+
557
+ >>> first = getter('hello.there[0]')
558
+ >>> first({'hello': {'there': [1, 2]}})
559
+ 1
560
+ >>> getter('[*].a')([{'a': 1}, {'a': 2}])
561
+ (1, 2)
562
+ """
563
+ r = base.RESOLVER if resolver is None else resolver
564
+ ops, chain = _get_setup(path, bindings, r)
565
+
566
+ def read(obj):
567
+ """
568
+ obj read through the getter's path.
569
+ """
570
+ return _get_read(obj, ops, chain, default, pattern_default, apply_transforms, strict, r)
571
+
572
+ return read
573
+
574
+
533
575
  def get_multi(obj, iterable, apply_transforms=True, strict=False, bindings=None, resolver=None):
534
576
  """
535
577
  Get all values from obj in iterable; return iterable
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dotted_notation
3
- Version: 0.51.1
3
+ Version: 0.51.2
4
4
  Summary: Dotted notation for safe nested data traversal with optional chaining, pattern matching, and transforms
5
5
  Author-email: Frey Waid <logophage1@gmail.com>
6
6
  License-Expression: MIT
@@ -437,6 +437,17 @@ Get the value at a dotted path. See the Paths, Patterns, and Operators sections
437
437
  >>> dotted.get({'a': {'b': {'c': {'d': 'nested'}}}}, 'a.b.c.d')
438
438
  'nested'
439
439
 
440
+ A path read many times can be made into a **getter** once: a callable
441
+ `obj -> value` that returns what `get` would, with the parse, the resolver's
442
+ hooks and the fast-path decision settled when it is made, against the
443
+ resolver in force then. It takes `get`'s arguments, the object aside.
444
+
445
+ >>> d_of = dotted.getter('a.b.c.d', default='none')
446
+ >>> d_of({'a': {'b': {'c': {'d': 'nested'}}}})
447
+ 'nested'
448
+ >>> d_of({})
449
+ 'none'
450
+
440
451
  <a id="update"></a>
441
452
  ### Update
442
453
 
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "dotted_notation"
9
- version = "0.51.1"
9
+ version = "0.51.2"
10
10
  description = "Dotted notation for safe nested data traversal with optional chaining, pattern matching, and transforms"
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.6"