python-jack-knife 0.7.0__tar.gz → 0.7.1__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 (84) hide show
  1. {python_jack_knife-0.7.0/src/python_jack_knife.egg-info → python_jack_knife-0.7.1}/PKG-INFO +1 -1
  2. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/history.py +3 -0
  3. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/integrations/postgres_pipe.py +12 -3
  4. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/factory.py +1 -1
  5. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/select.py +2 -2
  6. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/graph_bar_line.py +11 -9
  7. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/npy_source.py +3 -4
  8. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/version.py +1 -1
  9. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1/src/python_jack_knife.egg-info}/PKG-INFO +1 -1
  10. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/LICENSE +0 -0
  11. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/README.md +0 -0
  12. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/pyproject.toml +0 -0
  13. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/setup.cfg +0 -0
  14. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/__init__.py +0 -0
  15. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/common.py +0 -0
  16. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/components.py +0 -0
  17. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/integrations/opensearch_client.py +0 -0
  18. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/integrations/opensearch_index_sink.py +0 -0
  19. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/integrations/opensearch_query_pipe.py +0 -0
  20. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/integrations/snowflake_pipe.py +0 -0
  21. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/log.py +0 -0
  22. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/main.py +0 -0
  23. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/man_page.py +0 -0
  24. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/parser.py +0 -0
  25. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/__init__.py +0 -0
  26. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/denorm.py +0 -0
  27. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/filter.py +0 -0
  28. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/head.py +0 -0
  29. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/join.py +0 -0
  30. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/let_reduce.py +0 -0
  31. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/map.py +0 -0
  32. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/move_field.py +0 -0
  33. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/progress_pipe.py +0 -0
  34. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/query_pipe.py +0 -0
  35. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/remove_field.py +0 -0
  36. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/sample.py +0 -0
  37. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/sort.py +0 -0
  38. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/tail.py +0 -0
  39. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/user_pipe_factory.py +0 -0
  40. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/pipes/where.py +0 -0
  41. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/progress.py +0 -0
  42. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/registry.py +0 -0
  43. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/__init__.py +0 -0
  44. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/create_sink.py +0 -0
  45. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/csv_sink.py +0 -0
  46. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/devnull.py +0 -0
  47. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/dir_sink.py +0 -0
  48. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/expect.py +0 -0
  49. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/factory.py +0 -0
  50. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/format_sink.py +0 -0
  51. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/graph.py +0 -0
  52. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/graph_cumulative.py +0 -0
  53. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/graph_hist.py +0 -0
  54. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/graph_scatter.py +0 -0
  55. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/json_sink.py +0 -0
  56. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/s3_sink.py +0 -0
  57. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/s3_stream.py +0 -0
  58. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/sinks.py +0 -0
  59. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/stdout.py +0 -0
  60. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/tsv_sink.py +0 -0
  61. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sinks/user_sink_factory.py +0 -0
  62. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/__init__.py +0 -0
  63. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/csv_source.py +0 -0
  64. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/dir_source.py +0 -0
  65. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/factory.py +0 -0
  66. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/favorite_source.py +0 -0
  67. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/format_source.py +0 -0
  68. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/inline_source.py +0 -0
  69. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/json_source.py +0 -0
  70. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/lazy_file.py +0 -0
  71. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/lazy_file_local.py +0 -0
  72. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/lazy_file_s3.py +0 -0
  73. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/parquet_source.py +0 -0
  74. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/s3_source.py +0 -0
  75. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/source_list.py +0 -0
  76. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/sql_source.py +0 -0
  77. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/tsv_source.py +0 -0
  78. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/sources/user_source_factory.py +0 -0
  79. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/pjk/usage.py +0 -0
  80. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/python_jack_knife.egg-info/SOURCES.txt +0 -0
  81. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/python_jack_knife.egg-info/dependency_links.txt +0 -0
  82. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/python_jack_knife.egg-info/entry_points.txt +0 -0
  83. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/python_jack_knife.egg-info/requires.txt +0 -0
  84. {python_jack_knife-0.7.0 → python_jack_knife-0.7.1}/src/python_jack_knife.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-jack-knife
3
- Version: 0.7.0
3
+ Version: 0.7.1
4
4
  Summary: Python Jack Knife – a command line data processor
5
5
  Author-email: Mike Schultz <mike.schultz@gmail.com>
6
6
  License:
@@ -30,6 +30,9 @@ def read_history(log_path: str) -> List[int]:
30
30
  if not line:
31
31
  continue
32
32
 
