datatailr 0.1.71__py3-none-any.whl → 0.1.73__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.
Potentially problematic release.
This version of datatailr might be problematic. Click here for more details.
- datatailr/excel/addin.py +11 -6
- datatailr/excel/stubs.py +37 -0
- datatailr/sbin/datatailr_run.py +9 -12
- datatailr/scheduler/base.py +1 -0
- datatailr/scheduler/batch.py +22 -6
- {datatailr-0.1.71.dist-info → datatailr-0.1.73.dist-info}/METADATA +1 -1
- {datatailr-0.1.71.dist-info → datatailr-0.1.73.dist-info}/RECORD +11 -10
- {datatailr-0.1.71.dist-info → datatailr-0.1.73.dist-info}/WHEEL +0 -0
- {datatailr-0.1.71.dist-info → datatailr-0.1.73.dist-info}/entry_points.txt +0 -0
- {datatailr-0.1.71.dist-info → datatailr-0.1.73.dist-info}/licenses/LICENSE +0 -0
- {datatailr-0.1.71.dist-info → datatailr-0.1.73.dist-info}/top_level.txt +0 -0
datatailr/excel/addin.py
CHANGED
|
@@ -13,7 +13,11 @@ import importlib
|
|
|
13
13
|
import subprocess
|
|
14
14
|
import inspect
|
|
15
15
|
import numpy as np
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
from dt.excel_base import Addin as AddinBase, Queue # type: ignore
|
|
19
|
+
except ImportError as e:
|
|
20
|
+
from datatailr.excel.stubs import AddinBase, Queue
|
|
17
21
|
|
|
18
22
|
|
|
19
23
|
def __progress__(queue, stop):
|
|
@@ -107,7 +111,9 @@ class Addin(AddinBase):
|
|
|
107
111
|
signature = inspect.signature(func)
|
|
108
112
|
|
|
109
113
|
def wrapper(*args, **kwargs):
|
|
110
|
-
|
|
114
|
+
# TODO: check whether it's possible to use a kwarg instead so that a decorated function can
|
|
115
|
+
# be called directly from python code without requiring positional argument for _id
|
|
116
|
+
_id = args[0]
|
|
111
117
|
|
|
112
118
|
for arg in signature.parameters.values():
|
|
113
119
|
if streaming and arg.name == "queue":
|
|
@@ -121,7 +127,7 @@ class Addin(AddinBase):
|
|
|
121
127
|
"excel/python/dt/excel.py: Got argument of wrong type, expected %s or numpy.ndarray, got %s"
|
|
122
128
|
% (arg.annotation, type(kwargs[arg.name]))
|
|
123
129
|
)
|
|
124
|
-
|
|
130
|
+
queue = Queue(self.name.lower() + "." + func.__name__, _id)
|
|
125
131
|
if not streaming:
|
|
126
132
|
if not progressbar:
|
|
127
133
|
result = func(**kwargs)
|
|
@@ -132,7 +138,7 @@ class Addin(AddinBase):
|
|
|
132
138
|
from threading import Event, Thread
|
|
133
139
|
|
|
134
140
|
error = None
|
|
135
|
-
|
|
141
|
+
|
|
136
142
|
stop = Event()
|
|
137
143
|
thread = Thread(target=__progress__, args=(queue, stop))
|
|
138
144
|
thread.start()
|
|
@@ -149,9 +155,8 @@ class Addin(AddinBase):
|
|
|
149
155
|
else:
|
|
150
156
|
queue.push(result)
|
|
151
157
|
return
|
|
152
|
-
|
|
153
158
|
try:
|
|
154
|
-
func(
|
|
159
|
+
func(queue, **kwargs)
|
|
155
160
|
except Exception as exception:
|
|
156
161
|
queue.error(str(exception))
|
|
157
162
|
|
datatailr/excel/stubs.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2025 - Datatailr Inc.
|
|
3
|
+
All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
This file is part of Datatailr and subject to the terms and conditions
|
|
6
|
+
defined in 'LICENSE.txt'. Unauthorized copying and/or distribution
|
|
7
|
+
of this file, in parts or full, via any medium is strictly prohibited.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AddinBase:
|
|
12
|
+
def __init__(self, name, *args, **kwargs):
|
|
13
|
+
self.name = name
|
|
14
|
+
|
|
15
|
+
def decorator_impl(
|
|
16
|
+
self,
|
|
17
|
+
signature,
|
|
18
|
+
wrapper,
|
|
19
|
+
func_name,
|
|
20
|
+
description,
|
|
21
|
+
help,
|
|
22
|
+
volatile,
|
|
23
|
+
streaming,
|
|
24
|
+
):
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Queue:
|
|
29
|
+
def __init__(self, name, _id):
|
|
30
|
+
self.name = name
|
|
31
|
+
self.id = _id
|
|
32
|
+
|
|
33
|
+
def push(self, value):
|
|
34
|
+
print(f"Queue {self.name} ({self.id}): {value}")
|
|
35
|
+
|
|
36
|
+
def error(self, message):
|
|
37
|
+
print(f"Queue {self.name} ({self.id}) Error: {message}")
|
datatailr/sbin/datatailr_run.py
CHANGED
|
@@ -75,11 +75,15 @@ def create_user_and_group() -> Tuple[str, str]:
|
|
|
75
75
|
gid = get_env_var("DATATAILR_GID")
|
|
76
76
|
|
|
77
77
|
# Create group if it does not exist
|
|
78
|
+
# -o: allow to create a group with a non-unique GID
|
|
78
79
|
os.system(f"getent group {group} || groupadd {group} -g {gid} -o")
|
|
79
80
|
|
|
80
81
|
# Create user if it does not exist
|
|
82
|
+
# -s /bin/bash: set the shell to bash
|
|
83
|
+
# -M: do not create home directory (it is already created on the NFS volume)
|
|
84
|
+
# -o: allow to create a user with a non-unique UID
|
|
81
85
|
os.system(
|
|
82
|
-
f"getent passwd {user} || useradd -g {group} -s /bin/bash -
|
|
86
|
+
f"getent passwd {user} || useradd -g {group} -s /bin/bash -M {user} -u {uid} -o"
|
|
83
87
|
)
|
|
84
88
|
|
|
85
89
|
permissions = (
|
|
@@ -93,11 +97,8 @@ def create_user_and_group() -> Tuple[str, str]:
|
|
|
93
97
|
| stat.S_IXGRP
|
|
94
98
|
)
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if os.path.exists(f"/home/{user}/tmp/.dt"):
|
|
100
|
-
os.chmod(f"/home/{user}/tmp/.dt", permissions)
|
|
100
|
+
os.makedirs(f"/home/{user}/tmp/.dt", exist_ok=True)
|
|
101
|
+
os.chmod(f"/home/{user}/tmp/.dt", permissions)
|
|
101
102
|
|
|
102
103
|
return user, group
|
|
103
104
|
|
|
@@ -231,21 +232,17 @@ def main():
|
|
|
231
232
|
} | env
|
|
232
233
|
run_single_command_non_blocking("datatailr_run_excel", user, env)
|
|
233
234
|
elif job_type == "workspace":
|
|
234
|
-
# Set a custom PS1 for the IDE terminal: 17:38|user@my-ide/~/dir/path:$
|
|
235
|
-
env["PS1"] = (
|
|
236
|
-
r"""\[\e[2m\]\A\[\e[0m\]|\[\e[38;5;40m\]\u\[\e[92m\]@${DATATAILR_JOB_NAME:-datatailr}\[\e[0m\]/\[\e[94;1m\]\w\[\e[0m\]\$"""
|
|
237
|
-
)
|
|
238
235
|
os.makedirs("/opt/datatailr/var/log", exist_ok=True)
|
|
239
236
|
ide_command = [
|
|
240
237
|
"code-server",
|
|
241
238
|
"--auth=none",
|
|
242
|
-
"--bind-addr=
|
|
239
|
+
"--bind-addr=127.0.0.1:9090",
|
|
243
240
|
f'--app-name="Datatailr IDE {get_env_var("DATATAILR_USER")}"',
|
|
244
241
|
]
|
|
245
242
|
job_name = get_env_var("DATATAILR_JOB_NAME")
|
|
246
243
|
jupyter_command = [
|
|
247
244
|
"jupyter-lab",
|
|
248
|
-
"--ip='
|
|
245
|
+
"--ip='127.0.0.1'",
|
|
249
246
|
"--port=7070",
|
|
250
247
|
"--no-browser",
|
|
251
248
|
"--NotebookApp.token=''",
|
datatailr/scheduler/base.py
CHANGED
|
@@ -245,6 +245,7 @@ class Job:
|
|
|
245
245
|
if self.type == JobType.EXCEL:
|
|
246
246
|
if "DATATAILR_LOCAL" not in self.__env_vars:
|
|
247
247
|
self.__env_vars.update({"DATATAILR_LOCAL": "false"})
|
|
248
|
+
job_dict["per_user_job"] = True
|
|
248
249
|
if self.type != JobType.BATCH:
|
|
249
250
|
job_dict["entrypoint"] = str(self.entrypoint) if self.entrypoint else None
|
|
250
251
|
job_dict["env"] = dict_to_env_vars(self.__env_vars)
|
datatailr/scheduler/batch.py
CHANGED
|
@@ -294,7 +294,7 @@ class BatchJob:
|
|
|
294
294
|
env = {
|
|
295
295
|
"DATATAILR_BATCH_ID": str(self.dag.id),
|
|
296
296
|
"DATATAILR_JOB_ID": str(self.__id),
|
|
297
|
-
"DATATAILR_JOB_NAME": self.name,
|
|
297
|
+
"DATATAILR_JOB_NAME": f"{self.dag.name}[{self.__id}]",
|
|
298
298
|
}
|
|
299
299
|
self.entrypoint(env=env)
|
|
300
300
|
else:
|
|
@@ -479,10 +479,26 @@ class Batch(Job):
|
|
|
479
479
|
|
|
480
480
|
def prepare_args(self) -> None:
|
|
481
481
|
def arg_name(arg: Union[BatchJob, str]) -> str:
|
|
482
|
-
return arg.
|
|
482
|
+
return f"{self.name}[{arg.id}]" if isinstance(arg, BatchJob) else arg
|
|
483
|
+
|
|
484
|
+
def adjust_mapping(mapping: Dict[str, str]) -> Dict[str, str]:
|
|
485
|
+
result = {}
|
|
486
|
+
for k, v in mapping.items():
|
|
487
|
+
if isinstance(v, BatchJob):
|
|
488
|
+
result[k] = f"{self.name}[{v.id}]"
|
|
489
|
+
elif isinstance(v, str):
|
|
490
|
+
job = self.get_job_by_name(v)
|
|
491
|
+
if job is not None:
|
|
492
|
+
result[k] = f"{self.name}[{job.id}]"
|
|
493
|
+
else:
|
|
494
|
+
result[k] = v
|
|
495
|
+
else:
|
|
496
|
+
raise TypeError(
|
|
497
|
+
f"Unsupported type in argument mapping: {type(v)} for key {k}"
|
|
498
|
+
)
|
|
499
|
+
return result
|
|
483
500
|
|
|
484
501
|
def merged(dst: dict[str, str], src: dict[str, str]) -> dict[str, str]:
|
|
485
|
-
# copy so we don't mutate the original mapping
|
|
486
502
|
out = dict(dst)
|
|
487
503
|
seen_vals = set(out.values())
|
|
488
504
|
for k, v in src.items():
|
|
@@ -492,12 +508,12 @@ class Batch(Job):
|
|
|
492
508
|
return out
|
|
493
509
|
|
|
494
510
|
args = {
|
|
495
|
-
j.
|
|
496
|
-
j.argument_mapping
|
|
511
|
+
f"{self.name}[{j.id}]": merged(
|
|
512
|
+
adjust_mapping(j.argument_mapping),
|
|
513
|
+
{j.argument_mapping.get(k, k): arg_name(v) for k, v in j.args.items()},
|
|
497
514
|
)
|
|
498
515
|
for j in self.__jobs
|
|
499
516
|
}
|
|
500
|
-
|
|
501
517
|
__ARGUMENTS_CACHE__.add_arguments(self.id, args)
|
|
502
518
|
|
|
503
519
|
def save(self) -> Tuple[bool, str]:
|
|
@@ -13,23 +13,24 @@ datatailr/wrapper.py,sha256=45RrMeYIFFWJAtOlQZRe1fT9daeq4vFlj6nIajbewEY,8080
|
|
|
13
13
|
datatailr/build/__init__.py,sha256=_dA7b4L6wsaAFaSxUoYSJ1oaRqDHDMR20kqoCocSOss,487
|
|
14
14
|
datatailr/build/image.py,sha256=YC8ML-l-sj6TcIBY-DCx_vaeI_7SmL9fPFhHnuxzRh0,5509
|
|
15
15
|
datatailr/excel/__init__.py,sha256=wox5ltPeOYZcZoRDW4R6tJsfOjf-0WZM2_pGgltGjdo,682
|
|
16
|
-
datatailr/excel/addin.py,sha256=
|
|
17
|
-
datatailr/
|
|
16
|
+
datatailr/excel/addin.py,sha256=3UiA7z71ewnEvLSTbcJdPNGWf-uYbeSt_3vbgN42h4E,6354
|
|
17
|
+
datatailr/excel/stubs.py,sha256=RU0Y6PWKRAtK-tgBP5uWrWYW-L3TIGRJwcUUhkA5yxU,830
|
|
18
|
+
datatailr/sbin/datatailr_run.py,sha256=qKMTKjJWX8bOc8GLAvTUR7ZL056-amLvXdAncqJMAEU,9962
|
|
18
19
|
datatailr/sbin/datatailr_run_app.py,sha256=itF76XC2F4RK9s6bkoEppEiYwSLHK_5Jai3yvC-kFhY,1501
|
|
19
20
|
datatailr/sbin/datatailr_run_batch.py,sha256=UWnp96j_G66R_Cape7Bb-rbK6UBLF7Y5_mTlWyGJAVQ,1818
|
|
20
21
|
datatailr/sbin/datatailr_run_excel.py,sha256=BLWmvxpKEE_8vJhs8E4VWq07FOBof5tlow-AkIEXtHw,1470
|
|
21
22
|
datatailr/sbin/datatailr_run_service.py,sha256=DO9LGOpz3CVZOJJRHb4ac7AgY_mLbXHGadSyVCeIknc,1212
|
|
22
23
|
datatailr/scheduler/__init__.py,sha256=qydHYVtEP6SUWd2CQ6FRdTdRWNz3SbYPJy4FK_wOvMk,1772
|
|
23
24
|
datatailr/scheduler/arguments_cache.py,sha256=00OE0DhobYteBOnirjulO1ltgGBRamAdCO168O3_Zes,6236
|
|
24
|
-
datatailr/scheduler/base.py,sha256=
|
|
25
|
-
datatailr/scheduler/batch.py,sha256=
|
|
25
|
+
datatailr/scheduler/base.py,sha256=GlTsp2Qcoy14DTfLSPhiFFBRE_cMfz_uA_ASQSx4tL0,17038
|
|
26
|
+
datatailr/scheduler/batch.py,sha256=ZhEf3YkXf1_ieV5ivk4-me60ov9v5r9f9BdkJw84i_0,18475
|
|
26
27
|
datatailr/scheduler/batch_decorator.py,sha256=LqL1bsupWLn-YEQUvFJYae7R3ogrL5-VodyiiScrkRw,5806
|
|
27
28
|
datatailr/scheduler/constants.py,sha256=5WWTsfwZ_BA8gVDOTa2AQX9DJ0NzfaWgtY3vrODS2-8,606
|
|
28
29
|
datatailr/scheduler/schedule.py,sha256=0XJJen2nL1xplRs0Xbjwgq3T-0bFCOrJzkSALdio998,3741
|
|
29
30
|
datatailr/scheduler/utils.py,sha256=up6oR2iwe6G52LkvgfO394xchXgCYNjOMGRQW3e8PQk,1082
|
|
30
|
-
datatailr-0.1.
|
|
31
|
-
datatailr-0.1.
|
|
32
|
-
datatailr-0.1.
|
|
33
|
-
datatailr-0.1.
|
|
34
|
-
datatailr-0.1.
|
|
35
|
-
datatailr-0.1.
|
|
31
|
+
datatailr-0.1.73.dist-info/licenses/LICENSE,sha256=ikKP4_O-UD_b8FuNdKmbzTb6odd0JX085ZW_FAPN3VI,1066
|
|
32
|
+
datatailr-0.1.73.dist-info/METADATA,sha256=gl76JiXGJXes-34NGbHzW0Jmauiohad2CaQuvvpWon0,5146
|
|
33
|
+
datatailr-0.1.73.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
34
|
+
datatailr-0.1.73.dist-info/entry_points.txt,sha256=YqXfk2At-olW4PUSRkqvy_O3Mbv7uTKCCPuAAiz3Qbg,312
|
|
35
|
+
datatailr-0.1.73.dist-info/top_level.txt,sha256=75gntW0X_SKpqxLL6hAPipvpk28GAhJBvoyqN_HohWU,10
|
|
36
|
+
datatailr-0.1.73.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|