lam-cli 0.0.4__py3-none-any.whl → 0.0.6__py3-none-any.whl

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.
lam/lam.py CHANGED
@@ -9,41 +9,61 @@ import subprocess
9
9
  from datetime import datetime
10
10
 
11
11
  import click
12
+ from logtail import LogtailHandler
12
13
  from posthog import Posthog
13
14
 
14
15
  posthog = Posthog(project_api_key='phc_wfeHFG0p5yZIdBpjVYy00o5x1HbEpggdMzIuFYgNPSK', host='https://app.posthog.com')
15
16
 
17
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
18
+ logger = logging.getLogger(__name__)
19
+
20
+ handler = LogtailHandler(source_token="TYz3WrrvC8ehYjXdAEGGyiDp")
21
+ logger.addHandler(handler)
22
+
16
23
  jq_path = 'jq'
17
24
 
25
+ def truncate_long_strings(data, max_length=1000, truncation_msg="... (truncated)"):
26
+ """
27
+ Truncate long strings in a JSON object if they exceed max_length.
28
+ Append a message to indicate truncation.
29
+ """
30
+ if isinstance(data, dict):
31
+ return {key: truncate_long_strings(value, max_length, truncation_msg) for key, value in data.items()}
32
+ elif isinstance(data, list):
33
+ return [truncate_long_strings(item, max_length, truncation_msg) for item in data]
34
+ elif isinstance(data, str):
35
+ return data[:max_length] + truncation_msg if len(data) > max_length else data
36
+ return data
37
+
18
38
  def generate_distinct_id(workspace_id, flow_id):
19
39
  user_id = os.getuid()
20
40
  hostname = socket.gethostname()
21
41
  return f"{user_id}_{hostname}_{workspace_id}_{flow_id}"
22
42
 
23
43
  def track_event(event_name, properties, workspace_id="local", flow_id="local"):
24
- logging.info(f"Event {event_name} triggered, with properties: {properties}")
44
+ logger.info(f"Event {event_name} triggered, with properties: {properties}")
25
45
 
26
46
  try:
27
47
  distinct_id = generate_distinct_id(workspace_id, flow_id)
28
48
  posthog.capture(distinct_id=distinct_id, event=event_name, properties=properties)
29
49
  except Exception as e:
30
- logging.error(f"Error logging event: {e}")
50
+ logger.error(f"Error logging event: {e}")
31
51
 
32
52
  def parse_program_file(program_file):
33
- logging.info(f"Parsing program file: {program_file}")
53
+ logger.info(f"Parsing program file: {program_file}")
34
54
  with open(program_file, 'r') as file:
35
55
  return ''.join(line for line in file if not line.strip().startswith('#'))
36
56
 
37
57
  def run_jq(jq_script, input_data):