33
+ if 'pjk ' in line: # legacy
34
+ line = line.split('pjk ', 1)[1]
35
+
33
36
  # Expected format: <command_string>
34
37
  line = line.strip()
35
38
 
@@ -35,9 +35,12 @@ class DBClient:
35
35
  self.conn = DBClient._connection
36
36
 
37
37
  def close(self):
38
+ import pg8000 # lazy
38
39
  if self.conn is not None:
39
40
  try:
40
41
  self.conn.close()
42
+ except pg8000.exceptions.InterfaceError:
43
+ pass
41
44
  finally:
42
45
  DBClient._connection = None
43
46
 
@@ -123,10 +126,15 @@ class PostgresPipe(QueryPipe,Integration):
123
126
 
124
127
  self.params_field = "params" # optional: list/tuple (positional) or dict (named)
125
128
 
129
+ self.client = None
130
+
126
131
  def reset(self):
127
132
  # stateless across reset
128
133
  pass
129
134
 
135
+ def close(self):
136
+ self.client.close()
137
+
130
138
  def _make_header(self, cur, query: str, params=None) -> Dict[str, Any]:
131
139
  """
132
140
  Inspect the cursor and build a full header record.
@@ -155,7 +163,7 @@ class PostgresPipe(QueryPipe,Integration):
155
163
  return h
156
164
 
157
165
  def execute_query_returning_S_xO_iterable(self, record):
158
- client = DBClient(
166
+ self.client = DBClient(
159
167
  host=self.db_host,
160
168
  username=self.db_user,
161
169
  password=self.db_pass,
@@ -173,7 +181,7 @@ class PostgresPipe(QueryPipe,Integration):
173
181
  params = record.get(self.params_field) # single-exec params
174
182
  batch = record.get("batch_params", None) # list[tuple|dict] for batching
175
183
 
176
- cur = client.conn.cursor()
184
+ cur = self.client.conn.cursor()
177
185
  try:
178
186
  did_executemany = False
179
187
 
@@ -215,4 +223,5 @@ class PostgresPipe(QueryPipe,Integration):
215
223
  finally:
216
224
  cur.close()
217
225
  finally:
218
- client.close()
226
+ pass
227
+ # client.close()
@@ -38,7 +38,7 @@ COMPONENTS = {
38
38
  'reduce': ReducePipe,
39
39
  'sort': SortPipe,
40
40
  'where': WherePipe,
41
- 'sel': SelectFields,
41
+ 'select': SelectFields,
42
42
  'sample': SamplePipe,
43
43
  'explode': DenormPipe,
44
44
  'postgres': PostgresPipe,
@@ -10,12 +10,12 @@ class SelectFields(DeepCopyPipe):
10
10
  @classmethod
11
11
  def usage(cls):
12
12
  usage = Usage(
13
- name='sel',
13
+ name='select',
14
14
  desc='Select specific fields from each record.',
15
15
  component_class=cls
16
16
  )
17
17
  usage.def_arg(name='fields', usage='Comma-separated list of fields to retain')
18
- usage.def_example(expr_tokens=["{id:1, dir:'up', color:'blue'}", 'sel:id,color'], expect="id: 1, color:'blue'")
18
+ usage.def_example(expr_tokens=["{id:1, dir:'up', color:'blue'}", 'select:id,color'], expect="id: 1, color:'blue'")
19
19
  return usage
20
20
 
21
21
  def __init__(self, ptok: ParsedToken, usage: Usage):
@@ -20,10 +20,6 @@ from typing import Any, Dict, Iterable, List, Optional, Sequence
20
20
  from datetime import date, datetime
21
21
  from collections import defaultdict
22
22
 
23
- import numpy as np
24
- import pandas as pd
25
-
26
-
27
23
  # ----------------------------- Public Params -----------------------------
28
24
  @dataclass
29
25
  class GraphParams:
@@ -48,6 +44,8 @@ class TimeDetector:
48
44
 
49
45
  @staticmethod
50
46
  def is_time(xs: pd.Series) -> bool:
47
+ import numpy as np # lazy
48
+ import pandas as pd # lazy
51
49
  # Already datetime dtype?
52
50
  if pd.api.types.is_datetime64_any_dtype(xs):
53
51
  return True
@@ -74,6 +72,7 @@ class TimeDetector:
74
72
 
75
73
  @staticmethod
76
74
  def parse_times(series: pd.Series) -> pd.Series:
75
+ import pandas as pd # lazy
77
76
  numeric = pd.to_numeric(series, errors="coerce")
78
77
  parsed = None
79
78
  if numeric.notna().mean() >= 0.9:
@@ -92,6 +91,7 @@ class MultiYAdapter:
92
91
  """Builds wide dataframe: columns = ['x'] + y_fields; sums duplicates of x."""
93
92
  @staticmethod
94
93
  def to_df(records: Iterable[Dict[str, Any]], x_field: str, y_fields: Sequence[str]) -> pd.DataFrame:
94
+ import pandas as pd # lazy
95
95
  rows: List[Dict[str, Any]] = []
96
96
  for r in records:
97
97
  if x_field not in r:
@@ -137,12 +137,14 @@ class SingleYWithSetsAdapter:
137
137
  # ----------------------------- Plotter -----------------------------
138
138
  class GraphPlotter:
139
139
  def __init__(self, params: GraphParams):
140
+ import numpy as np
140
141
  self.pms = params
141
142
  self.y_fields = list(dict.fromkeys(self.pms.y_fields)) # dedupe, preserve order
142
143
 
143
144
  def plot(self, chart_type: str = "line"):
144
- import matplotlib.pyplot as plt
145
- import matplotlib.dates as mdates
145
+ import matplotlib.pyplot as plt # lazy
146
+ import matplotlib.dates as mdates # lazy
147
+ import pandas as pd # lazy
146
148
 
147
149
  fig = plt.figure()
148
150
  ax = plt.gca()
@@ -258,7 +260,7 @@ class GraphPlotter:
258
260
  # ---------- Formatting helpers ----------
259
261
  @staticmethod
260
262
  def _format_time_axis(ax, df: pd.DataFrame) -> None:
261
- import matplotlib.dates as mdates
263
+ import matplotlib.dates as mdates # lazy
262
264
  fig = ax.get_figure()
263
265
  ts = df["ts"]
264
266
  if ts.empty:
@@ -322,7 +324,7 @@ class GraphPlotter:
322
324
 
323
325
  # ---------- Misc ----------
324
326
  def _apply_args_dict(self) -> None:
325
- import matplotlib.pyplot as plt
327
+ import matplotlib.pyplot as plt # lazy
326
328
  for name, val in getattr(self.pms, "args_dict", {}).items():
327
329
  fn = getattr(plt, name, None)
328
330
  if callable(fn):
@@ -345,7 +347,7 @@ def graph_bar_line(obj, type):
345
347
  Returns (fig, ax) for optional downstream tweaks (safe to ignore).
346
348
  """
