datatailr 0.1.33__tar.gz → 0.1.34__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.

Potentially problematic release.


This version of datatailr might be problematic. Click here for more details.

Files changed (39) hide show
  1. {datatailr-0.1.33/src/datatailr.egg-info → datatailr-0.1.34}/PKG-INFO +1 -1
  2. {datatailr-0.1.33 → datatailr-0.1.34}/pyproject.toml +1 -1
  3. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/blob.py +2 -6
  4. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/group.py +2 -2
  5. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/logging.py +9 -40
  6. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/scheduler/batch.py +1 -9
  7. {datatailr-0.1.33 → datatailr-0.1.34/src/datatailr.egg-info}/PKG-INFO +1 -1
  8. {datatailr-0.1.33 → datatailr-0.1.34}/src/sbin/datatailr_run.py +24 -51
  9. {datatailr-0.1.33 → datatailr-0.1.34}/src/sbin/datatailr_run_excel.py +4 -4
  10. {datatailr-0.1.33 → datatailr-0.1.34}/LICENSE +0 -0
  11. {datatailr-0.1.33 → datatailr-0.1.34}/README.md +0 -0
  12. {datatailr-0.1.33 → datatailr-0.1.34}/setup.cfg +0 -0
  13. {datatailr-0.1.33 → datatailr-0.1.34}/setup.py +0 -0
  14. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/__init__.py +0 -0
  15. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/acl.py +0 -0
  16. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/build/__init__.py +0 -0
  17. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/build/image.py +0 -0
  18. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/dt_json.py +0 -0
  19. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/errors.py +0 -0
  20. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/excel.py +0 -0
  21. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/scheduler/__init__.py +0 -0
  22. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/scheduler/arguments_cache.py +0 -0
  23. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/scheduler/base.py +0 -0
  24. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/scheduler/batch_decorator.py +0 -0
  25. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/scheduler/constants.py +0 -0
  26. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/scheduler/schedule.py +0 -0
  27. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/scheduler/utils.py +0 -0
  28. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/user.py +0 -0
  29. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/utils.py +0 -0
  30. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/version.py +0 -0
  31. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr/wrapper.py +0 -0
  32. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr.egg-info/SOURCES.txt +0 -0
  33. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr.egg-info/dependency_links.txt +0 -0
  34. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr.egg-info/entry_points.txt +0 -0
  35. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr.egg-info/requires.txt +0 -0
  36. {datatailr-0.1.33 → datatailr-0.1.34}/src/datatailr.egg-info/top_level.txt +0 -0
  37. {datatailr-0.1.33 → datatailr-0.1.34}/src/sbin/datatailr_run_app.py +0 -0
  38. {datatailr-0.1.33 → datatailr-0.1.34}/src/sbin/datatailr_run_batch.py +0 -0
  39. {datatailr-0.1.33 → datatailr-0.1.34}/src/sbin/datatailr_run_service.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datatailr
3
- Version: 0.1.33
3
+ Version: 0.1.34
4
4
  Summary: Ready-to-Use Platform That Drives Business Insights
5
5
  Author-email: Datatailr <info@datatailr.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "datatailr"
7
- version = "0.1.33"
7
+ version = "0.1.34"
8
8
  description = "Ready-to-Use Platform That Drives Business Insights"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -98,10 +98,6 @@ class Blob:
98
98
  # Since direct reading and writting of blobs is not implemented yet, we are using a temporary file.
99
99
  # This is a workaround to allow writing the blob content directly to the blob storage.
100
100
  with tempfile.NamedTemporaryFile(delete=True) as temp_file:
101
- if isinstance(blob, bytes):
102
- with open(temp_file.name, "wb") as f:
103
- f.write(blob)
104
- else:
105
- with open(temp_file.name, "w") as f:
106
- f.write(blob)
101
+ with open(temp_file.name, "w") as f:
102
+ f.write(blob)
107
103
  self.put_file(name, temp_file.name)
@@ -103,8 +103,8 @@ class Group:
103
103
 
104
104
  @staticmethod
