Skip to content

Commit b52d694

Browse files
committed
feature: update streamson to 6.2 + update streamson binary
* add AllMatcher - matcher which match all paths * shorten for convert strategy * before, after and separator for extract strategy * struct (to analyze JSONs) for trigger strategy
1 parent a835fd1 commit b52d694

6 files changed

Lines changed: 92 additions & 15 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ crate-type = ["cdylib"]
3535

3636
[dependencies]
3737
pyo3 = { version = "~0.11.1", features = ["extension-module"] }
38-
streamson-lib = "~6.0.0"
38+
streamson-lib = "~6.2.0"

src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,14 @@ impl RustMatcher {
6464
),
6565
})
6666
}
67+
68+
/// Create a matcher which will match all paths
69+
#[staticmethod]
70+
pub fn all() -> PyResult<Self> {
71+
Ok(Self {
72+
inner: matcher::Combinator::new(matcher::All),
73+
})
74+
}
6775
}
6876

6977
#[pyproto]

streamson/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from .convert import convert_async, convert_fd, convert_iter # noqa
22
from .extract import extract_async, extract_fd, extract_iter # noqa
33
from .filter import filter_async, filter_fd, filter_iter # noqa
4-
from .matcher import DepthMatcher, Matcher, SimpleMatcher # noqa
4+
from .matcher import AllMatcher, DepthMatcher, Matcher, SimpleMatcher # noqa
55
from .trigger import trigger_async, trigger_fd, trigger_iter # noqa

streamson/__main__.py

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import argparse
2+
import collections
3+
import re
24
import sys
35
import typing
46

@@ -12,13 +14,24 @@ def convert_parser(root_parser):
1214
convert.add_argument("-s", "--simple", help="Match by simple match", required=False, action="append")
1315
convert.add_argument("-d", "--depth", help="Match by depth", required=False, action="append")
1416

15-
convert.add_argument("-r", "--replace", help="Replaces matched part by given string", required=True)
17+
action = convert.add_mutually_exclusive_group(required=True)
18+
action.add_argument("-r", "--replace", help="Replaces matched part by given string")
19+
action.add_argument("-o", "--shorten", help="Shortens matched data", nargs=2, metavar=("MAX_COUNT", "TERMINATOR"))
1620

1721

1822
def extract_parser(root_parser):
1923
extract = root_parser.add_parser("extract", help="Passes only matched parts of JSON")
2024
extract.add_argument("-s", "--simple", help="Match by simple match", required=False, action="append")
2125
extract.add_argument("-d", "--depth", help="Match by depth", required=False, action="append")
26+
extract.add_argument("-b", "--before", help="Will be printed before matched outputs", required=False, default="")
27+
extract.add_argument("-a", "--after", help="Will be printed after matched outputs", required=False, default="")
28+
extract.add_argument(
29+
"-S",
30+
"--separator",
31+
help="Will be printed to separate matched outputs",
32+
required=False,
33+
default="",
34+
)
2235

2336

2437
def filter_parser(root_parser):
@@ -64,16 +77,23 @@ def trigger_parser(root_parser):
6477
default=[],
6578
)
6679

80+
trigger_parser.add_argument(
81+
"-s",
82+
"--struct",
83+
help="Goes through a json and prints JSON structure at the end of processing.",
84+
action="store_true",
85+
)
86+
6787

6888
def filter_strategy(options: argparse.Namespace, input_gen: typing.Generator[bytes, None, None]):
6989
matcher: typing.Optional[streamson.Matcher] = None
70-
for simple in options.simple:
90+
for simple in options.simple or []:
7191
if matcher:
7292
matcher |= streamson.SimpleMatcher(simple)
7393
else:
7494
matcher = streamson.SimpleMatcher(simple)
7595

