datatailr 0.1.75__py3-none-any.whl → 0.1.76__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/__init__.py CHANGED
@@ -16,6 +16,7 @@ from datatailr.blob import Blob
16
16
  from datatailr.build import Image
17
17
  from datatailr.utils import Environment, is_dt_installed
18
18
  from datatailr.version import __version__
19
+ from datatailr.scheduler import App, Service, ExcelAddin
19
20
 
20
21
  system = dt__System()
21
22
  if isinstance(system, mock_cli_tool):
@@ -33,4 +34,7 @@ __all__ = [
33
34
  "__version__",
34
35
  "__provider__",
35
36
  "is_dt_installed",
37
+ "App",
38
+ "Service",
39
+ "ExcelAddin",
36
40
  ]
datatailr/excel/addin.py CHANGED
@@ -12,6 +12,8 @@ import sys
12
12
  import importlib
13
13
  import subprocess
14
14
  import inspect
15
+ from urllib.parse import urlparse
16
+
15
17
  import numpy as np
16
18
 
17
19
  try:
@@ -45,11 +47,28 @@ def get_package_root(mod):
45
47
  return mod_path
46
48
 
47
49
 
50
+ def matches_annotation(value, annotation):
51
+ if isinstance(value, np.ndarray):
52
+ return True
53
+ if annotation is bool:
54
+ return isinstance(value, bool) or (type(value) is int and value in (0, 1))
55
+ if annotation is float:
56
+ return isinstance(value, float) or (type(value) is int)
57
+ return isinstance(value, annotation)
58
+
59
+
60
+ def extract_hostname(url: str) -> str | None:
61
+ url = url if url else ""
62
+ if "://" not in url:
63
+ url = "//" + url
64
+ return urlparse(url).hostname
65
+
66
+
48
67
  class Addin(AddinBase):
49
68
  def __init__(self, *args, **kwargs):
50
69
  super(Addin, self).__init__(*args, **kwargs)
51
70
 
52
- def run(self, port):
71
+ def run(self, port, ws_port, ide=True):
53
72
  # Excel addin executable will try to import an object literally called "addin"
54
73
  # from a module passed to dt-excel.sh as an argument. So to find which module
55
74
  # to pass to dt-excel.sh, we walk the callstack until a module with "addin"
@@ -91,11 +110,14 @@ class Addin(AddinBase):
91
110
  module_name = os.path.splitext(os.path.basename(filename))[0]
92
111
  dir_name = os.path.dirname(os.path.abspath(filename))
93
112
 
113
+ ide_flag = "-i" if ide else ""
114
+ hostname = extract_hostname(os.environ.get("VSCODE_PROXY_URI"))
115
+
94
116
  subprocess.run(
95
117
  [
96
118
  "bash",
97
119
  "-c",
98
- f'PYTHONPATH="{dir_name}:$PYTHONPATH" /opt/datatailr/bin/dt-excel.sh -n -H "localhost" -l -p {port} -w 8000 {module_name}',
120
+ f'PYTHONPATH="{dir_name}:$PYTHONPATH" /opt/datatailr/bin/dt-excel.sh {ide_flag} -n -H {hostname} -p {port} -w {ws_port} {module_name}',
99
121
  ]
100
122
  )
101
123
 
@@ -115,17 +137,18 @@ class Addin(AddinBase):
115
137
  # be called directly from python code without requiring positional argument for _id
116
138
  _id = args[0]
117
139
 
140
+ bound = signature.bind_partial(**kwargs)
141
+ bound.apply_defaults()
118
142
  for arg in signature.parameters.values():
119
143
  if streaming and arg.name == "queue":
120
144
  continue
121
145
 