105
105
  def add(name: str) -> Optional["Group"]:
106
- new_group = __client__.add(name, json_enrichened=True)
107
- return Group(new_group["name"]) if new_group else None
106
+ __client__.add(name)
107
+ return Group.get(name)
108
108
 
109
109
  @staticmethod
110
110
  def ls() -> list:
@@ -10,7 +10,7 @@
10
10
 
11
11
  import logging
12
12
  import os
13
- import sys
13
+ from logging import StreamHandler
14
14
  from logging.handlers import RotatingFileHandler
15
15
  from typing import Optional
16
16
  from datatailr import User
@@ -33,28 +33,6 @@ def get_log_level() -> int:
33
33
  return logging.INFO
34
34
 
35
35
 
36
- class MaxLevelFilter(logging.Filter):
37
- """Allow only log records at or below a given level."""
38
-
39
- def __init__(self, level):
40
- super().__init__()
41
- self.level = level
42
-
43
- def filter(self, record: logging.LogRecord) -> bool:
44
- return record.levelno <= self.level
45
-
46
-
47
- class MinLevelFilter(logging.Filter):
48
- """Allow only log records at or above a given level."""
49
-
50
- def __init__(self, level):
51
- super().__init__()
52
- self.level = level
53
-
54
- def filter(self, record: logging.LogRecord) -> bool:
55
- return record.levelno >= self.level
56
-
57
-
58
36
  tag = dt__Tag()
59
37
  node_name = tag.get("node_name") or "local"
60
38
  node_ip = tag.get("node_ip")
@@ -88,21 +66,12 @@ class DatatailrLogger:
88
66
  self.logger = logging.getLogger(name)
89
67
  self.logger.setLevel(log_level)
90
68
 
91
- formatter = logging.Formatter(log_format)
92
-
93
- # stdout handler (DEBUG/INFO only)
94
- stdout_handler = logging.StreamHandler(sys.stdout)
95
- stdout_handler.setLevel(logging.DEBUG)
96
- stdout_handler.addFilter(MaxLevelFilter(logging.INFO))
97
- stdout_handler.setFormatter(formatter)
98
- self.logger.addHandler(stdout_handler)
99
-
100
- # stderr handler (WARNING and above)
101
- stderr_handler = logging.StreamHandler(sys.stderr)
102
- stderr_handler.setLevel(logging.WARNING)
103
- stderr_handler.addFilter(MinLevelFilter(logging.WARNING))
104
- stderr_handler.setFormatter(formatter)
105
- self.logger.addHandler(stderr_handler)
69
+ # Stream handler for stdout/stderr
70
+ stream_handler = StreamHandler()
71
+ stream_handler.setLevel(log_level)
72
+ stream_formatter = logging.Formatter(log_format)
73
+ stream_handler.setFormatter(stream_formatter)
74
+ self.logger.addHandler(stream_handler)
106
75
 
107
76
  # Optional file handler
108
77
  if log_file:
@@ -110,9 +79,9 @@ class DatatailrLogger:
110
79
  log_file, maxBytes=10 * 1024 * 1024, backupCount=5
111
80
  )
112
81
  file_handler.setLevel(log_level)
113
- file_handler.setFormatter(formatter)
82
+ file_formatter = logging.Formatter(log_format)
83
+ file_handler.setFormatter(file_formatter)
114
84
  self.logger.addHandler(file_handler)
115
-
116
85
  self.enable_opentelemetry()
117
86
 
118
87
  def get_logger(self):
@@ -459,7 +459,7 @@ class Batch(Job):
459
459
  return args
460
460
  return {}
461
461
 
462
- def prepare_args(self) -> None:
462
+ def run(self) -> Tuple[bool, str]:
463
463
  def arg_name(arg: Union[BatchJob, str]) -> str:
464
464
  return arg.name if isinstance(arg, BatchJob) else arg
465
465
 
@@ -481,14 +481,6 @@ class Batch(Job):
481
481
  }
482
482
 
483
483
  __ARGUMENTS_CACHE__.add_arguments(self.id, args)
