datatailr 0.1.72__tar.gz → 0.1.74__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 (42) hide show
  1. {datatailr-0.1.72/src/datatailr.egg-info → datatailr-0.1.74}/PKG-INFO +1 -1
  2. {datatailr-0.1.72 → datatailr-0.1.74}/pyproject.toml +1 -1
  3. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/excel/addin.py +11 -6
  4. datatailr-0.1.74/src/datatailr/excel/stubs.py +37 -0
  5. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/scheduler/base.py +9 -4
  6. {datatailr-0.1.72 → datatailr-0.1.74/src/datatailr.egg-info}/PKG-INFO +1 -1
  7. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr.egg-info/SOURCES.txt +1 -0
  8. {datatailr-0.1.72 → datatailr-0.1.74}/src/sbin/datatailr_run.py +18 -17
  9. {datatailr-0.1.72 → datatailr-0.1.74}/LICENSE +0 -0
  10. {datatailr-0.1.72 → datatailr-0.1.74}/README.md +0 -0
  11. {datatailr-0.1.72 → datatailr-0.1.74}/setup.cfg +0 -0
  12. {datatailr-0.1.72 → datatailr-0.1.74}/setup.py +0 -0
  13. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/__init__.py +0 -0
  14. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/acl.py +0 -0
  15. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/blob.py +0 -0
  16. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/build/__init__.py +0 -0
  17. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/build/image.py +0 -0
  18. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/dt_json.py +0 -0
  19. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/errors.py +0 -0
  20. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/excel/__init__.py +0 -0
  21. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/group.py +0 -0
  22. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/logging.py +0 -0
  23. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/scheduler/__init__.py +0 -0
  24. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/scheduler/arguments_cache.py +0 -0
  25. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/scheduler/batch.py +0 -0
  26. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/scheduler/batch_decorator.py +0 -0
  27. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/scheduler/constants.py +0 -0
  28. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/scheduler/schedule.py +0 -0
  29. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/scheduler/utils.py +0 -0
  30. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/tag.py +0 -0
  31. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/user.py +0 -0
  32. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/utils.py +0 -0
  33. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/version.py +0 -0
  34. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr/wrapper.py +0 -0
  35. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr.egg-info/dependency_links.txt +0 -0
  36. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr.egg-info/entry_points.txt +0 -0
  37. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr.egg-info/requires.txt +0 -0
  38. {datatailr-0.1.72 → datatailr-0.1.74}/src/datatailr.egg-info/top_level.txt +0 -0
  39. {datatailr-0.1.72 → datatailr-0.1.74}/src/sbin/datatailr_run_app.py +0 -0
  40. {datatailr-0.1.72 → datatailr-0.1.74}/src/sbin/datatailr_run_batch.py +0 -0
  41. {datatailr-0.1.72 → datatailr-0.1.74}/src/sbin/datatailr_run_excel.py +0 -0
  42. {datatailr-0.1.72 → datatailr-0.1.74}/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.72
3
+ Version: 0.1.74
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.72"
7
+ version = "0.1.74"
8
8
  description = "Ready-to-Use Platform That Drives Business Insights"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -13,7 +13,11 @@ import importlib
13
13
  import subprocess
14
14
  import inspect
15
15
  import numpy as np
16
- from dt.excel_base import Addin as AddinBase, Queue # type: ignore
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
- id = args[0]
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
- queue = Queue(self.name.lower() + "." + func.__name__, id)
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(Queue(self.name.lower() + "." + func.__name__, id), **kwargs)
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)
@@ -293,6 +294,7 @@ class Job:
293
294
  Returns a tuple of (branch: str, commit_hash: str).