122
- if not (
123
- isinstance(kwargs[arg.name], arg.annotation)
124
- or isinstance(kwargs[arg.name], np.ndarray)
146
+ if not matches_annotation(
147
+ bound.arguments[arg.name], arg.annotation
125
148
  ):
126
149
  raise ValueError(
127
150
  "excel/python/dt/excel.py: Got argument of wrong type, expected %s or numpy.ndarray, got %s"
128
- % (arg.annotation, type(kwargs[arg.name]))
151
+ % (arg.annotation, type(bound.arguments[arg.name]))
129
152
  )
130
153
  queue = Queue(self.name.lower() + "." + func.__name__, _id)
131
154
  if not streaming:
@@ -36,12 +36,13 @@ import concurrent.futures
36
36
  import subprocess
37
37
  import os
38
38
  import sys
39
- import stat
40
39
  import shlex
40
+ import shutil
41
41
  import sysconfig
42
42
  from typing import Optional, Tuple
43
43
  from datatailr.logging import DatatailrLogger
44
44
  from datatailr.utils import is_dt_installed
45
+ from datatailr import User
45
46
 
46
47
  logger = DatatailrLogger(os.path.abspath(__file__)).get_logger()
47
48
 
@@ -82,26 +83,67 @@ def create_user_and_group() -> Tuple[str, str]:
82
83
  # Create user if it does not exist
83
84
  # -s /bin/bash: set the shell to bash
84
85
  # -o: allow to create a user with a non-unique UID
85
- # -m: create the home directory for the group - .bashrc file is located in build/.bashrc and copied to /etc/skel/ during image build
86
86
  os.system(
87
- f"getent passwd {user} || useradd -g {group} -s /bin/bash -u {uid} -o -m {user}"
87
+ f"getent passwd {user} || useradd -g {group} -s /bin/bash -u {uid} -o {user}"
88
88
  )
89
89
 
90
- permissions = (
91
- stat.S_IWOTH
92
- | stat.S_IXOTH
93
- | stat.S_IWUSR
94
- | stat.S_IRUSR
95
- | stat.S_IRGRP
96
- | stat.S_IWGRP
97
- | stat.S_IXUSR
98
- | stat.S_IXGRP
99
- )
90
+ for directory in [
91
+ ".cache",
92
+ ".config",
93
+ ".config/code-server",
94
+ ".local",
95
+ "tmp",
96
+ "tmp/.dt",
97
+ ".vscode",
98
+ ]:
99
+ dir_name = f"/home/{user}/{directory}"
100
+ if os.path.exists(dir_name):
101
+ continue
102
+ os.makedirs(dir_name, exist_ok=True)
103
+ os.chown(dir_name, int(uid), int(gid))
104
+ os.chmod(dir_name, 0o773) # rwxrwxr-x
105
+
106
+ copy_dotfiles(user, int(uid), int(gid))
107
+ create_git_config(user, int(uid), int(gid))
108
+ return user, group
100
109
 
101
- os.makedirs(f"/home/{user}/tmp/.dt", exist_ok=True)
102
- os.chmod(f"/home/{user}/tmp/.dt", permissions)
103
110
 
104
- return user, group
111
+ def copy_dotfiles(user: str, uid: int, gid: int):
112
+ home_dir = f"/home/{user}"
113
+ skel_dir = "/etc/skel"
114
+ # Copy dotfiles from /etc/skel to the new user's home directory if they do not already exist
115
+ for root, dirs, files in os.walk(skel_dir):
116
+ rel_path = os.path.relpath(root, skel_dir)
117
+ target_root = os.path.join(home_dir, rel_path) if rel_path != "." else home_dir
118
+
119
+ for d in dirs:
120
+ target_dir = os.path.join(target_root, d)
121
+ if not os.path.exists(target_dir):
122
+ os.makedirs(target_dir, exist_ok=True)
123
+ os.chown(target_dir, uid, gid)
124
+ os.chmod(target_dir, 0o773) # rwxrwxr-x
125
+
126
+ for f in files:
127
+ src_file = os.path.join(root, f)
128
+ target_file = os.path.join(target_root, f)
129
+ if not os.path.exists(target_file):
130
+ shutil.copy(src_file, target_file)
131
+ os.chown(target_file, uid, gid)
132
+ os.chmod(target_file, 0o773) # rwxrwxr-x
133
+
134
+
135
+ def create_git_config(user: str, uid: int, gid: int):
136
+ dt_user = User(user)
137
+ if not os.path.exists(f"/home/{user}/.gitconfig"):
138
+ with open(f"/home/{user}/.gitconfig", "w") as gitconfig_file:
139
+ gitconfig_file.write(
140
+ "[user]\n"
141
+ f" name = {dt_user.first_name} {dt_user.last_name}\n"
142
+ f" email = {dt_user.email}\n"
143
+ f"[init]\n"
144
+ f" defaultBranch = main\n"
145
+ )
146
+ os.chown(f"/home/{user}/.gitconfig", int(uid), int(gid))
105
147
 
106
148
 
107
149
  def prepare_command_argv(command: str | list, user: str, env_vars: dict) -> list[str]:
@@ -225,19 +267,26 @@ def main():
225
267
  host = get_env_var("DATATAILR_HOST", "")
226
268
  entrypoint = get_env_var("DATATAILR_ENTRYPOINT")
227
269
  local = get_env_var("DATATAILR_LOCAL", False)
270
+ dt_environment = get_env_var("DATATAILR_JOB_ENVIRONMENT")
228
271
  env = {
229
272
  "DATATAILR_ENTRYPOINT": entrypoint,
230
273
  "DATATAILR_HOST": host,
231
274
  "DATATAILR_LOCAL": local,
275
+ "DATATAILR_JOB_ENVIRONMENT": dt_environment,
232
276
  } | env
233
277
  return run_single_command_non_blocking("datatailr_run_excel", user, env)
278
+
234
279
  elif job_type == "workspace":
235
280
  os.makedirs("/opt/datatailr/var/log", exist_ok=True)
236
281
  ide_command = [
237
282
  "code-server",
283
+ "--disable-telemetry",
284
+ "--disable-update-check",
238
285
  "--auth=none",
239
286
  "--bind-addr=127.0.0.1:9090",
240
287
  f'--app-name="Datatailr IDE {get_env_var("DATATAILR_USER")}"',
288
+ f"--user-data-dir=/home/{user}/.vscode",
289
+ f"/home/{user}",
241
290
  ]
242
291
  job_name = get_env_var("DATATAILR_JOB_NAME")
243
292
  jupyter_command = [
@@ -247,8 +296,8 @@ def main():
247
296
  "--no-browser",
248
297
  "--NotebookApp.token=''",
249
298
  "--NotebookApp.password=''",
250
- f"--ServerApp.base_url=/workspace/{job_name}/jupyter/",
251
- f"--ServerApp.static_url_prefix=/workspace/{job_name}/jupyter/static/",
299
+ f"--ServerApp.base_url=/workspace/dev/{job_name}/jupyter/",
300
+ f"--ServerApp.file_url_prefix=/workspace/dev/{job_name}/jupyter/static/",
252
301
  f"--ServerApp.root_dir=/home/{user}",
253
302
  ]
254
303
  return run_commands_in_parallel(
@@ -37,6 +37,7 @@ from datatailr.scheduler.base import (
37
37
  from datatailr.scheduler.batch import Batch, BatchJob, DuplicateJobNameError
38
38
  from datatailr.scheduler.batch_decorator import batch_decorator as batch_job
39
39
  from datatailr.scheduler.schedule import Schedule
40
+ from datatailr.scheduler.job import App, Service, ExcelAddin
40
41
 
41
42
  __all__ = [
42
43
  "Job",
@@ -51,4 +52,7 @@ __all__ = [
51
52
  "DuplicateJobNameError",
52
53
  "set_allow_unsafe_scheduling",
53
54
  "Schedule",
55
+ "App",
56
+ "Service",
57
+ "ExcelAddin",
54
58
  ]
@@ -142,7 +142,7 @@ class Job:
142
142
  environment: Optional[Environment] = Environment.DEV,
143
143
  image: Optional[Image] = None,
144
144
  run_as: Optional[Union[str, User]] = None,
145
- resources: Resources = Resources(memory="128m", cpu=0.25),
145
+ resources: Resources = Resources(),
146
146
  acl: Optional[ACL] = None,
147
147
  python_version: str = "3.12",
148
148
  python_requirements: str = "",
@@ -35,9 +35,17 @@ from datatailr.scheduler.schedule import Schedule
35
35
  from datatailr.utils import is_dt_installed, dict_to_env_vars
36
36
 
37
37
  __DAG_CONTEXT__: contextvars.ContextVar = contextvars.ContextVar("dag_context")
38
- __ARGUMENTS_CACHE__ = ArgumentsCache()
39
38
  logger = DatatailrLogger(os.path.abspath(__file__)).get_logger()
40
39
 
40
+ __ARGUMENTS_CACHE__ = None
41
+
42
+
43
+ def get_arguments_cache() -> ArgumentsCache:
44
+ global __ARGUMENTS_CACHE__
45
+ if __ARGUMENTS_CACHE__ is None:
46
+ __ARGUMENTS_CACHE__ = ArgumentsCache()
47
+ return __ARGUMENTS_CACHE__
48
+
41
49
 
42
50
  def get_current_manager():
43
51
  return __DAG_CONTEXT__.get(None)
@@ -514,7 +522,7 @@ class Batch(Job):
514
522
  )
515
523
  for j in self.__jobs
516
524
  }
517
- __ARGUMENTS_CACHE__.add_arguments(self.id, args)
525
+ get_arguments_cache().add_arguments(self.id, args)
518
526
 
519
527
  def save(self) -> Tuple[bool, str]:
520
528
  status = super().save()
@@ -523,11 +531,12 @@ class Batch(Job):
523
531
  return status
524
532
 
525
533
  def run(self) -> Tuple[bool, str]:
526
- self.prepare_args()
527
-
528
534
  if not self.__local_run and is_dt_installed():
529
- return super().run()
535
+ result = super().run()
536
+ self.prepare_args()
537
+ return result
530
538
  else:
539
+ self.prepare_args()
531
540
  os.environ["DATATAILR_BATCH_RUN_ID"] = uuid.uuid4().hex[:8]
532
541
  for step in self.__topological_sort__():
533
542
  for job_id in step:
@@ -23,10 +23,19 @@ from datatailr.scheduler.batch import (
23
23
  from datatailr.scheduler.constants import DEFAULT_TASK_CPU, DEFAULT_TASK_MEMORY
24
24
  from datatailr.scheduler.utils import get_available_env_args
25
25
 
26
- __ARGUMENTS_CACHE__ = ArgumentsCache()
26
+
27
27
  __FUNCTIONS_CREATED_IN_DAG__: dict[Callable, str] = {}
28
28
  logger = DatatailrLogger(__name__).get_logger()
29
29
 
30
+ __ARGUMENTS_CACHE__ = None
31
+
32
+
33
+ def get_arguments_cache() -> ArgumentsCache:
34
+ global __ARGUMENTS_CACHE__
35
+ if __ARGUMENTS_CACHE__ is None:
36
+ __ARGUMENTS_CACHE__ = ArgumentsCache()
37
+ return __ARGUMENTS_CACHE__
38
+
30
39
 
31
40
  def batch_run_id() -> str:
32
41
  return os.getenv("DATATAILR_BATCH_RUN_ID", "unknown")
@@ -79,7 +88,7 @@ def batch_decorator(memory: str = DEFAULT_TASK_MEMORY, cpu: float = DEFAULT_TASK
79
88
  )
80
89
  final_args[all_function_args.index(name)] = value
81
90
  try:
82
- final_kwargs = __ARGUMENTS_CACHE__.get_arguments(
91
+ final_kwargs = get_arguments_cache().get_arguments(
83
92
  dag_id(func),
84
93
  os.getenv("DATATAILR_JOB_NAME", func.__name__),
85
94
  os.getenv("DATATAILR_BATCH_RUN_ID"),
@@ -97,7 +106,7 @@ def batch_decorator(memory: str = DEFAULT_TASK_MEMORY, cpu: float = DEFAULT_TASK
97
106
  for i, arg_name in enumerate(parameters.keys()):
98
107
  final_args[i] = final_kwargs.pop(arg_name, final_args[i])
99
108
  result = func(*final_args, **final_kwargs)
100
- __ARGUMENTS_CACHE__.add_result(
109
+ get_arguments_cache().add_result(
101
110
  batch_run_id(),
102
111
  os.getenv("DATATAILR_JOB_NAME", func.__name__),
103
112
  result,
@@ -8,8 +8,8 @@
8
8
  # of this file, in parts or full, via any medium is strictly prohibited.
9
9
  # *************************************************************************
10
10
 
11
- DEFAULT_TASK_MEMORY = "100m"
12
- DEFAULT_TASK_CPU = 1.0
11
+ DEFAULT_TASK_MEMORY = "128m"
12
+ DEFAULT_TASK_CPU = 0.25
13
13
 
14
14
  BATCH_JOB_ARGUMENTS = (
15
15
  "rundate",
@@ -0,0 +1,112 @@
1
+ from typing import Dict, Optional, Union, Callable
2
+ from datatailr.build import Image
3
+ from datatailr import ACL, Environment, User
4
+ from datatailr.scheduler.base import Job, JobType, EntryPoint, Resources
5
+
6
+
7
+ class App(Job):
8
+ def __init__(
9
+ self,
10
+ name: str,
11
+ entrypoint: Callable,
12
+ environment: Optional[Environment] = Environment.DEV,
13
+ image: Optional[Image] = None,
14
+ run_as: Optional[Union[str, User]] = None,
15
+ resources: Resources = Resources(),
16
+ acl: Optional[ACL] = None,
17
+ python_version: str = "3.12",
18
+ python_requirements: str = "",
19
+ build_script_pre: str = "",
20
+ build_script_post: str = "",
21
+ env_vars: Dict[str, str | int | float | bool] = {},
22
+ update_existing: bool = False,
23
+ ):
24
+ entrypoint = EntryPoint(JobType.APP, entrypoint)
25
+ super().__init__(
26
+ name=name,
27
+ type=JobType.APP,
28
+ entrypoint=entrypoint,
29
+ environment=environment,
30
+ image=image,
31
+ run_as=run_as,
32
+ resources=resources,
33
+ acl=acl,
34
+ python_version=python_version,
35
+ python_requirements=python_requirements,
36
+ build_script_pre=build_script_pre,
37
+ build_script_post=build_script_post,
38
+ env_vars=env_vars,
39
+ update_existing=update_existing,
40
+ )
41
+
42
+
43
+ class Service(Job):
44
+ def __init__(
45
+ self,
46
+ name: str,
47
+ entrypoint: Callable,
48
+ environment: Optional[Environment] = Environment.DEV,
49
+ image: Optional[Image] = None,
50
+ run_as: Optional[Union[str, User]] = None,
51
+ resources: Resources = Resources(),
52
+ acl: Optional[ACL] = None,
53
+ python_version: str = "3.12",
54
+ python_requirements: str = "",
55
+ build_script_pre: str = "",
56
+ build_script_post: str = "",
57
+ env_vars: Dict[str, str | int | float | bool] = {},
58
+ update_existing: bool = False,
59
+ ):
60
+ entrypoint = EntryPoint(JobType.SERVICE, entrypoint)
61
+ super().__init__(
62
+ name=name,
63
+ type=JobType.SERVICE,
64
+ entrypoint=entrypoint,
65
+ environment=environment,
66
+ image=image,
67
+ run_as=run_as,
68
+ resources=resources,
69
+ acl=acl,
70
+ python_version=python_version,
71
+ python_requirements=python_requirements,
72
+ build_script_pre=build_script_pre,
73
+ build_script_post=build_script_post,
74
+ env_vars=env_vars,
75
+ update_existing=update_existing,
76
+ )
77
+
78
+
79
+ class ExcelAddin(Job):
80
+ def __init__(
81
+ self,
82
+ name: str,
83
+ entrypoint: Callable,
84
+ environment: Optional[Environment] = Environment.DEV,
85
+ image: Optional[Image] = None,
86
+ run_as: Optional[Union[str, User]] = None,
87
+ resources: Resources = Resources(),
88
+ acl: Optional[ACL] = None,
89
+ python_version: str = "3.12",
90
+ python_requirements: str = "",
91
+ build_script_pre: str = "",
92
+ build_script_post: str = "",
93
+ env_vars: Dict[str, str | int | float | bool] = {},
94
+ update_existing: bool = False,
95
+ ):
96
+ entrypoint = EntryPoint(JobType.EXCEL, entrypoint)
97
+ super().__init__(
98
+ name=name,
99
+ type=JobType.EXCEL,
100
+ entrypoint=entrypoint,
101
+ environment=environment,
102
+ image=image,
103
+ run_as=run_as,
104
+ resources=resources,
105
+ acl=acl,
106
+ python_version=python_version,
107
+ python_requirements=python_requirements,
108
+ build_script_pre=build_script_pre,
109
+ build_script_post=build_script_post,
110
+ env_vars=env_vars,
111
+ update_existing=update_existing,
112
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datatailr
3
- Version: 0.1.75
3
+ Version: 0.1.76
4
4
  Summary: Ready-to-Use Platform That Drives Business Insights
5
5
  Author-email: Datatailr <info@datatailr.com>
6
6
  License-Expression: MIT
@@ -1,4 +1,4 @@
1
- datatailr/__init__.py,sha256=QTTG8X76BnlQwVx5N4ZQtSbLkgFipZ9NJGAbvtfuk_g,1051
1
+ datatailr/__init__.py,sha256=Ww2YChKqkYXm-KOba9jxURg-7bPLxH6pV5Vlok63Uls,1152
2
2
  datatailr/acl.py,sha256=7hBwF7TP_ADoDryYEFuXx2FCLavLmp3k_F0-sEXg26g,4173
3
3
  datatailr/blob.py,sha256=FHAB90wpt0DgDsejo46iCtZ1N2d6QMpo19uY_7NX1t8,3581
4
4
  datatailr/dt_json.py,sha256=3xmTqDBk68oPl2UW8UVOYPaBw4lAsVg6nDLwcen5nuo,2252
@@ -13,24 +13,25 @@ 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=3UiA7z71ewnEvLSTbcJdPNGWf-uYbeSt_3vbgN42h4E,6354
16
+ datatailr/excel/addin.py,sha256=QSufcJ1U8TaeBfd156loTS3V0EnMvKpPzg4r9JUl-0U,7091
17
17
  datatailr/excel/stubs.py,sha256=RU0Y6PWKRAtK-tgBP5uWrWYW-L3TIGRJwcUUhkA5yxU,830
18
- datatailr/sbin/datatailr_run.py,sha256=RNyR9bLLoWeEEtjAUxEew0yGUW-eGabJGnvyPTTgsUU,10043
18
+ datatailr/sbin/datatailr_run.py,sha256=D18axyX3WvHQa-qv1UXalM0Goxub9igpR5o35GVTI4w,11956
19
19
  datatailr/sbin/datatailr_run_app.py,sha256=itF76XC2F4RK9s6bkoEppEiYwSLHK_5Jai3yvC-kFhY,1501
20
20
  datatailr/sbin/datatailr_run_batch.py,sha256=UWnp96j_G66R_Cape7Bb-rbK6UBLF7Y5_mTlWyGJAVQ,1818
21
21
  datatailr/sbin/datatailr_run_excel.py,sha256=BLWmvxpKEE_8vJhs8E4VWq07FOBof5tlow-AkIEXtHw,1470
22
22
  datatailr/sbin/datatailr_run_service.py,sha256=DO9LGOpz3CVZOJJRHb4ac7AgY_mLbXHGadSyVCeIknc,1212
23
- datatailr/scheduler/__init__.py,sha256=qydHYVtEP6SUWd2CQ6FRdTdRWNz3SbYPJy4FK_wOvMk,1772
23
+ datatailr/scheduler/__init__.py,sha256=nh3CVQ1pM-goUsiKTZZoiYDNRlxNIiH5Z5jnK0T1P0c,1877
24
24
  datatailr/scheduler/arguments_cache.py,sha256=00OE0DhobYteBOnirjulO1ltgGBRamAdCO168O3_Zes,6236
25
- datatailr/scheduler/base.py,sha256=o0N5bgKnwm9C3vOsPnftFbRLqmeB5jciLeNKU5HBfyA,17043
26
- datatailr/scheduler/batch.py,sha256=ZhEf3YkXf1_ieV5ivk4-me60ov9v5r9f9BdkJw84i_0,18475
27
- datatailr/scheduler/batch_decorator.py,sha256=LqL1bsupWLn-YEQUvFJYae7R3ogrL5-VodyiiScrkRw,5806
28
- datatailr/scheduler/constants.py,sha256=5WWTsfwZ_BA8gVDOTa2AQX9DJ0NzfaWgtY3vrODS2-8,606
25
+ datatailr/scheduler/base.py,sha256=28diOUW9AL64tDgNloTESXroJWM-0HaQJz411OMFFo8,17020
26
+ datatailr/scheduler/batch.py,sha256=-me20N0HIazDTfiC_z0tF3im6gDJhFe535KR8p9Lit8,18721
27
+ datatailr/scheduler/batch_decorator.py,sha256=R39tczlgL9OGGXwGUjnOI5oFDCbLXWXZqJnqCdWF3G4,5992
28
+ datatailr/scheduler/constants.py,sha256=38QC6KhCA6farBXukvxVXEWvY6X-dJwFaX_0kPMElJM,607
29
+ datatailr/scheduler/job.py,sha256=6j5qJwA6Fbk22fSnunfRPipclNveG1LDfKTy4JjDBGE,3760
29
30
  datatailr/scheduler/schedule.py,sha256=0XJJen2nL1xplRs0Xbjwgq3T-0bFCOrJzkSALdio998,3741
30
31
  datatailr/scheduler/utils.py,sha256=up6oR2iwe6G52LkvgfO394xchXgCYNjOMGRQW3e8PQk,1082
31
- datatailr-0.1.75.dist-info/licenses/LICENSE,sha256=ikKP4_O-UD_b8FuNdKmbzTb6odd0JX085ZW_FAPN3VI,1066
32
- datatailr-0.1.75.dist-info/METADATA,sha256=byfaQgxDcANT99-XMuT6qjmJAqC2CqnP04cL3HaKPH4,5146
33
- datatailr-0.1.75.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
34
- datatailr-0.1.75.dist-info/entry_points.txt,sha256=YqXfk2At-olW4PUSRkqvy_O3Mbv7uTKCCPuAAiz3Qbg,312
35
- datatailr-0.1.75.dist-info/top_level.txt,sha256=75gntW0X_SKpqxLL6hAPipvpk28GAhJBvoyqN_HohWU,10
36
- datatailr-0.1.75.dist-info/RECORD,,
32
+ datatailr-0.1.76.dist-info/licenses/LICENSE,sha256=ikKP4_O-UD_b8FuNdKmbzTb6odd0JX085ZW_FAPN3VI,1066
33
+ datatailr-0.1.76.dist-info/METADATA,sha256=GqLpAZo8daCZxKdFAKTkkYShZ-gkwHfsx1W1n44It2Y,5146
34
+ datatailr-0.1.76.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ datatailr-0.1.76.dist-info/entry_points.txt,sha256=YqXfk2At-olW4PUSRkqvy_O3Mbv7uTKCCPuAAiz3Qbg,312
36
+ datatailr-0.1.76.dist-info/top_level.txt,sha256=75gntW0X_SKpqxLL6hAPipvpk28GAhJBvoyqN_HohWU,10
37
+ datatailr-0.1.76.dist-info/RECORD,,