484
-
485
- def save(self) -> Tuple[bool, str]:
486
- self.prepare_args()
487
- return super().save()
488
-
489
- def run(self) -> Tuple[bool, str]:
490
- self.prepare_args()
491
-
492
484
  if not self.__local_run and is_dt_installed():
493
485
  return super().run()
494
486
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datatailr
3
- Version: 0.1.33
3
+ Version: 0.1.34
4
4
  Summary: Ready-to-Use Platform That Drives Business Insights
5
5
  Author-email: Datatailr <info@datatailr.com>
6
6
  License-Expression: MIT
@@ -32,7 +32,6 @@
32
32
  # DATATAILR_JOB_ID - the unique identifier for the job.
33
33
 
34
34
 
35
- import subprocess
36
35
  import os
37
36
  import sys
38
37
  from typing import Tuple
@@ -43,7 +42,7 @@ logger = DatatailrLogger(os.path.abspath(__file__)).get_logger()
43
42
 
44
43
  if not is_dt_installed():
45
44
  logger.error("Datatailr is not installed.")
46
- # sys.exit(1) # TODO: Uncomment after testing
45
+ sys.exit(1)
47
46
 
48
47
 
49
48
  def get_env_var(name: str, default: str | None = None) -> str:
@@ -81,32 +80,18 @@ def create_user_and_group() -> Tuple[str, str]:
81
80
  return user, group
82
81
 
83
82
 
84
- def run_command_as_user(command: str | list, user: str, env_vars: dict):
83
+ def run_command_as_user(command: str, user: str, env_vars: dict):
85
84
  """
86
85
  Run a command as a specific user with the given environment variables.
87
86
  """
88
- if isinstance(command, str):
89
- command = command.split(" ")
90
- env_vars = {
91
- "PATH": get_env_var("PATH", ""),
92
- "PYTHONPATH": get_env_var("PYTHONPATH", ""),
93
- } | env_vars
94
-
95
- env_kv = [f"{k}={v}" for k, v in env_vars.items()]
96
- argv = ["sudo", "-u", user, "env", *env_kv, "bash", "-lc", *command]
97
-
98
- try:
99
- result = subprocess.run(
100
- argv,
101
- check=True, # raises if returncode != 0
102
- capture_output=True,
103
- text=True,
104
- )
105
- logger.info(f"stdout: {result.stdout}")
106
- logger.debug(f"stderr: {result.stderr}")
107
- except subprocess.CalledProcessError as e:
108
- logger.error(f"Command failed with exit code {e.returncode}")
109
- logger.error(f"stderr: {e.stderr}")
87
+ env_vars.update({"PATH": get_env_var("PATH")})
88
+ env_vars.update({"PYTHONPATH": get_env_var("PYTHONPATH", "")})
89
+ env_vars_str = " ".join(f"{key}='{value}'" for key, value in env_vars.items())
90
+ full_command = f"sudo -u {user} {env_vars_str} {command}"
91
+ logger.debug(f"Running command: {full_command}")
92
+ status = os.system(full_command)
93
+ if status != 0:
94
+ logger.error(f"Command failed with status {status / 256:g}")
110
95
  sys.exit(1)
111
96
 
112
97
 
@@ -114,11 +99,8 @@ def main():
114
99
  user, _ = create_user_and_group()
115
100
  job_type = get_env_var("DATATAILR_JOB_TYPE")
116
101
 
117
- env = {
118
- "DATATAILR_JOB_TYPE": job_type,
119
- "DATATAILR_JOB_NAME": get_env_var("DATATAILR_JOB_NAME"),
120
- "DATATAILR_JOB_ID": get_env_var("DATATAILR_JOB_ID"),
121
- }
102
+ job_name = get_env_var("DATATAILR_JOB_NAME")
103
+ job_id = get_env_var("DATATAILR_JOB_ID")
122
104
 
123
105
  if job_type == "batch":
124
106
  run_id = get_env_var("DATATAILR_BATCH_RUN_ID")