294
295
  """
295
296
  path_to_repo = self.image.path_to_repo or "."
297
+ branch_name, local_commit, return_code = "unknown", "unknown", None
296
298
  try:
297
299
  local_commit = run_shell_command(
298
300
  f"cd {path_to_repo} && git rev-parse HEAD"
@@ -300,6 +302,13 @@ class Job:
300
302
  branch_name = run_shell_command(
301
303
  f"cd {path_to_repo} && git rev-parse --abbrev-ref HEAD"
302
304
  )[0]
305
+
306
+ if (
307
+ os.getenv("DATATAILR_ALLOW_UNSAFE_SCHEDULING", "false").lower()
308
+ == "true"
309
+ ):
310
+ return branch_name, local_commit
311
+
303
312
  return_code = run_shell_command(
304
313
  f"cd {path_to_repo} && git diff --exit-code"
305
314
  )
@@ -308,15 +317,11 @@ class Job:
308
317
  logger.warning(
309
318
  "Git is not installed or not found in PATH. Repository validation is not possible."
310
319
  )
311
- branch_name, local_commit, return_code = "unknown", "unknown", None
312
320
  else:
313
321
  raise RepoValidationError(
314
322
  f"Error accessing git repository at {path_to_repo}: {e}"
315
323
  ) from e
316
324
 
317
- if os.getenv("DATATAILR_ALLOW_UNSAFE_SCHEDULING", "false").lower() == "true":
318
- return branch_name, local_commit
319
-
320
325
  is_committed = return_code is not None and return_code[1] == 0
321
326
 
322
327
  if not is_committed:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datatailr
3
- Version: 0.1.72
3
+ Version: 0.1.74
4
4
  Summary: Ready-to-Use Platform That Drives Business Insights
5
5
  Author-email: Datatailr <info@datatailr.com>
6
6
  License-Expression: MIT
@@ -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
@@ -35,6 +35,7 @@
35
35
  import concurrent.futures
36
36
  import subprocess
37
37
  import os
38
+ import sys
38
39
  import stat
39
40
  import shlex
40
41
  import sysconfig
@@ -46,7 +47,7 @@ logger = DatatailrLogger(os.path.abspath(__file__)).get_logger()
46
47
 
47
48
  if not is_dt_installed():
48
49
  logger.error("Datatailr is not installed.")
49
- # sys.exit(1) # TODO: Uncomment after testing
50
+ sys.exit(1)
50
51
 
51
52
 
52
53
  def get_env_var(name: str, default: str | None = None) -> str:
@@ -75,11 +76,15 @@ def create_user_and_group() -> Tuple[str, str]:
75
76
  gid = get_env_var("DATATAILR_GID")
76
77
 
77
78
  # Create group if it does not exist
79
+ # -o: allow to create a group with a non-unique GID
78
80
  os.system(f"getent group {group} || groupadd {group} -g {gid} -o")
79
81
 
80
82
  # Create user if it does not exist
83
+ # -s /bin/bash: set the shell to bash
84
+ # -M: do not create home directory (it is already created on the NFS volume)
85
+ # -o: allow to create a user with a non-unique UID
81
86
  os.system(
82
- f"getent passwd {user} || useradd -g {group} -s /bin/bash -m {user} -u {uid} -o"
87
+ f"getent passwd {user} || useradd -g {group} -s /bin/bash -M {user} -u {uid} -o"
83
88
  )
84
89
 
85
90
  permissions = (
@@ -201,7 +206,7 @@ def main():
201
206
  "DATATAILR_BATCH_ID": batch_id,
202
207
  "DATATAILR_BATCH_ENTRYPOINT": entrypoint,
203
208
  } | env
204
- run_single_command_non_blocking("datatailr_run_batch", user, env)
209
+ return run_single_command_non_blocking("datatailr_run_batch", user, env)
205
210
  elif job_type == "service":
206
211
  port = get_env_var("DATATAILR_SERVICE_PORT", 8080)
207
212
  entrypoint = get_env_var("DATATAILR_ENTRYPOINT")
@@ -209,16 +214,15 @@ def main():
209
214
  "DATATAILR_ENTRYPOINT": entrypoint,
210
215
  "DATATAILR_SERVICE_PORT": port,
211
216
  } | env
212
- run_single_command_non_blocking("datatailr_run_service", user, env)
217
+ return run_single_command_non_blocking("datatailr_run_service", user, env)
213
218
  elif job_type == "app":
214
219
  entrypoint = get_env_var("DATATAILR_ENTRYPOINT")
215
220
  env = {
216
221
  "DATATAILR_ENTRYPOINT": entrypoint,
217
222
  } | env
218
- run_single_command_non_blocking("datatailr_run_app", user, env)
223
+ return run_single_command_non_blocking("datatailr_run_app", user, env)
219
224
  elif job_type == "excel":
220
225
  host = get_env_var("DATATAILR_HOST", "")
221
- local = get_env_var("DATATAILR_LOCAL", "")
222
226
  entrypoint = get_env_var("DATATAILR_ENTRYPOINT")
223
227
  local = get_env_var("DATATAILR_LOCAL", False)
224
228
  env = {
@@ -226,23 +230,19 @@ def main():
226
230
  "DATATAILR_HOST": host,
227
231
  "DATATAILR_LOCAL": local,
228
232
  } | env
229
- run_single_command_non_blocking("datatailr_run_excel", user, env)
233
+ return 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=0.0.0.0:9090",
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=''",
@@ -251,7 +251,7 @@ def main():
251
251
  f"--ServerApp.static_url_prefix=/workspace/{job_name}/jupyter/static/",
252
252
  f"--ServerApp.root_dir=/home/{user}",
253
253
  ]
254
- run_commands_in_parallel(
254
+ return run_commands_in_parallel(
255
255
  [ide_command, jupyter_command], user, env, ["code-server", "jupyter"]
256
256
  )
257
257
 
@@ -262,8 +262,9 @@ def main():
262
262
  if __name__ == "__main__":
263
263
  try:
264
264
  logger.debug("Starting job execution...")
265
- main()
266
- logger.debug("Job executed successfully.")
265
+ rc = main()
266
+ logger.debug(f"Job executed successfully, with code {rc}")
267
+ raise SystemExit(rc)
267
268
  except Exception as e:
268
269
  logger.error(f"Error during job execution: {e}")
269
- raise
270
+ raise SystemExit(1)
File without changes
File without changes
File without changes
File without changes