datatailr 0.1.72__tar.gz → 0.1.73__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.
- {datatailr-0.1.72/src/datatailr.egg-info → datatailr-0.1.73}/PKG-INFO +1 -1
- {datatailr-0.1.72 → datatailr-0.1.73}/pyproject.toml +1 -1
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/excel/addin.py +11 -6
- datatailr-0.1.73/src/datatailr/excel/stubs.py +37 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/scheduler/base.py +1 -0
- {datatailr-0.1.72 → datatailr-0.1.73/src/datatailr.egg-info}/PKG-INFO +1 -1
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr.egg-info/SOURCES.txt +1 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/sbin/datatailr_run.py +7 -7
- {datatailr-0.1.72 → datatailr-0.1.73}/LICENSE +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/README.md +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/setup.cfg +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/setup.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/__init__.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/acl.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/blob.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/build/__init__.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/build/image.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/dt_json.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/errors.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/excel/__init__.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/group.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/logging.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/scheduler/__init__.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/scheduler/arguments_cache.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/scheduler/batch.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/scheduler/batch_decorator.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/scheduler/constants.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/scheduler/schedule.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/scheduler/utils.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/tag.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/user.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/utils.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/version.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr/wrapper.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr.egg-info/dependency_links.txt +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr.egg-info/entry_points.txt +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr.egg-info/requires.txt +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/datatailr.egg-info/top_level.txt +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/sbin/datatailr_run_app.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/sbin/datatailr_run_batch.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/sbin/datatailr_run_excel.py +0 -0
- {datatailr-0.1.72 → datatailr-0.1.73}/src/sbin/datatailr_run_service.py +0 -0
|
@@ -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
|
|
|
@@ -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}")
|
|
@@ -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)
|
|
@@ -24,6 +24,7 @@ src/datatailr/build/__init__.py
|
|
|
24
24
|
src/datatailr/build/image.py
|
|
25
25
|
src/datatailr/excel/__init__.py
|
|
26
26
|
src/datatailr/excel/addin.py
|
|
27
|
+
src/datatailr/excel/stubs.py
|
|
27
28
|
src/datatailr/scheduler/__init__.py
|
|
28
29
|
src/datatailr/scheduler/arguments_cache.py
|
|
29
30
|
src/datatailr/scheduler/base.py
|
|
@@ -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 = (
|
|
@@ -228,21 +232,17 @@ def main():
|
|
|
228
232
|
} | env
|
|
229
233
|
run_single_command_non_blocking("datatailr_run_excel", user, env)
|
|
230
234
|
elif job_type == "workspace":
|
|
231
|
-
# Set a custom PS1 for the IDE terminal: 17:38|user@my-ide/~/dir/path:$
|
|
232
|
-
env["PS1"] = (
|
|
233
|
-
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\]\$"""
|
|
234
|
-
)
|
|
235
235
|
os.makedirs("/opt/datatailr/var/log", exist_ok=True)
|
|
236
236
|
ide_command = [
|
|
237
237
|
"code-server",
|
|
238
238
|
"--auth=none",
|
|
239
|
-
"--bind-addr=
|
|
239
|
+
"--bind-addr=127.0.0.1:9090",
|
|
240
240
|
f'--app-name="Datatailr IDE {get_env_var("DATATAILR_USER")}"',
|
|
241
241
|
]
|
|
242
242
|
job_name = get_env_var("DATATAILR_JOB_NAME")
|
|
243
243
|
jupyter_command = [
|
|
244
244
|
"jupyter-lab",
|
|
245
|
-
"--ip='
|
|
245
|
+
"--ip='127.0.0.1'",
|
|
246
246
|
"--port=7070",
|
|
247
247
|
"--no-browser",
|
|
248
248
|
"--NotebookApp.token=''",
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|