38
- logging.info(f"Running jq script {jq_script} with input data {input_data}")
58
+ logger.info(f"Running jq script {jq_script} with input data {truncate_long_strings(input_data)}")
39
59
  process = subprocess.Popen([jq_path, '-c', jq_script], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
40
60
  output, error = process.communicate(input=input_data)
41
61
  if error:
42
- logging.error(f"Error running jq: {error}")
62
+ logger.error(f"Error running jq: {error}")
43
63
  return output, error
44
64
 
45
65
  def process_input(input, workspace_id, flow_id):
46
- logging.info(f"Processing input: {input}")
66
+ logger.info(f"Processing input: {truncate_long_strings(input)}")
47
67
  if os.path.isfile(input):
48
68
  with open(input, 'r') as file:
49
69
  return file.read(), None
@@ -51,21 +71,20 @@ def process_input(input, workspace_id, flow_id):
51
71
  json.loads(input)
52
72
  return input, None
53
73
  except json.JSONDecodeError as e:
54
- logging.error(f"Invalid JSON input: {e}")
74
+ logger.error(f"Invalid JSON input: {e}")
55
75
  track_event('lam.run.error', {'error': f"Invalid JSON input: {e}", 'workspace_id': workspace_id, 'flow_id': flow_id}, workspace_id, flow_id)
56
76
  return None, str(e)
57
77
 
58
78
  def handle_jq_output(output, as_json, workspace_id, flow_id):
59
- logging.info(f"Handling jq output: {output}")
79
+ logger.info(f"Handling jq output: {truncate_long_strings(output)}")
60
80
  try:
61
81
  json_output = json.loads(output)
62
- # Make sure the output has a top-level object
63
82
  if not isinstance(json_output, dict):
64
83
  track_event('lam.run.warn', {'error': 'Invalid JSON output', 'workspace_id': workspace_id, 'flow_id': flow_id}, workspace_id, flow_id)
65
84
  return {"lam.result": json_output} if as_json else output, None
66
85
  return json_output if as_json else output, None
67
86
  except json.JSONDecodeError as e:
68
- logging.error("Failed to parse JSON output, may be multiple JSON objects. Attempting to parse as JSON lines.")
87
+ logger.error("Failed to parse JSON output, may be multiple JSON objects. Attempting to parse as JSON lines.")
69
88
  track_event('lam.run.warn', {'error': f"Invalid JSON output: {e}", 'workspace_id': workspace_id, 'flow_id': flow_id}, workspace_id, flow_id)
70
89
  if as_json:
71
90
  json_objects = [json.loads(line) for line in output.strip().split('\n') if line]
@@ -91,14 +110,14 @@ def run(program_file, input, workspace_id, flow_id, as_json):
91
110
  log_file = f"lam_run_{workspace_id}_{flow_id}_{timestamp}.log"
92
111
  result_file = f"lam_result_{workspace_id}_{flow_id}_{timestamp}.json"
93
112
 
94
- # Now configure logging with the determined log file name
95
- logging.basicConfig(level=logging.INFO, filename=log_file, filemode='w',
96
- format='%(asctime)s - %(levelname)s - %(message)s')
113
+ file_handler = logging.FileHandler(log_file, 'w')
114
+ file_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
115
+ logger.addHandler(file_handler)
97
116
 
98
- logging.info(f"Logging to {log_file}")
99
- logging.info(f"Running command with program file: {program_file}, input: {input}, workspace_id: {workspace_id}, flow_id: {flow_id}, as_json: {as_json}")
117
+ logger.info(f"Logging to {log_file}")
118
+ logger.info(f"Running command with program file: {program_file}, input: {truncate_long_strings(input)}, workspace_id: {workspace_id}, flow_id: {flow_id}, as_json: {as_json}")
100
119
  if not shutil.which("jq"):
101
- logging.error("Unable to find jq, killing process")
120
+ logger.error("Unable to find jq, killing process")
102
121
  click.echo({"lam.error": "jq is not installed"}, err=True)
103
122
  track_event('lam.run.error', {'error': 'jq is not installed', 'workspace_id': workspace_id, 'flow_id': flow_id}, workspace_id, flow_id)
104
123
  write_to_result_file({"lam.error": "jq is not installed"}, result_file)
@@ -131,7 +150,8 @@ def run(program_file, input, workspace_id, flow_id, as_json):
131
150
  track_event('lam.run.success', {'workspace_id': workspace_id, 'flow_id': flow_id}, workspace_id, flow_id)
132
151
  write_to_result_file(result, result_file)
133
152
 
134
- logging.info("Run complete, waiting for event logger to finish")
153
+ logger.info("Run complete, waiting for event logger to finish")
154
+ logger.removeHandler(file_handler)
135
155
 
136
156
  if __name__ == '__main__':
137
- lam()
157
+ lam()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lam-cli
3
- Version: 0.0.4
3
+ Version: 0.0.6
4
4
  Summary: Laminar data transformation tool
5
5
  Home-page: https://github.com/laminar-run/lam
6
6
  Author: Laminar Run, Inc.
@@ -9,6 +9,7 @@ License: GPLv3
9
9
  License-File: LICENSE
10
10
  Requires-Dist: click
11
11
  Requires-Dist: posthog
12
+ Requires-Dist: logtail-python
12
13
 
13
14
 
14
15
  Laminar is a platform that makes building and maintaining API integrations faster.
@@ -0,0 +1,8 @@
1
+ lam/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ lam/lam.py,sha256=a2O622WWikM3OZq_KhTQm-3kl4JHygkYCK_NwQCeTP8,7269
3
+ lam_cli-0.0.6.dist-info/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
4
+ lam_cli-0.0.6.dist-info/METADATA,sha256=vl5pMwIXxzOzmq1AfrYu0eBpvcUu7eDdivn81ofKrlo,404
5
+ lam_cli-0.0.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ lam_cli-0.0.6.dist-info/entry_points.txt,sha256=ph7QV6H2VWqf9fU5rtoAgEabDgZ4f85ZImdLXeBmdfA,36
7
+ lam_cli-0.0.6.dist-info/top_level.txt,sha256=WyM7-Ig60qQH9meqS293pEd83jrMtbvGJM8ALZOQCtA,4
8
+ lam_cli-0.0.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,8 +0,0 @@
1
- lam/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- lam/lam.py,sha256=p5VyBROZFx9xl0ueZJXrpRea31Tc22ZH-nK2wtt_BKk,6353
3
- lam_cli-0.0.4.dist-info/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
4
- lam_cli-0.0.4.dist-info/METADATA,sha256=p9bpZSiR4hEX5_fSR-sYDq-u1oZ5SRMIYufND0XMlz0,374
5
- lam_cli-0.0.4.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
6
- lam_cli-0.0.4.dist-info/entry_points.txt,sha256=ph7QV6H2VWqf9fU5rtoAgEabDgZ4f85ZImdLXeBmdfA,36
7
- lam_cli-0.0.4.dist-info/top_level.txt,sha256=WyM7-Ig60qQH9meqS293pEd83jrMtbvGJM8ALZOQCtA,4
8
- lam_cli-0.0.4.dist-info/RECORD,,