@@ -127,49 +109,40 @@ def main():
127
109
  env = {
128
110
  "DATATAILR_BATCH_RUN_ID": run_id,
129
111
  "DATATAILR_BATCH_ID": batch_id,
112
+ "DATATAILR_JOB_ID": job_id,
130
113
  "DATATAILR_BATCH_ENTRYPOINT": entrypoint,
131
- } | env
114
+ }
132
115
  run_command_as_user("datatailr_run_batch", user, env)
133
116
  elif job_type == "service":
134
117
  port = get_env_var("DATATAILR_SERVICE_PORT")
135
118
  entrypoint = get_env_var("DATATAILR_ENTRYPOINT")
136
119
  env = {
120
+ "DATATAILR_JOB_NAME": job_name,
121
+ "DATATAILR_JOB_ID": job_id,
137
122
  "DATATAILR_ENTRYPOINT": entrypoint,
138
123
  "DATATAILR_SERVICE_PORT": port,
139
- } | env
124
+ }
140
125
  run_command_as_user("datatailr_run_service", user, env)
141
126
  elif job_type == "app":
142
127
  entrypoint = get_env_var("DATATAILR_ENTRYPOINT")
143
128
  env = {
129
+ "DATATAILR_JOB_NAME": job_name,
130
+ "DATATAILR_JOB_ID": job_id,
144
131
  "DATATAILR_ENTRYPOINT": entrypoint,
145
- } | env
132
+ }
146
133
  run_command_as_user("datatailr_run_app", user, env)
147
134
  elif job_type == "excel":
148
135
  host = get_env_var("DATATAILR_HOST")
149
136
  entrypoint = get_env_var("DATATAILR_ENTRYPOINT")
150
137
  env = {
138
+ "DATATAILR_JOB_NAME": job_name,
139
+ "DATATAILR_JOB_ID": job_id,
151
140
  "DATATAILR_ENTRYPOINT": entrypoint,
152
141
  "DATATAILR_HOST": host,
153
- } | env
142
+ }
154
143
  run_command_as_user("datatailr_run_excel", user, env)
155
144
  elif job_type == "IDE":
156
- command = [
157
- "code-server",
158
- "--auth=none",
159
- "--bind-addr=0.0.0.0:8080",
160
- f'--app-name="Datatailr IDE {get_env_var("DATATAILR_USER")}"',
161
- ]
162
- run_command_as_user(command, user, env)
163
- elif job_type == "jupyter":
164
- command = [
165
- "jupyter-lab",
166
- "--ip='*'",
167
- "--port=8080",
168
- "--no-browser",
169
- "--NotebookApp.token=''",
170
- "--NotebookApp.password=''",
171
- ]
172
- run_command_as_user(command, user, env)
145
+ pass
173
146
  else:
174
147
  raise ValueError(f"Unknown job type: {job_type}")
175
148
 
@@ -21,14 +21,14 @@ logger = DatatailrLogger(os.path.abspath(__file__)).get_logger()
21
21
  def run():
22
22
  logger.info("Starting Datatailr excel add-in...")
23
23
  entrypoint = os.environ.get("DATATAILR_ENTRYPOINT")
24
- hostname = os.environ.get("DATATAILR_HOST")
24
+ # hostname = os.environ.get("DATATAILR_HOST")
25
25
 
26
26
  if entrypoint is None:
27
27
  raise ValueError("Environment variable 'DATATAILR_ENTRYPOINT' is not set.")
28
28
 
29
- if hostname is None:
30
- raise ValueError("Environment variable 'DATATAILR_HOST' is not set.")
29
+ # if hostname is None:
30
+ # raise ValueError("Environment variable 'DATATAILR_HOST' is not set.")
31
31
 
32
- entrypoint = f'./dt-excel.sh -n -H "{hostname}" -p 8080 "{entrypoint}"'
32
+ # entrypoint = f'./dt-excel.sh -n -H "{hostname}" -p 8080 "{entrypoint}"'
33
33
  logger.info(f"Running entrypoint: {entrypoint}")
34
34
  subprocess.run(entrypoint, shell=True)
File without changes
File without changes
File without changes
File without changes