datatailr 0.1.32__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.
- {datatailr-0.1.32/src/datatailr.egg-info → datatailr-0.1.34}/PKG-INFO +1 -1
- {datatailr-0.1.32 → datatailr-0.1.34}/pyproject.toml +1 -1
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/blob.py +2 -6
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/group.py +2 -2
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/logging.py +9 -40
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/scheduler/base.py +0 -3
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/scheduler/batch.py +1 -9
- {datatailr-0.1.32 → datatailr-0.1.34/src/datatailr.egg-info}/PKG-INFO +1 -1
- {datatailr-0.1.32 → datatailr-0.1.34}/src/sbin/datatailr_run.py +24 -51
- {datatailr-0.1.32 → datatailr-0.1.34}/src/sbin/datatailr_run_excel.py +4 -4
- {datatailr-0.1.32 → datatailr-0.1.34}/LICENSE +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/README.md +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/setup.cfg +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/setup.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/__init__.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/acl.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/build/__init__.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/build/image.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/dt_json.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/errors.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/excel.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/scheduler/__init__.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/scheduler/arguments_cache.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/scheduler/batch_decorator.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/scheduler/constants.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/scheduler/schedule.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/scheduler/utils.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/user.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/utils.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/version.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr/wrapper.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr.egg-info/SOURCES.txt +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr.egg-info/dependency_links.txt +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr.egg-info/entry_points.txt +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr.egg-info/requires.txt +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/datatailr.egg-info/top_level.txt +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/sbin/datatailr_run_app.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/sbin/datatailr_run_batch.py +0 -0
- {datatailr-0.1.32 → datatailr-0.1.34}/src/sbin/datatailr_run_service.py +0 -0
|
@@ -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
|
-
|
|
102
|
-
|
|
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
|
-
|
|
107
|
-
return Group(
|
|
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
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
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):
|
|
@@ -241,9 +241,6 @@ class Job:
|
|
|
241
241
|
}
|
|
242
242
|
if self.type != JobType.BATCH:
|
|
243
243
|
job_dict["entrypoint"] = str(self.entrypoint) if self.entrypoint else None
|
|
244
|
-
job_dict["image"] = (self.image,)
|
|
245
|
-
job_dict["memory"] = (self.resources.memory,)
|
|
246
|
-
job_dict["cpu"] = self.resources.cpu
|
|
247
244
|
return job_dict
|
|
248
245
|
|
|
249
246
|
def from_dict(self, job_dict: dict):
|
|
@@ -459,7 +459,7 @@ class Batch(Job):
|
|
|
459
459
|
return args
|
|
460
460
|
return {}
|
|
461
461
|
|
|
462
|
-
def
|
|
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:
|
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
118
|
-
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
142
|
+
}
|
|
154
143
|
run_command_as_user("datatailr_run_excel", user, env)
|
|
155
144
|
elif job_type == "IDE":
|
|
156
|
-
|
|
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
|
-
|
|
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
|
|
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
|