python-jack-knife 0.6.0__tar.gz → 0.6.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.
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/PKG-INFO +1 -1
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/common.py +4 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/parser.py +104 -69
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/denorm.py +6 -3
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/move_field.py +9 -10
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/query_pipe.py +1 -1
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/version.py +1 -1
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/PKG-INFO +1 -1
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/LICENSE +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/README.md +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/pyproject.toml +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/setup.cfg +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/__init__.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/base.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/integrations/ddb_sink.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/integrations/postgres_pipe.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/integrations/snowflake_pipe.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/log.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/main.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/man_page.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/__init__.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/factory.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/filter.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/head.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/join.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/let_reduce.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/map.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/progress_pipe.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/remove_field.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/sample.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/select.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/sort.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/tail.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/user_pipe_factory.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/pipes/where.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/progress.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/registry.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/__init__.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/create_sink.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/csv_sink.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/devnull.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/dir_sink.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/expect.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/factory.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/format_sink.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/graph.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/graph_bar_line.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/graph_cumulative.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/graph_hist.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/graph_scatter.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/json_sink.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/s3_sink.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/s3_stream.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/sinks.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/stdout.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/tsv_sink.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sinks/user_sink_factory.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/__init__.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/csv_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/dir_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/factory.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/format_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/inline_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/json_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/lazy_file.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/lazy_file_local.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/lazy_file_s3.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/npy_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/parquet_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/s3_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/source_list.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/sql_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/tsv_source.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/pjk/sources/user_source_factory.py +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/SOURCES.txt +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/dependency_links.txt +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/entry_points.txt +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/requires.txt +0 -0
- {python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/top_level.txt +0 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import sys, shutil, subprocess, contextlib, signal
|
|
5
5
|
import os
|
|
6
|
+
import re
|
|
6
7
|
import yaml
|
|
7
8
|
from pjk.base import TokenError, Integration
|
|
8
9
|
|
|
@@ -156,3 +157,6 @@ class ComponentFactory:
|
|
|
156
157
|
|
|
157
158
|
def create(self, token: str):
|
|
158
159
|
pass
|
|
160
|
+
|
|
161
|
+
def is_valid_field_name(name: str):
|
|
162
|
+
return re.fullmatch(r'^[A-Za-z_][A-Za-z0-9_]*$', name)
|
|
@@ -55,8 +55,20 @@ class OperandStack:
|
|
|
55
55
|
return None
|
|
56
56
|
return self.stack[-1]
|
|
57
57
|
|
|
58
|
+
def clear(self):
|
|
59
|
+
self.stack.clear()
|
|
60
|
+
|
|
58
61
|
def empty(self):
|
|
59
62
|
return len(self.stack) == 0
|
|
63
|
+
|
|
64
|
+
def print(self, toadd):
|
|
65
|
+
print('---------')
|
|
66
|
+
if toadd:
|
|
67
|
+
print(f'{type(toadd).__name__}={id(toadd)}')
|
|
68
|
+
if len(self.stack) == 0:
|
|
69
|
+
print(f'Stack={id(self)} StackEmpty')
|
|
70
|
+
for op in self.stack:
|
|
71
|
+
print(f'Stack={id(self)} {type(op).__name__}={id(op)}')
|
|
60
72
|
|
|
61
73
|
class ExpressionParser:
|
|
62
74
|
def __init__(self, registry: ComponentRegistry):
|
|
@@ -69,6 +81,9 @@ class ExpressionParser:
|
|
|
69
81
|
'pjk <source> [<pipe> ...] <sink>'])
|
|
70
82
|
|
|
71
83
|
source = self.stack.pop()
|
|
84
|
+
if isinstance(source, SubExpression):
|
|
85
|
+
raise TokenError("Poorly formed sub-expression. Begin token '[' without matching 'over' keyword." )
|
|
86
|
+
|
|
72
87
|
if not self.stack.empty():
|
|
73
88
|
raise TokenError.from_list(['A sink can only consume one source.',
|
|
74
89
|
'pjk <source> [<pipe> ...] <sink>'])
|
|
@@ -167,29 +182,38 @@ class StackLoader:
|
|
|
167
182
|
return ReducerAggregatorPipe(top_level_reducers=self.top_level_reducers)
|
|
168
183
|
|
|
169
184
|
def add_operator(self, op, stack: OperandStack):
|
|
185
|
+
#stack.print(op)
|
|
186
|
+
|
|
170
187
|
if not stack.empty() and isinstance(stack.peek(), SubExpression):
|
|
171
|
-
|
|
188
|
+
subexp = stack.peek()
|
|
172
189
|
|
|
173
|
-
if isinstance(op, SubExpressionOver):
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
op.add_source(subexp_begin)
|
|
190
|
+
if isinstance(op, SubExpressionOver) and subexp.recursion_depth() == 0:
|
|
191
|
+
subexp = stack.pop()
|
|
192
|
+
op.add_source(subexp)
|
|
177
193
|
stack.push(op)
|
|
178
194
|
|
|
179
195
|
global stack_level
|
|
180
|
-
|
|
181
|
-
stack_level-=1
|
|
196
|
+
stack_level -=1 # not sure why this can't be handled exclusively by the stack
|
|
182
197
|
return
|
|
198
|
+
|
|
183
199
|
else: # an operator within the subexpression
|
|
184
|
-
|
|
200
|
+
subexp = stack.peek()
|
|
201
|
+
subexp.add_subop(op)
|
|
185
202
|
return
|
|
186
203
|
|
|
204
|
+
if isinstance(op, SubExpressionOver):
|
|
205
|
+
if stack.empty or not isinstance(stack.peek(), SubExpression):
|
|
206
|
+
raise TokenError("Poorly formed sub-expression. 'over' keyword without matching begin token '['.")
|
|
207
|
+
op.add_source(stack.pop())
|
|
208
|
+
stack.push(op)
|
|
209
|
+
|
|
187
210
|
# order matters, because sources are pipes
|
|
188
211
|
if isinstance(op, Pipe):
|
|
189
212
|
arity = op.arity # class level attribute
|
|
190
213
|
for _ in range(arity):
|
|
191
214
|
if stack.empty():
|
|
192
|
-
|
|
215
|
+
name = type(op).usage().name
|
|
216
|
+
raise TokenError(f"'{name}' requires {arity} input(s)")
|
|
193
217
|
op.add_source(stack.pop())
|
|
194
218
|
stack.push(op)
|
|
195
219
|
|
|
@@ -243,6 +267,31 @@ class UpstreamSource(Source):
|
|
|
243
267
|
self.sub_recs_in.increment()
|
|
244
268
|
yield item
|
|
245
269
|
|
|
270
|
+
class SubExpressionOver(Pipe):
|
|
271
|
+
@classmethod
|
|
272
|
+
def usage(cls) -> Usage:
|
|
273
|
+
u = Usage(
|
|
274
|
+
name="over",
|
|
275
|
+
desc="sub-expression over.",
|
|
276
|
+
component_class=cls,
|
|
277
|
+
)
|
|
278
|
+
return u
|
|
279
|
+
|
|
280
|
+
def __init__(self, ptok: ParsedToken, usage: Usage):
|
|
281
|
+
super().__init__(ptok, usage)
|
|
282
|
+
self.over_arg = ptok.get_arg(0)
|
|
283
|
+
|
|
284
|
+
def reset(self):
|
|
285
|
+
pass # stateless
|
|
286
|
+
|
|
287
|
+
def __iter__(self):
|
|
288
|
+
if not isinstance(self.left, SubExpression):
|
|
289
|
+
raise Exception('this actually cannot happen, but did')
|
|
290
|
+
|
|
291
|
+
for record in self.left:
|
|
292
|
+
self.left.subexp_process(record, self.over_arg)
|
|
293
|
+
yield record
|
|
294
|
+
|
|
246
295
|
class SubExpression(Pipe, ProgressIgnore):
|
|
247
296
|
@classmethod
|
|
248
297
|
def create(cls, token: str) -> Pipe:
|
|
@@ -255,28 +304,34 @@ class SubExpression(Pipe, ProgressIgnore):
|
|
|
255
304
|
|
|
256
305
|
def __init__(self, ptok: ParsedToken, usage: Usage):
|
|
257
306
|
super().__init__(ptok)
|
|
258
|
-
self.over_arg = None
|
|
259
|
-
self.over_field = None
|
|
260
307
|
self.subexp_ops = []
|
|
261
|
-
self.over_pipe = None
|
|
262
308
|
self.stack_helper = StackLoader()
|
|
263
309
|
self.subexp_stack = OperandStack()
|
|
264
310
|
self.upstream_source = UpstreamSource()
|
|
265
311
|
self.subexp_stack.push(self.upstream_source)
|
|
312
|
+
self.recursions = 0 # number of subexpression within
|
|
313
|
+
self.subexp_left = None
|
|
266
314
|
|
|
267
315
|
def add_subop(self, op):
|
|
268
316
|
self.subexp_ops.append(op)
|
|
317
|
+
if isinstance(op, SubExpression):
|
|
318
|
+
self.recursions += 1
|
|
319
|
+
elif isinstance(op, SubExpressionOver):
|
|
320
|
+
self.recursions -= 1
|
|
269
321
|
self.stack_helper.add_operator(op, self.subexp_stack)
|
|
270
322
|
|
|
271
|
-
def
|
|
272
|
-
self.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
323
|
+
def recursion_depth(self):
|
|
324
|
+
return self.recursions
|
|
325
|
+
|
|
326
|
+
#def bind(self, subex_over: SubExpressionOver):
|
|
327
|
+
# self.over_arg = subex_over.get_over_arg()
|
|
328
|
+
# if self.over_arg.endswith('.py'):
|
|
329
|
+
# self.over_field = 'child'
|
|
330
|
+
# self.over_pipe = UserPipeFactory.create(self.over_arg)
|
|
331
|
+
# self.upstream_source.set_source(self.over_pipe)
|
|
332
|
+
# self.subexp_ops.append(self.over_pipe)
|
|
333
|
+
# else:
|
|
334
|
+
# self.over_field = self.over_arg
|
|
280
335
|
|
|
281
336
|
def reset(self):
|
|
282
337
|
for op in self.subexp_ops:
|
|
@@ -284,60 +339,40 @@ class SubExpression(Pipe, ProgressIgnore):
|
|
|
284
339
|
op.reset()
|
|
285
340
|
|
|
286
341
|
def __iter__(self):
|
|
287
|
-
|
|
288
|
-
if self.over_pipe:
|
|
289
|
-
one = UpstreamSource()
|
|
290
|
-
one.add_item(record)
|
|
291
|
-
self.over_pipe.set_sources([one])
|
|
292
|
-
else:
|
|
293
|
-
field_data = record.pop(self.over_field, None)
|
|
294
|
-
if not field_data:
|
|
295
|
-
yield record
|
|
296
|
-
continue
|
|
297
|
-
if isinstance(field_data, list):
|
|
298
|
-
self.upstream_source.set_list(field_data)
|
|
299
|
-
else:
|
|
300
|
-
self.upstream_source.set_list([field_data])
|
|
342
|
+
yield from self.left # pass thru to subexp_over which then calls process
|
|
301
343
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
344
|
+
def subexp_process(self, record: dict, over_field: str):
|
|
345
|
+
#for record in self.left:
|
|
346
|
+
# if self.over_pipe:
|
|
347
|
+
# one = UpstreamSource()
|
|
348
|
+
# one.add_item(record)
|
|
349
|
+
# self.over_pipe.set_sources([one])
|
|
305
350
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
for rec in top:
|
|
309
|
-
out_recs.append(rec)
|
|
351
|
+
if not self.subexp_left:
|
|
352
|
+
self.subexp_left = self.subexp_stack.pop()
|
|
310
353
|
|
|
311
|
-
|
|
354
|
+
field_data = record.pop(over_field, None)
|
|
355
|
+
if not field_data:
|
|
356
|
+
return
|
|
312
357
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if name:
|
|
318
|
-
record[name] = value
|
|
358
|
+
if isinstance(field_data, list):
|
|
359
|
+
self.upstream_source.set_list(field_data)
|
|
360
|
+
else:
|
|
361
|
+
self.upstream_source.set_list([field_data])
|
|
319
362
|
|
|
320
|
-
|
|
363
|
+
# Reset sub-pipe stack
|
|
364
|
+
for op in self.subexp_ops:
|
|
365
|
+
op.reset()
|
|
321
366
|
|
|
322
|
-
|
|
323
|
-
@classmethod
|
|
324
|
-
def usage(cls) -> Usage:
|
|
325
|
-
u = Usage(
|
|
326
|
-
name="over",
|
|
327
|
-
desc="sub-expression over.",
|
|
328
|
-
component_class=cls,
|
|
329
|
-
)
|
|
330
|
-
return u
|
|
331
|
-
|
|
332
|
-
def __init__(self, ptok: ParsedToken, usage: Usage):
|
|
333
|
-
super().__init__(ptok, usage)
|
|
334
|
-
self.over_arg = ptok.get_arg(0)
|
|
367
|
+
out_recs = []
|
|
335
368
|
|
|
336
|
-
|
|
337
|
-
|
|
369
|
+
for rec in self.subexp_left:
|
|
370
|
+
out_recs.append(rec)
|
|
338
371
|
|
|
339
|
-
|
|
340
|
-
pass # stateless
|
|
372
|
+
record[over_field] = out_recs
|
|
341
373
|
|
|
342
|
-
|
|
343
|
-
|
|
374
|
+
for op in self.subexp_ops:
|
|
375
|
+
if isinstance(op, ReducePipe):
|
|
376
|
+
name, value = op.get_subexp_result()
|
|
377
|
+
if name:
|
|
378
|
+
record[name] = value
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
from pjk.base import Pipe, ParsedToken, Usage, UsageError
|
|
7
7
|
from typing import Iterator
|
|
8
|
+
from pjk.progress import papi
|
|
8
9
|
|
|
9
10
|
class Denormer:
|
|
10
11
|
def __init__(self, record, field):
|
|
@@ -23,7 +24,7 @@ class Denormer:
|
|
|
23
24
|
elif isinstance(data, dict):
|
|
24
25
|
self.subrec_list = [data]
|
|
25
26
|
else:
|
|
26
|
-
raise UsageError("can only
|
|
27
|
+
raise UsageError("can only explode sub-records")
|
|
27
28
|
|
|
28
29
|
def __iter__(self) -> Iterator[dict]:
|
|
29
30
|
for subrec in self.subrec_list:
|
|
@@ -53,8 +54,8 @@ class DenormPipe(Pipe):
|
|
|
53
54
|
super().__init__(ptok)
|
|
54
55
|
|
|
55
56
|
self.field = usage.get_arg('field')
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
self.recs_in = papi.get_counter(self, None) # don't display
|
|
58
|
+
self.recs_out = papi.get_percentage_counter(self, 'recs_out', self.recs_in)
|
|
58
59
|
|
|
59
60
|
self._pending_iter = None
|
|
60
61
|
|
|
@@ -63,6 +64,8 @@ class DenormPipe(Pipe):
|
|
|
63
64
|
|
|
64
65
|
def __iter__(self):
|
|
65
66
|
for record in self.left:
|
|
67
|
+
self.recs_in.increment()
|
|
66
68
|
denormer = Denormer(record, self.field)
|
|
67
69
|
for out in denormer:
|
|
70
|
+
self.recs_out.increment()
|
|
68
71
|
yield out
|
|
@@ -3,34 +3,33 @@
|
|
|
3
3
|
|
|
4
4
|
# djk/pipes/move_field.py
|
|
5
5
|
|
|
6
|
-
from pjk.base import Pipe, ParsedToken, Usage
|
|
6
|
+
from pjk.base import Pipe, ParsedToken, Usage, TokenError
|
|
7
|
+
from pjk.common import is_valid_field_name
|
|
7
8
|
|
|
8
9
|
class MoveField(Pipe):
|
|
9
10
|
@classmethod
|
|
10
11
|
def usage(cls):
|
|
11
|
-
|
|
12
|
+
u = Usage(
|
|
12
13
|
name='as',
|
|
13
14
|
desc='rename a field in the record',
|
|
14
15
|
component_class=cls
|
|
15
16
|
)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
u.def_arg(name='src', usage='Source field name')
|
|
18
|
+
u.def_arg(name='dst', usage='Destination field name')
|
|
19
|
+
u.def_example(expr_tokens=['{up:1}', 'as:up:down'], expect="{down:1}")
|
|
19
20
|
|
|
20
|
-
return
|
|
21
|
+
return u
|
|
21
22
|
|
|
22
23
|
def __init__(self, ptok: ParsedToken, usage: Usage):
|
|
23
24
|
super().__init__(ptok, usage)
|
|
24
25
|
self.src = usage.get_arg('src')
|
|
25
26
|
self.dst = usage.get_arg('dst')
|
|
26
|
-
self.count = 0
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
if not is_valid_field_name(self.dst) or not is_valid_field_name(self.src):
|
|
29
|
+
raise TokenError('field names only allow letters, numbers (non-initially) and underbar')
|
|
30
30
|
|
|
31
31
|
def __iter__(self):
|
|
32
32
|
for record in self.left:
|
|
33
|
-
self.count += 1
|
|
34
33
|
if self.src in record:
|
|
35
34
|
record[self.dst] = record.pop(self.src)
|
|
36
35
|
yield record
|
|
@@ -18,7 +18,7 @@ class QueryPipe(Pipe):
|
|
|
18
18
|
desc=cls.desc,
|
|
19
19
|
component_class=cls
|
|
20
20
|
)
|
|
21
|
-
u.def_arg(name=cls.arg0[0], usage=f
|
|
21
|
+
u.def_arg(name=cls.arg0[0], usage=f"{cls.arg0[1]} ~/.pjk/lookups.yaml must contain entry '{cls.__name__}-<{cls.arg0[0]}'>\n with necessary parameters.")
|
|
22
22
|
u.def_param("query_field", usage="field of query.", default="query")
|
|
23
23
|
u.def_param("count", usage="Number of search results, (databases may ignore)", is_num=True, default="10")
|
|
24
24
|
u.def_param("shape", usage='the shape of ouput records', is_num=False,
|
|
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
|
|
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
|
{python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/requires.txt
RENAMED
|
File without changes
|
{python_jack_knife-0.6.0 → python_jack_knife-0.6.2}/src/python_jack_knife.egg-info/top_level.txt
RENAMED
|
File without changes
|