dotted-notation 0.43.2__tar.gz → 0.43.3__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.
- {dotted_notation-0.43.2/dotted_notation.egg-info → dotted_notation-0.43.3}/PKG-INFO +1 -1
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/grammar.py +64 -18
- {dotted_notation-0.43.2 → dotted_notation-0.43.3/dotted_notation.egg-info}/PKG-INFO +1 -1
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/setup.py +1 -1
- dotted_notation-0.43.3/tests/test_numeric.py +199 -0
- dotted_notation-0.43.2/tests/test_numeric.py +0 -103
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/LICENSE +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/README.md +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/__init__.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/__main__.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/access.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/api.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/base.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/cli/__init__.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/cli/_compat.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/cli/formats.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/cli/main.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/containers.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/engine.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/filters.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/groups.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/matchers.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/predicates.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/recursive.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/results.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/sqlize.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/transforms.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/utils.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/utypes.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted/wrappers.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted_notation.egg-info/SOURCES.txt +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted_notation.egg-info/dependency_links.txt +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted_notation.egg-info/entry_points.txt +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted_notation.egg-info/requires.txt +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted_notation.egg-info/top_level.txt +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/setup.cfg +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/__init__.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_api.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_appender.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_assemble.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_attrs.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_bindings.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_cli.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_concat.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_container_filter.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_cut.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_empty.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_filter_keyvalue.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_get.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_guard_transforms.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_invert.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_json_sentinels.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_keys_values.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_match.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_matchable.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_named_subst.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_negation.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_nop.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_opgroup.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_pluck.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_predicates.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_quote_idempotent.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_recursive.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_reference.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_replace.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_slice.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_softcut.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_sqlize.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_strict.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_string_glob.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_subst_escape.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_subst_transforms.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_threading.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_transforms.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_translate.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_type_restriction.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_unpack.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_update.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_update_if.py +0 -0
- {dotted_notation-0.43.2 → dotted_notation-0.43.3}/tests/test_value_guard.py +0 -0
|
@@ -147,8 +147,9 @@ _ccomma = pp.Optional(pp.White()).suppress() + comma + pp.Optional(pp.White()).s
|
|
|
147
147
|
# Forward for recursive container values
|
|
148
148
|
container_value = pp.Forward()
|
|
149
149
|
|
|
150
|
-
# Scalar atoms usable inside containers (same as value atoms minus containers)
|
|
151
|
-
|
|
150
|
+
# Scalar atoms usable inside containers (same as value atoms minus containers).
|
|
151
|
+
# Uses numeric_slot (ppc.number) so floats parse in value position.
|
|
152
|
+
_val_atoms = bytes_literal | string | wildcard | var | regex | numeric_quoted | none | true | false | numeric_extended | numeric_slot
|
|
152
153
|
|
|
153
154
|
# Glob inside containers: ... with optional /regex/ then optional count
|
|
154
155
|
# Regex pattern for glob (unsuppressed slashes handled inline)
|
|
@@ -385,7 +386,7 @@ concrete_value <<= (
|
|
|
385
386
|
value = pp.Forward()
|
|
386
387
|
_value_group_inner = value + OM(_ccomma + value)
|
|
387
388
|
value_group = (S('(') + _value_group_inner + S(')')).set_parse_action(lambda t: [ct.ValueGroup(*t)])
|
|
388
|
-
value <<= value_group | container_value | string_glob | bytes_literal | string | wildcard | var | regex | numeric_quoted | none | true | false | numeric_extended |
|
|
389
|
+
value <<= value_group | container_value | string_glob | bytes_literal | string | wildcard | var | regex | numeric_quoted | none | true | false | numeric_extended | numeric_slot
|
|
389
390
|
# ---------------------------------------------------------------------------
|
|
390
391
|
# Concat: part+part for key construction using Python's native + operator.
|
|
391
392
|
# Each part can carry per-part transforms: part|xform+part|xform
|
|
@@ -859,9 +860,11 @@ rec_dstar = _dstar_body().set_parse_action(
|
|
|
859
860
|
rec_pat = _pat_body().set_parse_action(
|
|
860
861
|
lambda t: _make_recursive(t))
|
|
861
862
|
|
|
862
|
-
|
|
863
|
-
_rec_dstar_guarded_all | _rec_pat_guarded_all |
|
|
863
|
+
recursive_op_nonguarded = (
|
|
864
864
|
rec_dstar_first | rec_dstar | rec_pat_first | rec_pat)
|
|
865
|
+
recursive_op_guarded = (
|
|
866
|
+
_rec_dstar_guarded_all | _rec_pat_guarded_all)
|
|
867
|
+
recursive_op = recursive_op_guarded | recursive_op_nonguarded
|
|
865
868
|
|
|
866
869
|
empty = pp.Empty().set_parse_action(access.Empty)
|
|
867
870
|
|
|
@@ -877,15 +880,23 @@ _dot_keycmd = (dot + keycmd).set_parse_action(lambda t: t[0])
|
|
|
877
880
|
# op_seq_item uses _nop_wrap (defined later); Forward for circular ref
|
|
878
881
|
op_seq_item = pp.Forward() # first item: allows bare (a,b)
|
|
879
882
|
_op_seq_cont = pp.Forward() # continuation: requires explicit ops
|
|
880
|
-
|
|
883
|
+
_op_seq_guarded = pp.Forward() # guarded terminator (resolved below)
|
|
884
|
+
# op_seq: guarded op is always terminal — either the sole op (alt 1), or
|
|
885
|
+
# optionally trailing a non-guarded path (alt 2).
|
|
886
|
+
op_seq = pp.Group(
|
|
887
|
+
_op_seq_guarded
|
|
888
|
+
| (op_seq_item + ZM(_op_seq_cont) + Opt(_op_seq_guarded))
|
|
889
|
+
)
|
|
881
890
|
|
|
882
891
|
# Continuation items (absorbed from former multi grammar):
|
|
883
892
|
# .~ and ~. with grouped expressions — prefix shorthand requires bare keys inside
|
|
884
893
|
_dot_nop_grouped = ((dot + tilde) | (tilde + dot)) + (_inner_grouped_bare_first | _inner_grouped_bare)
|
|
885
894
|
_dot_nop_grouped = _dot_nop_grouped.set_parse_action(lambda t: wrappers.NopWrap(t[-1]))
|
|
886
895
|
_dot_plain_grouped = (dot + (_inner_grouped_bare_first | _inner_grouped_bare)).set_parse_action(lambda t: t[0])
|
|
887
|
-
# .recursive
|
|
888
|
-
|
|
896
|
+
# .recursive (split into guarded / non-guarded)
|
|
897
|
+
_dot_recursive_nonguarded = (dot + recursive_op_nonguarded).set_parse_action(lambda t: t[0])
|
|
898
|
+
_dot_recursive_guarded = (dot + recursive_op_guarded).set_parse_action(lambda t: t[0])
|
|
899
|
+
_dot_recursive = _dot_recursive_guarded | _dot_recursive_nonguarded
|
|
889
900
|
# @(group) — attribute group access: @(a,b) == (@a,@b), prefix requires bare keys
|
|
890
901
|
_at_plain_grouped = (at + (_inner_grouped_bare_first | _inner_grouped_bare)).set_parse_action(
|
|
891
902
|
lambda t: groups.as_attrs_opgroup(t[0])
|
|
@@ -916,28 +927,63 @@ _explicit_nop_inner = (
|
|
|
916
927
|
)
|
|
917
928
|
_explicit_nop_wrap = (tilde + _explicit_nop_inner).set_parse_action(lambda t: wrappers.NopWrap(t[1]))
|
|
918
929
|
|
|
919
|
-
#
|
|
920
|
-
#
|
|
921
|
-
#
|
|
930
|
+
# Guarded variants — terminal within op_seq. After a `=value`, no more ops
|
|
931
|
+
# may follow (guards have no right-side delimiter, so continuations are
|
|
932
|
+
# ambiguous/meaningless — `a=1.b` is not a legal path).
|
|
933
|
+
_op_seq_guarded << (
|
|
934
|
+
_keycmd_guarded_all |
|
|
935
|
+
_dot_keycmd_guarded_nop | _dot_keycmd_guarded_plain |
|
|
936
|
+
_slotcmd_guarded_all |
|
|
937
|
+
recursive_op_guarded |
|
|
938
|
+
_dot_recursive_guarded
|
|
939
|
+
)
|
|
940
|
+
|
|
941
|
+
# Lookahead: a non-guarded continuation must NOT be followed by a guarded
|
|
942
|
+
# suffix (`|transform* + pred_op`). If it is, the whole thing belongs to
|
|
943
|
+
# the trailing `_op_seq_guarded` terminator, not to this continuation.
|
|
944
|
+
# A bare `|transform` (without pred_op) is fine — that's a template-level
|
|
945
|
+
# transform applied after the path resolves.
|
|
946
|
+
_guard_la = pp.NotAny(ZM(pipe + transform) + _pred_op_re)
|
|
947
|
+
|
|
948
|
+
# Continuation items for the ZM middle of op_seq — guarded variants excluded.
|
|
949
|
+
# Items that could be the LHS of a guard get a `_guard_la` lookahead so
|
|
950
|
+
# they don't greedily eat what belongs to the trailing guarded terminator.
|
|
922
951
|
_op_seq_cont_items = (
|
|
923
952
|
_nop_wrap |
|
|
924
953
|
_inner_grouped_explicit_first | _inner_grouped_explicit |
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
_dot_keycmd_nop | _dot_keycmd |
|
|
954
|
+
(recursive_op_nonguarded + _guard_la) |
|
|
955
|
+
(keycmd + _guard_la) |
|
|
956
|
+
_dot_recursive_nonguarded |
|
|
957
|
+
((_dot_keycmd_nop | _dot_keycmd) + _guard_la) |
|
|
930
958
|
_dot_nop_grouped | _dot_plain_grouped |
|
|
931
959
|
_at_nop_grouped | _at_plain_grouped |
|
|
932
960
|
attrcmd |
|
|
933
961
|
slotgroup_first | slotgroup |
|
|
934
|
-
|
|
962
|
+
(slotcmd + _guard_la) |
|
|
935
963
|
slotspecial | slicefilter | slicecmd
|
|
936
964
|
)
|
|
937
965
|
_op_seq_cont << _op_seq_cont_items
|
|
966
|
+
|
|
967
|
+
# First-item items — same set but WITHOUT the lookahead: the first position
|
|
968
|
+
# doesn't need it because alt 1 (_op_seq_guarded) handles sole-guard cases
|
|
969
|
+
# like `first=7` before we fall into this branch.
|
|
970
|
+
_op_seq_first_items = (
|
|
971
|
+
_nop_wrap |
|
|
972
|
+
_inner_grouped_explicit_first | _inner_grouped_explicit |
|
|
973
|
+
recursive_op_nonguarded |
|
|
974
|
+
keycmd |
|
|
975
|
+
_dot_recursive_nonguarded |
|
|
976
|
+
_dot_keycmd_nop | _dot_keycmd |
|
|
977
|
+
_dot_nop_grouped | _dot_plain_grouped |
|
|
978
|
+
_at_nop_grouped | _at_plain_grouped |
|
|
979
|
+
attrcmd |
|
|
980
|
+
slotgroup_first | slotgroup |
|
|
981
|
+
slotcmd |
|
|
982
|
+
slotspecial | slicefilter | slicecmd
|
|
983
|
+
)
|
|
938
984
|
# First item also allows bare grouped expressions — (a,b) with bare keys.
|
|
939
985
|
# This is valid at the start of a path (top-level inference).
|
|
940
|
-
op_seq_item << (inner_grouped_first | inner_grouped |
|
|
986
|
+
op_seq_item << (inner_grouped_first | inner_grouped | _op_seq_first_items)
|
|
941
987
|
|
|
942
988
|
# Precedence tower (atoms are op_seqs)
|
|
943
989
|
inner_atom = op_seq
|
|
@@ -5,7 +5,7 @@ with open("README.md", "rt") as f:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name="dotted_notation",
|
|
8
|
-
version="0.43.
|
|
8
|
+
version="0.43.3",
|
|
9
9
|
author="Frey Waid",
|
|
10
10
|
author_email="logophage1@gmail.com",
|
|
11
11
|
description="Dotted notation for safe nested data traversal with optional chaining, pattern matching, and transforms",
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import dotted
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_numeric_get_key():
|
|
5
|
+
T = {111: {'stuff': 'hi'}}
|
|
6
|
+
|
|
7
|
+
m = dotted.get(T, '111.stuff')
|
|
8
|
+
assert m == 'hi'
|
|
9
|
+
|
|
10
|
+
m = dotted.get(T, '111.0.stuff')
|
|
11
|
+
assert m != 'hi'
|
|
12
|
+
|
|
13
|
+
# 111.0 == 111
|
|
14
|
+
m = dotted.get(T, '#"111.0".stuff')
|
|
15
|
+
assert m == 'hi'
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_numeric_get_slot():
|
|
19
|
+
T = {111: {'stuff': 'hi'}}
|
|
20
|
+
|
|
21
|
+
m = dotted.get(T, '[111].stuff')
|
|
22
|
+
assert m == 'hi'
|
|
23
|
+
|
|
24
|
+
# 111.0 == 111
|
|
25
|
+
m = dotted.get(T, '[111.0].stuff')
|
|
26
|
+
assert m == 'hi'
|
|
27
|
+
|
|
28
|
+
# 111.0 == 111
|
|
29
|
+
m = dotted.get(T, '[#"111.0"].stuff')
|
|
30
|
+
assert m == 'hi'
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_numeric_expand_int():
|
|
34
|
+
T = {111: {'stuff': 'hi'}}
|
|
35
|
+
|
|
36
|
+
m = dotted.expand(T, '*.*')
|
|
37
|
+
assert m == ('111.stuff',)
|
|
38
|
+
|
|
39
|
+
m = dotted.expand(T, '[*].*')
|
|
40
|
+
assert m == ('[111].stuff',)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_numeric_expand_float():
|
|
44
|
+
T = {111.0: {'stuff': 'hi'}}
|
|
45
|
+
|
|
46
|
+
m = dotted.expand(T, '*.*')
|
|
47
|
+
assert m == ("#'111.0'.stuff",)
|
|
48
|
+
|
|
49
|
+
m = dotted.expand(T, '[*].*')
|
|
50
|
+
assert m == ('[111.0].stuff',)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_numeric_update():
|
|
54
|
+
m = dotted.update({}, '07a', 8)
|
|
55
|
+
assert m == {'07a': 8}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Extended numeric literals
|
|
59
|
+
|
|
60
|
+
def test_numeric_extended_scientific():
|
|
61
|
+
lst = list(range(11))
|
|
62
|
+
assert dotted.get(lst, '[1e1]') == 10
|
|
63
|
+
d = {10000000000: 'big'}
|
|
64
|
+
assert dotted.get(d, '1e10') == 'big'
|
|
65
|
+
assert dotted.get(d, '1e+10') == 'big'
|
|
66
|
+
# negative exponent — float key
|
|
67
|
+
d2 = {1e-12: 'tiny'}
|
|
68
|
+
assert dotted.get(d2, '1e-12') == 'tiny'
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_numeric_extended_underscore():
|
|
72
|
+
lst = list(range(1001))
|
|
73
|
+
assert dotted.get(lst, '[1_000]') == 1000
|
|
74
|
+
d = {1000: 'thousand'}
|
|
75
|
+
assert dotted.get(d, '1_000') == 'thousand'
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_numeric_extended_hex():
|
|
79
|
+
lst = list(range(32))
|
|
80
|
+
assert dotted.get(lst, '[0x1F]') == 31
|
|
81
|
+
d = {31: 'hex'}
|
|
82
|
+
assert dotted.get(d, '0x1F') == 'hex'
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_numeric_extended_octal():
|
|
86
|
+
lst = list(range(16))
|
|
87
|
+
assert dotted.get(lst, '[0o17]') == 15
|
|
88
|
+
d = {15: 'octal'}
|
|
89
|
+
assert dotted.get(d, '0o17') == 'octal'
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_numeric_extended_binary():
|
|
93
|
+
lst = list(range(11))
|
|
94
|
+
assert dotted.get(lst, '[0b1010]') == 10
|
|
95
|
+
d = {10: 'binary'}
|
|
96
|
+
assert dotted.get(d, '0b1010') == 'binary'
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_numeric_extended_negative_slot():
|
|
100
|
+
lst = [None] * 5 + ['neg_sci']
|
|
101
|
+
assert dotted.get(lst, '[-1e1]') is None # -10, out of range for len 6
|
|
102
|
+
d = {-100000: 'neg_sci'}
|
|
103
|
+
assert dotted.get(d, '[-1e5]') == 'neg_sci'
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# --- Floats in RHS (value) positions ---
|
|
107
|
+
|
|
108
|
+
def test_rhs_float_guard():
|
|
109
|
+
"""
|
|
110
|
+
a=0.9 parses as a float guard, not (a=0, .9).
|
|
111
|
+
"""
|
|
112
|
+
p = dotted.parse('a=0.9')
|
|
113
|
+
assert dotted.assemble(p) == 'a=0.9'
|
|
114
|
+
assert dotted.get({'a': 0.9}, 'a=0.9') == 0.9
|
|
115
|
+
assert dotted.get({'a': 1}, 'a=0.9') is None
|
|
116
|
+
|
|
117
|
+
def test_rhs_float_dotted_keycmd_guard():
|
|
118
|
+
"""
|
|
119
|
+
a.b=7.1 must parse as (a, b=7.1), not (a, b=7, 1).
|
|
120
|
+
"""
|
|
121
|
+
p = dotted.parse('a.b=7.1')
|
|
122
|
+
assert dotted.assemble(p) == 'a.b=7.1'
|
|
123
|
+
assert dotted.get({'a': {'b': 7.1}}, 'a.b=7.1') == 7.1
|
|
124
|
+
|
|
125
|
+
def test_rhs_float_negative():
|
|
126
|
+
assert dotted.get({'a': -0.9}, 'a=-0.9') == -0.9
|
|
127
|
+
|
|
128
|
+
def test_rhs_float_scientific():
|
|
129
|
+
assert dotted.get({'a': 150.0}, 'a=1.5e2') == 150.0
|
|
130
|
+
|
|
131
|
+
def test_rhs_float_in_filter():
|
|
132
|
+
data = [{'x': 0.9}, {'x': 1.1}]
|
|
133
|
+
assert dotted.get(data, '[x=0.9]') == [{'x': 0.9}]
|
|
134
|
+
|
|
135
|
+
def test_rhs_float_in_slot_guard():
|
|
136
|
+
assert dotted.get([0.1, 0.9, 0.5], '[*]=0.9') == (0.9,)
|
|
137
|
+
|
|
138
|
+
def test_rhs_float_in_container():
|
|
139
|
+
p = dotted.parse('a=[0.1, 0.2]')
|
|
140
|
+
assert dotted.assemble(p) == 'a=[0.1, 0.2]'
|
|
141
|
+
assert dotted.get({'a': [0.1, 0.2]}, 'a=[0.1, 0.2]') == [0.1, 0.2]
|
|
142
|
+
|
|
143
|
+
def test_rhs_float_in_transform_arg():
|
|
144
|
+
"""
|
|
145
|
+
Transform arguments accept floats.
|
|
146
|
+
"""
|
|
147
|
+
assert dotted.get({'a': 0.5}, 'a|round:0') == 0
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# --- Guarded ops are terminal within op_seq ---
|
|
151
|
+
|
|
152
|
+
def test_guard_terminal_keycmd():
|
|
153
|
+
"""
|
|
154
|
+
a=1.b: guard `a=1` cannot have a continuation `.b` after it.
|
|
155
|
+
"""
|
|
156
|
+
import pytest
|
|
157
|
+
from dotted.api import ParseError
|
|
158
|
+
with pytest.raises(ParseError):
|
|
159
|
+
dotted.parse('a=1.b')
|
|
160
|
+
with pytest.raises(ParseError):
|
|
161
|
+
dotted.parse('a=1.0b')
|
|
162
|
+
|
|
163
|
+
def test_guard_terminal_dotted_keycmd():
|
|
164
|
+
"""
|
|
165
|
+
a.b=7.c: guard `b=7` is already terminal; adding `.c` after must fail.
|
|
166
|
+
"""
|
|
167
|
+
import pytest
|
|
168
|
+
from dotted.api import ParseError
|
|
169
|
+
with pytest.raises(ParseError):
|
|
170
|
+
dotted.parse('a.b=7.c')
|
|
171
|
+
|
|
172
|
+
def test_guard_terminal_slot():
|
|
173
|
+
"""
|
|
174
|
+
a[0]=7.b: slot guard `[0]=7` must be terminal.
|
|
175
|
+
"""
|
|
176
|
+
import pytest
|
|
177
|
+
from dotted.api import ParseError
|
|
178
|
+
with pytest.raises(ParseError):
|
|
179
|
+
dotted.parse('a[0]=7.b')
|
|
180
|
+
with pytest.raises(ParseError):
|
|
181
|
+
dotted.parse('[0]=7.a')
|
|
182
|
+
|
|
183
|
+
def test_guard_terminal_recursive_dstar():
|
|
184
|
+
"""
|
|
185
|
+
**=7.a: recursive wildcard guard must be terminal.
|
|
186
|
+
"""
|
|
187
|
+
import pytest
|
|
188
|
+
from dotted.api import ParseError
|
|
189
|
+
with pytest.raises(ParseError):
|
|
190
|
+
dotted.parse('**=7.a')
|
|
191
|
+
|
|
192
|
+
def test_guard_terminal_recursive_pattern():
|
|
193
|
+
"""
|
|
194
|
+
*x=7.a: recursive pattern guard must be terminal.
|
|
195
|
+
"""
|
|
196
|
+
import pytest
|
|
197
|
+
from dotted.api import ParseError
|
|
198
|
+
with pytest.raises(ParseError):
|
|
199
|
+
dotted.parse('*x=7.a')
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import dotted
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def test_numeric_get_key():
|
|
5
|
-
T = {111: {'stuff': 'hi'}}
|
|
6
|
-
|
|
7
|
-
m = dotted.get(T, '111.stuff')
|
|
8
|
-
assert m == 'hi'
|
|
9
|
-
|
|
10
|
-
m = dotted.get(T, '111.0.stuff')
|
|
11
|
-
assert m != 'hi'
|
|
12
|
-
|
|
13
|
-
# 111.0 == 111
|
|
14
|
-
m = dotted.get(T, '#"111.0".stuff')
|
|
15
|
-
assert m == 'hi'
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def test_numeric_get_slot():
|
|
19
|
-
T = {111: {'stuff': 'hi'}}
|
|
20
|
-
|
|
21
|
-
m = dotted.get(T, '[111].stuff')
|
|
22
|
-
assert m == 'hi'
|
|
23
|
-
|
|
24
|
-
# 111.0 == 111
|
|
25
|
-
m = dotted.get(T, '[111.0].stuff')
|
|
26
|
-
assert m == 'hi'
|
|
27
|
-
|
|
28
|
-
# 111.0 == 111
|
|
29
|
-
m = dotted.get(T, '[#"111.0"].stuff')
|
|
30
|
-
assert m == 'hi'
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def test_numeric_expand_int():
|
|
34
|
-
T = {111: {'stuff': 'hi'}}
|
|
35
|
-
|
|
36
|
-
m = dotted.expand(T, '*.*')
|
|
37
|
-
assert m == ('111.stuff',)
|
|
38
|
-
|
|
39
|
-
m = dotted.expand(T, '[*].*')
|
|
40
|
-
assert m == ('[111].stuff',)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def test_numeric_expand_float():
|
|
44
|
-
T = {111.0: {'stuff': 'hi'}}
|
|
45
|
-
|
|
46
|
-
m = dotted.expand(T, '*.*')
|
|
47
|
-
assert m == ("#'111.0'.stuff",)
|
|
48
|
-
|
|
49
|
-
m = dotted.expand(T, '[*].*')
|
|
50
|
-
assert m == ('[111.0].stuff',)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def test_numeric_update():
|
|
54
|
-
m = dotted.update({}, '07a', 8)
|
|
55
|
-
assert m == {'07a': 8}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# Extended numeric literals
|
|
59
|
-
|
|
60
|
-
def test_numeric_extended_scientific():
|
|
61
|
-
lst = list(range(11))
|
|
62
|
-
assert dotted.get(lst, '[1e1]') == 10
|
|
63
|
-
d = {10000000000: 'big'}
|
|
64
|
-
assert dotted.get(d, '1e10') == 'big'
|
|
65
|
-
assert dotted.get(d, '1e+10') == 'big'
|
|
66
|
-
# negative exponent — float key
|
|
67
|
-
d2 = {1e-12: 'tiny'}
|
|
68
|
-
assert dotted.get(d2, '1e-12') == 'tiny'
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def test_numeric_extended_underscore():
|
|
72
|
-
lst = list(range(1001))
|
|
73
|
-
assert dotted.get(lst, '[1_000]') == 1000
|
|
74
|
-
d = {1000: 'thousand'}
|
|
75
|
-
assert dotted.get(d, '1_000') == 'thousand'
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def test_numeric_extended_hex():
|
|
79
|
-
lst = list(range(32))
|
|
80
|
-
assert dotted.get(lst, '[0x1F]') == 31
|
|
81
|
-
d = {31: 'hex'}
|
|
82
|
-
assert dotted.get(d, '0x1F') == 'hex'
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def test_numeric_extended_octal():
|
|
86
|
-
lst = list(range(16))
|
|
87
|
-
assert dotted.get(lst, '[0o17]') == 15
|
|
88
|
-
d = {15: 'octal'}
|
|
89
|
-
assert dotted.get(d, '0o17') == 'octal'
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def test_numeric_extended_binary():
|
|
93
|
-
lst = list(range(11))
|
|
94
|
-
assert dotted.get(lst, '[0b1010]') == 10
|
|
95
|
-
d = {10: 'binary'}
|
|
96
|
-
assert dotted.get(d, '0b1010') == 'binary'
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def test_numeric_extended_negative_slot():
|
|
100
|
-
lst = [None] * 5 + ['neg_sci']
|
|
101
|
-
assert dotted.get(lst, '[-1e1]') is None # -10, out of range for len 6
|
|
102
|
-
d = {-100000: 'neg_sci'}
|
|
103
|
-
assert dotted.get(d, '[-1e5]') == 'neg_sci'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dotted_notation-0.43.2 → dotted_notation-0.43.3}/dotted_notation.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|