summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-05-31 06:54:53 +0000
committerCoprDistGit <infra@openeuler.org>2023-05-31 06:54:53 +0000
commit87c6915bcdc97421ef3eaa957411b39ed5e0c017 (patch)
treec15451ace47c6b7282d2444ac617983820546c7c
parentbd23735c9ff7162173043f3511aa3bcdcac8a87a (diff)
automatic import of python-dotted-notation
-rw-r--r--.gitignore1
-rw-r--r--python-dotted-notation.spec1053
-rw-r--r--sources1
3 files changed, 1055 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..106f515 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/dotted-notation-0.10.0.tar.gz
diff --git a/python-dotted-notation.spec b/python-dotted-notation.spec
new file mode 100644
index 0000000..caf11bd
--- /dev/null
+++ b/python-dotted-notation.spec
@@ -0,0 +1,1053 @@
+%global _empty_manifest_terminate_build 0
+Name: python-dotted-notation
+Version: 0.10.0
+Release: 1
+Summary: Dotted notation parser with pattern matching
+License: MIT license
+URL: https://github.com/freywaid/dotted
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/7e/f3/9493a7a026fed3bc3f166dca5c625de180088ec8d1e3135f429d00cc8c4a/dotted-notation-0.10.0.tar.gz
+BuildArch: noarch
+
+
+%description
+# Dotted
+
+Sometimes you want to fetch data from a deeply nested data structure. Dotted notation
+helps you do that.
+
+Let's say you have a dictionary containing a dictionary containing a list and you wish
+to fetch the ith value from that nested list.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}}
+ >>> dotted.get(d, 'hi.there[1]')
+ 2
+
+## API
+
+Probably the easiest thing to do is pydoc the api layer.
+
+ $ pydoc dotted.api
+
+### Get
+
+See grammar discussion below about things you can do get data via dotted.
+
+ >>> import dotted
+ >>> dotted.get({'a': {'b': {'c': {'d': 'nested'}}}}, 'a.b.c.d')
+ 'nested'
+
+### Update
+
+Update will mutate the object if it can. It always returns the changed object though. If
+it's not mutable, then get via the return.
+
+ >>> import dotted
+ >>> l = []
+ >>> t = ()
+ >>> dotted.update(l, '[0]', 'hello')
+ ['hello']
+ >>> l
+ ['hello']
+ >>> dotted.update(t, '[0]', 'hello')
+ ('hello',)
+ >>> t
+ ()
+ ```
+#### Update via pattern
+
+You can update all fields that match pattern given by either a wildcard OR regex.
+
+ >>> import dotted
+ >>> d = {'a': 'hello', 'b': {'bye'}}
+ >>> dotted.update(d, '*', 'me')
+ {'a': 'me', 'b': 'me'}
+
+### Remove
+
+You can remove a field or do so only if it matches value. For example,
+
+ >>> import dotted
+ >>> d = {'a': 'hello', 'b': 'bye'}
+ >>> dotted.remove(d, 'b')
+ {'a': 'hello'}
+ >>> dotted.remove(d, 'a', 'bye')
+ {'a': 'hello'}
+
+#### Remove via pattern
+
+Similar to update, all patterns that match will be removed. If you provide a value as
+well, only the matched patterns that also match the value will be removed.
+
+### Match
+
+Use to match a dotted-style pattern to a field. Partial matching is on by default. You
+can match via wildcard OR via regex. Here's a regex example:
+
+ >>> import dotted
+ >>> dotted.match('/a.+/', 'abced.b')
+ 'abced.b'
+ >>> dotted.match('/a.+/', 'abced.b', partial=False)
+
+With the `groups=True` parameter, you'll see how it was matched:
+
+ >>> import dotted
+ >>> match('hello.*', 'hello.there.bye', groups=True)
+ ('hello.there.bye', ('hello', 'there.bye'))
+
+In the above example, `hello` matched to `hello` and `*` matched to `there.bye` (partial
+matching is enabled by default).
+
+### Expand
+
+You may wish to _expand_ all fields that match a pattern in an object.
+
+ >>> import dotted
+ >>> d = {'hello': {'there': [1, 2, 3]}, 'bye': 7}
+ >>> dotted.expand(d, '*')
+ ('hello', 'bye')
+ >>> dotted.expand(d, '*.*')
+ ('hello.there',)
+ >>> dptted.expand(d, '*.*[*]')
+ ('hello.there[0]', 'hello.there[1]', 'hello.there[2]')
+ >>> dotted.expand(d, '*.*[1:]')
+ ('hello.there[1:]',)
+
+## Grammar
+
+Dotted notation looks similar to python. Both _dot_ fields and _bracketed_ fields
+use `keys()` and `__getitem__()` internally. A _dot_ field expects to see a
+dictionary-like object. A _slot_ field is biased towards sequences (like lists, tuples,
+and strs) but can act on dicts as well. Dotted also supports slicing notation as well as
+transforms discussed below.
+
+### Key fields
+
+A key field is expressed as `a` or part of a dotted expression, such as `a.b`. The
+grammar parser is permissive for what can be in a key field. Pretty much any non-reserved
+char will match. Note that key fields will only work on objects that have a `keys()`
+method. Basically, they work with dictionary or dictionary-like objects.
+
+ >>> import dotted
+ >>> dotted.get({'a': {'b': 'hello'}}, 'a.b')
+ 'hello'
+
+If the key field starts with a space or `-`, you should either quote it OR you may use
+a `\` as the first char.
+
+### Bracketed fields
+
+You may also use bracket notation, such as `a[0]` which does a `__getitem__` at key 0.
+The parser prefers numeric types over string types (if you wish to look up a non-numeric
+field using brackets be sure to quote it). Bracketed fields will work with pretty much
+any object that can be looked up via `__getitem__`.
+
+ >>> import dotted
+ >>> dotted.get({'a': ['first', 'second', 'third']}, 'a[0]')
+ 'first'
+ >>> dotted.get({'a': {'b': 'hello'}}, 'a["b"]')
+ 'first'
+
+### Numeric types
+
+The parser will attempt to interpret a field numerically if it can, such as `field.1`
+will interpret the `1` part numerically.
+
+ >>> import dotted
+ >>> dotted.get({'7': 'me', 7: 'you'}, '7')
+ 'you'
+
+### Quoting
+
+Sometimes you need to quote a field which you can do by just putting the field in quotes.
+
+ >>> import dotted
+ >>> dotted.get({'has . in it': 7}, '"has . in it"')
+ 7
+
+### The numericize `#` operator
+
+Non-integer numeric fields may be interpreted incorrectly if they have decimal point. To
+solve, use the numerize operator `#` at the front of a quoted field, such as `#'123.45'`.
+This will coerce to a numeric type (e.g. float).
+
+ >>> import dotted
+ >>> d = {'a': {1.2: 'hello', 1: {2: 'fooled you'}}}
+ >>> dotted.get(d, 'a.1.2')
+ 'fooled you'
+ >>> dotted.get(d, 'a.#"1.2"')
+ 'hello'
+
+### Slicing
+
+Dotted slicing works like python slicing and all that entails.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.get(d, 'hi.there[::2]')
+ [1, 3]
+ >>> dotted.get(d, '*.there[1:]')
+ ([2, 3], [5, 6])
+
+### The append `+` operator
+
+Both bracketed fileds and slices support the '+' operator which refers to the end of
+sequence. You may append an item or slice to the end a sequence.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.update(d, '*.there[+]', 8)
+ {'hi': {'there': [1, 2, 3, 8]}, 'bye': {'there': [4, 5, 6, 8]}}
+ >>> dotted.update(d, '*.there[+:]', [999])
+ {'hi': {'there': [1, 2, 3, 8, 999]}, 'bye': {'there': [4, 5, 6, 8, 999]}}
+
+### The append-unique `+?` operator
+
+If you want to update only _unique_ items to a list, you can use the `?`
+postfix. This will ensure that it's only added once (see match-first below).
+
+ >>> import dotted
+ >>> items = [1, 2]
+ >>> dotted.update(items, '[+?]', 3)
+ [1, 2, 3]
+ >>> dotted.update(items, '[+?]', 3)
+ [1, 2, 3]
+
+### The invert `-` operator
+
+You can invert the meaning of the notation by prefixing a `-`. For example,
+to remove an item using `update`:
+
+ >>> import dotted
+ >>> d = {'a': 'hello', 'b': 'bye'}
+ >>> dotted.update(d, '-b', dotted.ANY)
+ {'a': 'hello'}
+ >>> dotted.remove(d, '-b', 'bye again')
+ {'a': 'hello', 'b': 'bye again'}
+
+## Patterns
+
+You may use dotted for pattern matching. You can match to wildcards or regular
+expressions. You'll note that patterns always return a tuple of matches.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.get(d, '*.there[2]')
+ (3, 6)
+ >>> dotted.get(d, '/h.*/.*')
+ ([1, 2, 3],)
+
+Dotted will return all values that match the pattern(s).
+
+### Wildcards
+
+The wildcard pattern is `*`. It will match anything.
+
+### Regular expressions
+
+The regex pattern is enclosed in slashes: `/regex/`. Note that if the field is a non-str,
+the regex pattern will internally match to its str representation.
+
+### The match-first operatoer
+
+You can also postfix any pattern with a `?`. This will return only
+the first match.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.get(d, '*?.there[2]')
+ (3,)
+
+## Transforms
+
+You can optionally add transforms to the end of dotted notation. These will
+be applied on `get` and `update`. Transforms are separated by the `|` operator
+and multiple may be chained together. Transforms may be parameterized using
+the `:` operator.
+
+ >>> import dotted
+ >>> d = [1, '2', 3]
+ >>> dotted.get(d, '[1]')
+ '2'
+ >>> dotted.get(d, '[1]|int')
+ 2
+ >>> dotted.get(d, '[0]|str:number=%d')
+ 'number=1'
+
+You may register new transforms via either `register` or the `@transform`
+decorator. Look at transforms.py for preregistered.
+
+## Filters
+
+### The key-value filter
+
+You may filter by key-value to narrow your result set. You may use with __key__ or
+__bracketed__ fields. Key-value fields may be disjunctively (OR) specified via the `,`
+delimiter.
+
+A key-value field on __key__ field looks like: `keyfield.key1=value1,key2=value2...`.
+This will return all key-value matches on a subordinate dict-like object. For example,
+
+ >>> d = {
+ ... 'a': {
+ ... 'id': 1,
+ ... 'hello': 'there',
+ ... },
+ ... 'b': {
+ ... 'id': 2,
+ ... 'hello': 'there',
+ ... },
+ ... }
+ >>> dotted.get(d, '*.id=1')
+ ({'id': 1, 'hello': 'there'},)
+ >>> dotted.get(d, '*.id=*')
+ ({'id': 1, 'hello': 'there'}, {'id': 2, 'hello': 'there'})
+
+A key-value field on a __bracketed__ field looks like: `[key1=value1,key2=value2...]`.
+This will return all items in a list that match key-value filter. For example,
+
+ >>> d = {
+ ... 'a': [{'id': 1, 'hello': 'there'}, {'id': 2, 'hello': 'there'}],
+ ... 'b': [{'id': 3, 'hello': 'there'}, {'id': 4, 'hello': 'bye'}],
+ ... }
+ >>> dotted.get(d, 'a[hello="there"][*].id')
+ (1, 2)
+ >>> dotted.get(d, '*[hello="there"][*].id')
+ r == (1, 2, 3)
+
+### The key-value first filter
+
+You can have it match first by appending a `?` to the end of the filter.
+
+ >>> d = {
+ ... 'a': [{'id': 1, 'hello': 'there'}, {'id': 2, 'hello': 'there'}],
+ ... 'b': [{'id': 3, 'hello': 'there'}, {'id': 4, 'hello': 'bye'}],
+ ... }
+ >>> dotted.get(d, 'a[hello="there"?]')
+ return [{'id': 1, 'hello': 'there'}]
+
+### Conjunction vs disjunction
+
+To _conjunctively_ connect filters use the `.` operator. Filters offer the ability to act
+_disjunctively_ as well by using the `,` operator.
+
+For example, given
+`*.key1=value1,key2=value2.key3=value3`. This will filter
+(`key1=value1` OR `key2=value2`) AND `key3=value3`.
+
+Note that this gives you the abilty to have a key filter multiple values, such as:
+`*.key1=value1,key2=value2`.
+
+
+%package -n python3-dotted-notation
+Summary: Dotted notation parser with pattern matching
+Provides: python-dotted-notation
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-dotted-notation
+# Dotted
+
+Sometimes you want to fetch data from a deeply nested data structure. Dotted notation
+helps you do that.
+
+Let's say you have a dictionary containing a dictionary containing a list and you wish
+to fetch the ith value from that nested list.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}}
+ >>> dotted.get(d, 'hi.there[1]')
+ 2
+
+## API
+
+Probably the easiest thing to do is pydoc the api layer.
+
+ $ pydoc dotted.api
+
+### Get
+
+See grammar discussion below about things you can do get data via dotted.
+
+ >>> import dotted
+ >>> dotted.get({'a': {'b': {'c': {'d': 'nested'}}}}, 'a.b.c.d')
+ 'nested'
+
+### Update
+
+Update will mutate the object if it can. It always returns the changed object though. If
+it's not mutable, then get via the return.
+
+ >>> import dotted
+ >>> l = []
+ >>> t = ()
+ >>> dotted.update(l, '[0]', 'hello')
+ ['hello']
+ >>> l
+ ['hello']
+ >>> dotted.update(t, '[0]', 'hello')
+ ('hello',)
+ >>> t
+ ()
+ ```
+#### Update via pattern
+
+You can update all fields that match pattern given by either a wildcard OR regex.
+
+ >>> import dotted
+ >>> d = {'a': 'hello', 'b': {'bye'}}
+ >>> dotted.update(d, '*', 'me')
+ {'a': 'me', 'b': 'me'}
+
+### Remove
+
+You can remove a field or do so only if it matches value. For example,
+
+ >>> import dotted
+ >>> d = {'a': 'hello', 'b': 'bye'}
+ >>> dotted.remove(d, 'b')
+ {'a': 'hello'}
+ >>> dotted.remove(d, 'a', 'bye')
+ {'a': 'hello'}
+
+#### Remove via pattern
+
+Similar to update, all patterns that match will be removed. If you provide a value as
+well, only the matched patterns that also match the value will be removed.
+
+### Match
+
+Use to match a dotted-style pattern to a field. Partial matching is on by default. You
+can match via wildcard OR via regex. Here's a regex example:
+
+ >>> import dotted
+ >>> dotted.match('/a.+/', 'abced.b')
+ 'abced.b'
+ >>> dotted.match('/a.+/', 'abced.b', partial=False)
+
+With the `groups=True` parameter, you'll see how it was matched:
+
+ >>> import dotted
+ >>> match('hello.*', 'hello.there.bye', groups=True)
+ ('hello.there.bye', ('hello', 'there.bye'))
+
+In the above example, `hello` matched to `hello` and `*` matched to `there.bye` (partial
+matching is enabled by default).
+
+### Expand
+
+You may wish to _expand_ all fields that match a pattern in an object.
+
+ >>> import dotted
+ >>> d = {'hello': {'there': [1, 2, 3]}, 'bye': 7}
+ >>> dotted.expand(d, '*')
+ ('hello', 'bye')
+ >>> dotted.expand(d, '*.*')
+ ('hello.there',)
+ >>> dptted.expand(d, '*.*[*]')
+ ('hello.there[0]', 'hello.there[1]', 'hello.there[2]')
+ >>> dotted.expand(d, '*.*[1:]')
+ ('hello.there[1:]',)
+
+## Grammar
+
+Dotted notation looks similar to python. Both _dot_ fields and _bracketed_ fields
+use `keys()` and `__getitem__()` internally. A _dot_ field expects to see a
+dictionary-like object. A _slot_ field is biased towards sequences (like lists, tuples,
+and strs) but can act on dicts as well. Dotted also supports slicing notation as well as
+transforms discussed below.
+
+### Key fields
+
+A key field is expressed as `a` or part of a dotted expression, such as `a.b`. The
+grammar parser is permissive for what can be in a key field. Pretty much any non-reserved
+char will match. Note that key fields will only work on objects that have a `keys()`
+method. Basically, they work with dictionary or dictionary-like objects.
+
+ >>> import dotted
+ >>> dotted.get({'a': {'b': 'hello'}}, 'a.b')
+ 'hello'
+
+If the key field starts with a space or `-`, you should either quote it OR you may use
+a `\` as the first char.
+
+### Bracketed fields
+
+You may also use bracket notation, such as `a[0]` which does a `__getitem__` at key 0.
+The parser prefers numeric types over string types (if you wish to look up a non-numeric
+field using brackets be sure to quote it). Bracketed fields will work with pretty much
+any object that can be looked up via `__getitem__`.
+
+ >>> import dotted
+ >>> dotted.get({'a': ['first', 'second', 'third']}, 'a[0]')
+ 'first'
+ >>> dotted.get({'a': {'b': 'hello'}}, 'a["b"]')
+ 'first'
+
+### Numeric types
+
+The parser will attempt to interpret a field numerically if it can, such as `field.1`
+will interpret the `1` part numerically.
+
+ >>> import dotted
+ >>> dotted.get({'7': 'me', 7: 'you'}, '7')
+ 'you'
+
+### Quoting
+
+Sometimes you need to quote a field which you can do by just putting the field in quotes.
+
+ >>> import dotted
+ >>> dotted.get({'has . in it': 7}, '"has . in it"')
+ 7
+
+### The numericize `#` operator
+
+Non-integer numeric fields may be interpreted incorrectly if they have decimal point. To
+solve, use the numerize operator `#` at the front of a quoted field, such as `#'123.45'`.
+This will coerce to a numeric type (e.g. float).
+
+ >>> import dotted
+ >>> d = {'a': {1.2: 'hello', 1: {2: 'fooled you'}}}
+ >>> dotted.get(d, 'a.1.2')
+ 'fooled you'
+ >>> dotted.get(d, 'a.#"1.2"')
+ 'hello'
+
+### Slicing
+
+Dotted slicing works like python slicing and all that entails.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.get(d, 'hi.there[::2]')
+ [1, 3]
+ >>> dotted.get(d, '*.there[1:]')
+ ([2, 3], [5, 6])
+
+### The append `+` operator
+
+Both bracketed fileds and slices support the '+' operator which refers to the end of
+sequence. You may append an item or slice to the end a sequence.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.update(d, '*.there[+]', 8)
+ {'hi': {'there': [1, 2, 3, 8]}, 'bye': {'there': [4, 5, 6, 8]}}
+ >>> dotted.update(d, '*.there[+:]', [999])
+ {'hi': {'there': [1, 2, 3, 8, 999]}, 'bye': {'there': [4, 5, 6, 8, 999]}}
+
+### The append-unique `+?` operator
+
+If you want to update only _unique_ items to a list, you can use the `?`
+postfix. This will ensure that it's only added once (see match-first below).
+
+ >>> import dotted
+ >>> items = [1, 2]
+ >>> dotted.update(items, '[+?]', 3)
+ [1, 2, 3]
+ >>> dotted.update(items, '[+?]', 3)
+ [1, 2, 3]
+
+### The invert `-` operator
+
+You can invert the meaning of the notation by prefixing a `-`. For example,
+to remove an item using `update`:
+
+ >>> import dotted
+ >>> d = {'a': 'hello', 'b': 'bye'}
+ >>> dotted.update(d, '-b', dotted.ANY)
+ {'a': 'hello'}
+ >>> dotted.remove(d, '-b', 'bye again')
+ {'a': 'hello', 'b': 'bye again'}
+
+## Patterns
+
+You may use dotted for pattern matching. You can match to wildcards or regular
+expressions. You'll note that patterns always return a tuple of matches.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.get(d, '*.there[2]')
+ (3, 6)
+ >>> dotted.get(d, '/h.*/.*')
+ ([1, 2, 3],)
+
+Dotted will return all values that match the pattern(s).
+
+### Wildcards
+
+The wildcard pattern is `*`. It will match anything.
+
+### Regular expressions
+
+The regex pattern is enclosed in slashes: `/regex/`. Note that if the field is a non-str,
+the regex pattern will internally match to its str representation.
+
+### The match-first operatoer
+
+You can also postfix any pattern with a `?`. This will return only
+the first match.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.get(d, '*?.there[2]')
+ (3,)
+
+## Transforms
+
+You can optionally add transforms to the end of dotted notation. These will
+be applied on `get` and `update`. Transforms are separated by the `|` operator
+and multiple may be chained together. Transforms may be parameterized using
+the `:` operator.
+
+ >>> import dotted
+ >>> d = [1, '2', 3]
+ >>> dotted.get(d, '[1]')
+ '2'
+ >>> dotted.get(d, '[1]|int')
+ 2
+ >>> dotted.get(d, '[0]|str:number=%d')
+ 'number=1'
+
+You may register new transforms via either `register` or the `@transform`
+decorator. Look at transforms.py for preregistered.
+
+## Filters
+
+### The key-value filter
+
+You may filter by key-value to narrow your result set. You may use with __key__ or
+__bracketed__ fields. Key-value fields may be disjunctively (OR) specified via the `,`
+delimiter.
+
+A key-value field on __key__ field looks like: `keyfield.key1=value1,key2=value2...`.
+This will return all key-value matches on a subordinate dict-like object. For example,
+
+ >>> d = {
+ ... 'a': {
+ ... 'id': 1,
+ ... 'hello': 'there',
+ ... },
+ ... 'b': {
+ ... 'id': 2,
+ ... 'hello': 'there',
+ ... },
+ ... }
+ >>> dotted.get(d, '*.id=1')
+ ({'id': 1, 'hello': 'there'},)
+ >>> dotted.get(d, '*.id=*')
+ ({'id': 1, 'hello': 'there'}, {'id': 2, 'hello': 'there'})
+
+A key-value field on a __bracketed__ field looks like: `[key1=value1,key2=value2...]`.
+This will return all items in a list that match key-value filter. For example,
+
+ >>> d = {
+ ... 'a': [{'id': 1, 'hello': 'there'}, {'id': 2, 'hello': 'there'}],
+ ... 'b': [{'id': 3, 'hello': 'there'}, {'id': 4, 'hello': 'bye'}],
+ ... }
+ >>> dotted.get(d, 'a[hello="there"][*].id')
+ (1, 2)
+ >>> dotted.get(d, '*[hello="there"][*].id')
+ r == (1, 2, 3)
+
+### The key-value first filter
+
+You can have it match first by appending a `?` to the end of the filter.
+
+ >>> d = {
+ ... 'a': [{'id': 1, 'hello': 'there'}, {'id': 2, 'hello': 'there'}],
+ ... 'b': [{'id': 3, 'hello': 'there'}, {'id': 4, 'hello': 'bye'}],
+ ... }
+ >>> dotted.get(d, 'a[hello="there"?]')
+ return [{'id': 1, 'hello': 'there'}]
+
+### Conjunction vs disjunction
+
+To _conjunctively_ connect filters use the `.` operator. Filters offer the ability to act
+_disjunctively_ as well by using the `,` operator.
+
+For example, given
+`*.key1=value1,key2=value2.key3=value3`. This will filter
+(`key1=value1` OR `key2=value2`) AND `key3=value3`.
+
+Note that this gives you the abilty to have a key filter multiple values, such as:
+`*.key1=value1,key2=value2`.
+
+
+%package help
+Summary: Development documents and examples for dotted-notation
+Provides: python3-dotted-notation-doc
+%description help
+# Dotted
+
+Sometimes you want to fetch data from a deeply nested data structure. Dotted notation
+helps you do that.
+
+Let's say you have a dictionary containing a dictionary containing a list and you wish
+to fetch the ith value from that nested list.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}}
+ >>> dotted.get(d, 'hi.there[1]')
+ 2
+
+## API
+
+Probably the easiest thing to do is pydoc the api layer.
+
+ $ pydoc dotted.api
+
+### Get
+
+See grammar discussion below about things you can do get data via dotted.
+
+ >>> import dotted
+ >>> dotted.get({'a': {'b': {'c': {'d': 'nested'}}}}, 'a.b.c.d')
+ 'nested'
+
+### Update
+
+Update will mutate the object if it can. It always returns the changed object though. If
+it's not mutable, then get via the return.
+
+ >>> import dotted
+ >>> l = []
+ >>> t = ()
+ >>> dotted.update(l, '[0]', 'hello')
+ ['hello']
+ >>> l
+ ['hello']
+ >>> dotted.update(t, '[0]', 'hello')
+ ('hello',)
+ >>> t
+ ()
+ ```
+#### Update via pattern
+
+You can update all fields that match pattern given by either a wildcard OR regex.
+
+ >>> import dotted
+ >>> d = {'a': 'hello', 'b': {'bye'}}
+ >>> dotted.update(d, '*', 'me')
+ {'a': 'me', 'b': 'me'}
+
+### Remove
+
+You can remove a field or do so only if it matches value. For example,
+
+ >>> import dotted
+ >>> d = {'a': 'hello', 'b': 'bye'}
+ >>> dotted.remove(d, 'b')
+ {'a': 'hello'}
+ >>> dotted.remove(d, 'a', 'bye')
+ {'a': 'hello'}
+
+#### Remove via pattern
+
+Similar to update, all patterns that match will be removed. If you provide a value as
+well, only the matched patterns that also match the value will be removed.
+
+### Match
+
+Use to match a dotted-style pattern to a field. Partial matching is on by default. You
+can match via wildcard OR via regex. Here's a regex example:
+
+ >>> import dotted
+ >>> dotted.match('/a.+/', 'abced.b')
+ 'abced.b'
+ >>> dotted.match('/a.+/', 'abced.b', partial=False)
+
+With the `groups=True` parameter, you'll see how it was matched:
+
+ >>> import dotted
+ >>> match('hello.*', 'hello.there.bye', groups=True)
+ ('hello.there.bye', ('hello', 'there.bye'))
+
+In the above example, `hello` matched to `hello` and `*` matched to `there.bye` (partial
+matching is enabled by default).
+
+### Expand
+
+You may wish to _expand_ all fields that match a pattern in an object.
+
+ >>> import dotted
+ >>> d = {'hello': {'there': [1, 2, 3]}, 'bye': 7}
+ >>> dotted.expand(d, '*')
+ ('hello', 'bye')
+ >>> dotted.expand(d, '*.*')
+ ('hello.there',)
+ >>> dptted.expand(d, '*.*[*]')
+ ('hello.there[0]', 'hello.there[1]', 'hello.there[2]')
+ >>> dotted.expand(d, '*.*[1:]')
+ ('hello.there[1:]',)
+
+## Grammar
+
+Dotted notation looks similar to python. Both _dot_ fields and _bracketed_ fields
+use `keys()` and `__getitem__()` internally. A _dot_ field expects to see a
+dictionary-like object. A _slot_ field is biased towards sequences (like lists, tuples,
+and strs) but can act on dicts as well. Dotted also supports slicing notation as well as
+transforms discussed below.
+
+### Key fields
+
+A key field is expressed as `a` or part of a dotted expression, such as `a.b`. The
+grammar parser is permissive for what can be in a key field. Pretty much any non-reserved
+char will match. Note that key fields will only work on objects that have a `keys()`
+method. Basically, they work with dictionary or dictionary-like objects.
+
+ >>> import dotted
+ >>> dotted.get({'a': {'b': 'hello'}}, 'a.b')
+ 'hello'
+
+If the key field starts with a space or `-`, you should either quote it OR you may use
+a `\` as the first char.
+
+### Bracketed fields
+
+You may also use bracket notation, such as `a[0]` which does a `__getitem__` at key 0.
+The parser prefers numeric types over string types (if you wish to look up a non-numeric
+field using brackets be sure to quote it). Bracketed fields will work with pretty much
+any object that can be looked up via `__getitem__`.
+
+ >>> import dotted
+ >>> dotted.get({'a': ['first', 'second', 'third']}, 'a[0]')
+ 'first'
+ >>> dotted.get({'a': {'b': 'hello'}}, 'a["b"]')
+ 'first'
+
+### Numeric types
+
+The parser will attempt to interpret a field numerically if it can, such as `field.1`
+will interpret the `1` part numerically.
+
+ >>> import dotted
+ >>> dotted.get({'7': 'me', 7: 'you'}, '7')
+ 'you'
+
+### Quoting
+
+Sometimes you need to quote a field which you can do by just putting the field in quotes.
+
+ >>> import dotted
+ >>> dotted.get({'has . in it': 7}, '"has . in it"')
+ 7
+
+### The numericize `#` operator
+
+Non-integer numeric fields may be interpreted incorrectly if they have decimal point. To
+solve, use the numerize operator `#` at the front of a quoted field, such as `#'123.45'`.
+This will coerce to a numeric type (e.g. float).
+
+ >>> import dotted
+ >>> d = {'a': {1.2: 'hello', 1: {2: 'fooled you'}}}
+ >>> dotted.get(d, 'a.1.2')
+ 'fooled you'
+ >>> dotted.get(d, 'a.#"1.2"')
+ 'hello'
+
+### Slicing
+
+Dotted slicing works like python slicing and all that entails.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.get(d, 'hi.there[::2]')
+ [1, 3]
+ >>> dotted.get(d, '*.there[1:]')
+ ([2, 3], [5, 6])
+
+### The append `+` operator
+
+Both bracketed fileds and slices support the '+' operator which refers to the end of
+sequence. You may append an item or slice to the end a sequence.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.update(d, '*.there[+]', 8)
+ {'hi': {'there': [1, 2, 3, 8]}, 'bye': {'there': [4, 5, 6, 8]}}
+ >>> dotted.update(d, '*.there[+:]', [999])
+ {'hi': {'there': [1, 2, 3, 8, 999]}, 'bye': {'there': [4, 5, 6, 8, 999]}}
+
+### The append-unique `+?` operator
+
+If you want to update only _unique_ items to a list, you can use the `?`
+postfix. This will ensure that it's only added once (see match-first below).
+
+ >>> import dotted
+ >>> items = [1, 2]
+ >>> dotted.update(items, '[+?]', 3)
+ [1, 2, 3]
+ >>> dotted.update(items, '[+?]', 3)
+ [1, 2, 3]
+
+### The invert `-` operator
+
+You can invert the meaning of the notation by prefixing a `-`. For example,
+to remove an item using `update`:
+
+ >>> import dotted
+ >>> d = {'a': 'hello', 'b': 'bye'}
+ >>> dotted.update(d, '-b', dotted.ANY)
+ {'a': 'hello'}
+ >>> dotted.remove(d, '-b', 'bye again')
+ {'a': 'hello', 'b': 'bye again'}
+
+## Patterns
+
+You may use dotted for pattern matching. You can match to wildcards or regular
+expressions. You'll note that patterns always return a tuple of matches.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.get(d, '*.there[2]')
+ (3, 6)
+ >>> dotted.get(d, '/h.*/.*')
+ ([1, 2, 3],)
+
+Dotted will return all values that match the pattern(s).
+
+### Wildcards
+
+The wildcard pattern is `*`. It will match anything.
+
+### Regular expressions
+
+The regex pattern is enclosed in slashes: `/regex/`. Note that if the field is a non-str,
+the regex pattern will internally match to its str representation.
+
+### The match-first operatoer
+
+You can also postfix any pattern with a `?`. This will return only
+the first match.
+
+ >>> import dotted
+ >>> d = {'hi': {'there': [1, 2, 3]}, 'bye': {'there': [4, 5, 6]}}
+ >>> dotted.get(d, '*?.there[2]')
+ (3,)
+
+## Transforms
+
+You can optionally add transforms to the end of dotted notation. These will
+be applied on `get` and `update`. Transforms are separated by the `|` operator
+and multiple may be chained together. Transforms may be parameterized using
+the `:` operator.
+
+ >>> import dotted
+ >>> d = [1, '2', 3]
+ >>> dotted.get(d, '[1]')
+ '2'
+ >>> dotted.get(d, '[1]|int')
+ 2
+ >>> dotted.get(d, '[0]|str:number=%d')
+ 'number=1'
+
+You may register new transforms via either `register` or the `@transform`
+decorator. Look at transforms.py for preregistered.
+
+## Filters
+
+### The key-value filter
+
+You may filter by key-value to narrow your result set. You may use with __key__ or
+__bracketed__ fields. Key-value fields may be disjunctively (OR) specified via the `,`
+delimiter.
+
+A key-value field on __key__ field looks like: `keyfield.key1=value1,key2=value2...`.
+This will return all key-value matches on a subordinate dict-like object. For example,
+
+ >>> d = {
+ ... 'a': {
+ ... 'id': 1,
+ ... 'hello': 'there',
+ ... },
+ ... 'b': {
+ ... 'id': 2,
+ ... 'hello': 'there',
+ ... },
+ ... }
+ >>> dotted.get(d, '*.id=1')
+ ({'id': 1, 'hello': 'there'},)
+ >>> dotted.get(d, '*.id=*')
+ ({'id': 1, 'hello': 'there'}, {'id': 2, 'hello': 'there'})
+
+A key-value field on a __bracketed__ field looks like: `[key1=value1,key2=value2...]`.
+This will return all items in a list that match key-value filter. For example,
+
+ >>> d = {
+ ... 'a': [{'id': 1, 'hello': 'there'}, {'id': 2, 'hello': 'there'}],
+ ... 'b': [{'id': 3, 'hello': 'there'}, {'id': 4, 'hello': 'bye'}],
+ ... }
+ >>> dotted.get(d, 'a[hello="there"][*].id')
+ (1, 2)
+ >>> dotted.get(d, '*[hello="there"][*].id')
+ r == (1, 2, 3)
+
+### The key-value first filter
+
+You can have it match first by appending a `?` to the end of the filter.
+
+ >>> d = {
+ ... 'a': [{'id': 1, 'hello': 'there'}, {'id': 2, 'hello': 'there'}],
+ ... 'b': [{'id': 3, 'hello': 'there'}, {'id': 4, 'hello': 'bye'}],
+ ... }
+ >>> dotted.get(d, 'a[hello="there"?]')
+ return [{'id': 1, 'hello': 'there'}]
+
+### Conjunction vs disjunction
+
+To _conjunctively_ connect filters use the `.` operator. Filters offer the ability to act
+_disjunctively_ as well by using the `,` operator.
+
+For example, given
+`*.key1=value1,key2=value2.key3=value3`. This will filter
+(`key1=value1` OR `key2=value2`) AND `key3=value3`.
+
+Note that this gives you the abilty to have a key filter multiple values, such as:
+`*.key1=value1,key2=value2`.
+
+
+%prep
+%autosetup -n dotted-notation-0.10.0
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-dotted-notation -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Wed May 31 2023 Python_Bot <Python_Bot@openeuler.org> - 0.10.0-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..bb49c86
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+17bed76accda500ab2775765098f5416 dotted-notation-0.10.0.tar.gz