76-
for depth in options.depth:
96+
for depth in options.depth or []:
7797
if matcher:
7898
matcher |= streamson.DepthMatcher(depth)
7999
else:
@@ -90,44 +110,68 @@ def filter_strategy(options: argparse.Namespace, input_gen: typing.Generator[byt
90110

91111
def extract_strategy(options: argparse.Namespace, input_gen: typing.Generator[bytes, None, None]):
92112
matcher: typing.Optional[streamson.Matcher] = None
93-
for simple in options.simple:
113+
for simple in options.simple or []:
94114
if matcher:
95115
matcher |= streamson.SimpleMatcher(simple)
96116
else:
97117
matcher = streamson.SimpleMatcher(simple)
98118

99-
for depth in options.depth:
119+
for depth in options.depth or []:
100120
if matcher:
101121
matcher |= streamson.DepthMatcher(depth)
102122
else:
103123
matcher = streamson.DepthMatcher(depth)
104124

105125
if matcher:
126+
sys.stdout.write(options.before)
127+
first = True
106128
for _, output in streamson.extract_iter(input_gen, matcher):
129+
if not first:
130+
sys.stdout.write(options.separator)
131+
else:
132+
first = False
107133
sys.stdout.write(output)
134+
sys.stdout.write(options.after)
108135

109136

110137
def convert_strategy(options: argparse.Namespace, input_gen: typing.Generator[bytes, None, None]):
111138
matcher: typing.Optional[streamson.Matcher] = None
112-
for simple in options.simple:
139+
for simple in options.simple or []:
113140
if matcher:
114141
matcher |= streamson.SimpleMatcher(simple)
115142
else:
116143
matcher = streamson.SimpleMatcher(simple)
117144

118-
for depth in options.depth:
145+
for depth in options.depth or []:
119146
if matcher:
120147
matcher |= streamson.DepthMatcher(depth)
121148
else:
122149
matcher = streamson.DepthMatcher(depth)
123150

124-
replace_str = options.replace
151+
if options.shorten:
152+
153+
def shorten(
154+
path: typing.Optional[str], matcher_idx: int, data: typing.Optional[bytes]
155+
) -> typing.Optional[bytes]:
156+
length, end = options.shorten
157+
if data:
158+
return bytes(bytearray(data[: int(length) + 1])) + end.encode()
159+
160+
return None
161+
162+
converter = shorten
163+
164+
elif options.replace:
125165

126-
def replace(path: typing.Optional[str], matcher_idx: int, data: typing.Optional[bytes]) -> typing.Optional[bytes]:
127-
return replace_str.encode()
166+
def replace(
167+
path: typing.Optional[str], matcher_idx: int, data: typing.Optional[bytes]
168+
) -> typing.Optional[bytes]:
169+
return options.replace.encode()
170+
171+
converter = replace
128172

129173
if matcher:
130-
for output in streamson.convert_iter(input_gen, [replace], matcher, False):
174+
for output in streamson.convert_iter(input_gen, [converter], matcher, False):
131175
sys.stdout.write(output)
132176

133177

@@ -192,9 +236,28 @@ def handler(
192236
matcher = make_matcher(matcher_name, matcher_str)
193237
handler_matcher_combinations.append((handler, matcher))
194238

239+
if options.struct:
240+
counter: typing.Counter[str] = collections.Counter()
241+
242+
def handler(
243+
path: typing.Optional[str], matcher_idx: int, data: typing.Optional[bytes]
244+
) -> typing.Optional[bytes]:
245+
246+
key = "<root>" if not path else re.sub(r"\[[0-9\-,]*\]", "[]", path)
247+
counter[key] += 1
248+
return None
249+
250+
matcher = streamson.AllMatcher()
251+
handler_matcher_combinations.append((handler, matcher))
252+
195253
for output in streamson.trigger_iter(input_gen, handler_matcher_combinations, True):
196254
pass
197255

256+
if options.struct:
257+
print("JSON structure:")
258+
for key in sorted(counter):
259+
print(f" {key}: {counter[key]}")
260+
198261

199262
def main():
200263
version = pkg_resources.get_distribution("streamson-python").version

streamson/matcher.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,9 @@ def __init__(self, path: str):
3737
:param: path: which will be used to create a SimpleMatcher
3838
"""
3939
super().__init__(RustMatcher.simple(path))
40+
41+
42+
class AllMatcher(Matcher):
43+
def __init__(self):
44+
"""Matches all paths"""
45+
super().__init__(RustMatcher.all())

0 commit comments

Comments
 (0)