347
349
  # Lazy import (ensures MPL backend)
348
- import matplotlib.pyplot as plt # noqa: F401
350
+ import matplotlib.pyplot as plt # noqa: F401 # lazy
349
351
 
350
352
  # Normalize y_fields from string or list
351
353
  raw_y = obj.y_field if isinstance(obj.y_field, str) else str(obj.y_field)
@@ -4,18 +4,15 @@
4
4
  import json
5
5
  from typing import Iterator, Dict, Any
6
6
 
7
- import numpy as np
8
- from pjk.usage import NoBindUsage
9
- from pjk.components import Source
10
7
  from pjk.sources.lazy_file import LazyFile
11
8
  from pjk.sources.format_source import FormatSource
12
9
  from pjk.log import logger
13
10
 
14
-
15
11
  class NpySource(FormatSource):
16
12
  extension = 'npy'
17
13
 
18
14
  def __init__(self, lazy_file: LazyFile):
15
+ super().__init__(root=None)
19
16
  self.lazy_file = lazy_file
20
17
  self.num_vecs = 0
21
18
 
@@ -32,9 +29,11 @@ class NpySource(FormatSource):
32
29
 
33
30
  try:
34
31
  # Use mmap to avoid loading entire array in RAM at once.
32
+ import numpy as np #lazy import
35
33
  arr = np.load(path, mmap_mode="r", allow_pickle=False)
36
34
  except Exception as e:
37
35
  logger.error(f"Failed to load .npy file at {path}: {e}")
36
+ raise Exception(f"Failed to load .npy file at {path}: {e}")
38
37
  return
39
38
 
40
39
  if arr.size == 0:
@@ -1,4 +1,4 @@
1
1
  # SPDX-License-Identifier: Apache-2.0
2
2
  # Copyright 2024 Mike Schultz
3
3
 
4
- __version__ = "0.7.0"
4
+ __version__ = "0.7.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-jack-knife
3
- Version: 0.7.0
3
+ Version: 0.7.1
4
4
  Summary: Python Jack Knife – a command line data processor
5
5
  Author-email: Mike Schultz <mike.schultz@gmail.com>
6
6
  License: