datatailr 0.1.16__py3-none-any.whl → 0.1.18__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/build/image.py CHANGED
@@ -10,6 +10,7 @@
10
10
 
11
11
  import json
12
12
  import os
13
+ import re
13
14
  from typing import Optional
14
15
 
15
16
  from datatailr import ACL, User
@@ -25,6 +26,7 @@ class Image:
25
26
  def __init__(
26
27
  self,
27
28
  acl: Optional[ACL] = None,
29
+ python_version: str = "3.12",
28
30
  python_requirements: str | list[str] = "",
29
31
  build_script_pre: str = "",
30
32
  build_script_post: str = "",
@@ -33,69 +35,103 @@ class Image:
33
35
  path_to_repo: Optional[str] = None,
34
36
  path_to_module: Optional[str] = None,
35
37
  ):
36
- if acl is None:
37
- signed_user = User.signed_user()
38
- if signed_user is None:
39
- raise ValueError(
40
- "ACL cannot be None. Please provide a valid ACL or ensure a user is signed in."
41
- )
42
- elif not isinstance(acl, ACL):
43
- raise TypeError("acl must be an instance of ACL.")
44
- self.acl = acl or ACL(signed_user)
45
-
46
- if isinstance(python_requirements, str) and os.path.isfile(python_requirements):
47
- with open(python_requirements, "r") as f:
48
- python_requirements = f.read()
49
- elif isinstance(python_requirements, list):
50
- python_requirements = "\n".join(python_requirements)
51
- if not isinstance(python_requirements, str):
38
+ self.python_version = python_version
39
+ self.acl = acl
40
+ self.python_requirements = python_requirements
41
+ self.build_script_pre = build_script_pre
42
+ self.build_script_post = build_script_post
43
+ self.branch_name = branch_name
44
+ self.commit_hash = commit_hash
45
+ self.path_to_repo = path_to_repo
46
+ self.path_to_module = path_to_module
47
+
48
+ def __repr__(self):
49
+ return f"Image(acl={self.acl},)"
50
+
51
+ @property
52
+ def python_version(self):
53
+ return self._python_version
54
+
55
+ @python_version.setter
56
+ def python_version(self, value: str):
57
+ if not isinstance(value, str):
58
+ raise TypeError("python_version must be a string.")
59
+ if not re.match(r"^\d+\.\d+(\.\d+)?$", value):
60
+ raise ValueError("Invalid python_version format. Expected format: X.Y[.Z]")
61
+ self._python_version = value
62
+
63
+ @property
64
+ def python_requirements(self):
65
+ return self._python_requirements
66
+
67
+ @python_requirements.setter
68
+ def python_requirements(self, value: str | list[str]):
69
+ if isinstance(value, str) and os.path.isfile(value):
70
+ with open(value, "r") as f:
71
+ value = f.read()
72
+ elif isinstance(value, list):
73
+ value = "\n".join(value)
74
+ if not isinstance(value, str):
52
75
  raise TypeError(
53
76
  "python_requirements must be a string or a file path to a requirements file."
54
77
  )
55
- self.python_requirements = python_requirements
78
+ self._python_requirements = value
79
+
80
+ @property
81
+ def build_script_pre(self):
82
+ return self._build_script_pre
56
83
 
57
- if os.path.isfile(build_script_pre):
58
- with open(build_script_pre, "r") as f:
59
- build_script_pre = f.read()
60
- if not isinstance(build_script_pre, str):
84
+ @build_script_pre.setter
85
+ def build_script_pre(self, value: str):
86
+ if not isinstance(value, str):
61
87
  raise TypeError(
62
88
  "build_script_pre must be a string or a file path to a script file."
63
89
  )
64
- self.build_script_pre = build_script_pre
90
+ if os.path.isfile(value):
91
+ with open(value, "r") as f:
92
+ value = f.read()
93
+ self._build_script_pre = value
94
+
95
+ @property
96
+ def build_script_post(self):
97
+ return self._build_script_post
65
98
 
66
- if os.path.isfile(build_script_post):
67
- with open(build_script_post, "r") as f:
68
- build_script_post = f.read()
69
- if not isinstance(build_script_post, str):
99
+ @build_script_post.setter
100
+ def build_script_post(self, value: str):
101
+ if not isinstance(value, str):
70
102
  raise TypeError(
71
103
  "build_script_post must be a string or a file path to a script file."
72
104
  )
73
- self.build_script_post = build_script_post
74
- self.branch_name = branch_name
75
- self.commit_hash = commit_hash
76
- self.path_to_repo = path_to_repo
77
- self.path_to_module = path_to_module
105
+ if os.path.isfile(value):
106
+ with open(value, "r") as f:
107
+ value = f.read()
108
+ self._build_script_post = value
78
109
 
79
- def __repr__(self):
80
- return f"Image(acl={self.acl},)"
110
+ @property
111
+ def acl(self):
112
+ return self._acl
113
+
114
+ @acl.setter
115
+ def acl(self, value: Optional[ACL]):
116
+ if value is None:
117
+ signed_user = User.signed_user()
118
+ if signed_user is None:
119
+ raise ValueError(
120
+ "ACL cannot be None. Please provide a valid ACL or ensure a user is signed in."
121
+ )
122
+ elif not isinstance(value, ACL):
123
+ raise TypeError("acl must be an instance of ACL.")
124
+ self._acl = value or ACL(signed_user)
81
125
 
82
126
  def update(self, **kwargs):
83
127
  for key, value in kwargs.items():
84
- if key == "acl" and not isinstance(value, ACL):
85
- raise TypeError("acl must be an instance of ACL.")
86
- elif key == "python_requirements" and not isinstance(value, str):
87
- raise TypeError("python_requirements must be a string.")
88
- elif key == "build_script_pre" and not isinstance(value, str):
89
- raise TypeError("build_script_pre must be a string.")
90
- elif key == "build_script_post" and not isinstance(value, str):
91
- raise TypeError("build_script_post must be a string.")
92
- elif (
128
+ if (
93
129
  key in ["branch_name", "commit_hash", "path_to_repo", "path_to_module"]
94
130
  and value is not None
95
131
  and not isinstance(value, str)
96
132
  ):
97
133
  raise TypeError(f"{key} must be a string or None.")
98
- if key not in self.__dict__:
134
+ if not hasattr(self, key):
99
135
  raise AttributeError(
100
136
  f"'{self.__class__.__name__}' object has no attribute '{key}'"
101
137
  )
@@ -107,6 +143,7 @@ class Image:
107
143
  """
108
144
  return {
109
145
  "acl": self.acl.to_dict(),
146
+ "python_version": self.python_version,
110
147
  "python_requirements": self.python_requirements,
111
148
  "build_script_pre": self.build_script_pre,
112
149
  "build_script_post": self.build_script_post,
@@ -82,6 +82,7 @@ def run_command_as_user(command: str, user: str, env_vars: dict):
82
82
  Run a command as a specific user with the given environment variables.
83
83
  """
84
84
  env_vars.update({"PATH": get_env_var("PATH")})
85
+ env_vars.update({"PYTHONPATH": get_env_var("PYTHONPATH")})
85
86
  env_vars_str = " ".join(f"{key}='{value}'" for key, value in env_vars.items())
86
87
  full_command = f"sudo -u {user} {env_vars_str} {command}"
87
88
  logger.debug(f"Running command: {full_command}")
@@ -89,6 +90,7 @@ def run_command_as_user(command: str, user: str, env_vars: dict):
89
90
 
90
91
 
91
92
  def main():
93
+ logger.info(f"Env inside datatailr_run.py: {os.environ}")
92
94
  user, _ = create_user_and_group()
93
95
  job_type = get_env_var("DATATAILR_JOB_TYPE")
94
96
 
@@ -19,6 +19,7 @@ logger = DatatailrLogger(os.path.abspath(__file__)).get_logger()
19
19
 
20
20
 
21
21
  def run():
22
+ logger.info(f"Env inside datatailr_run.py run(): {os.environ}")
22
23
  logger.info("Running Datatailr batch job")
23
24
  entry_point = os.environ.get("DATATAILR_BATCH_ENTRYPOINT")
24
25
  batch_run_id = os.environ.get("DATATAILR_BATCH_RUN_ID")
@@ -133,8 +133,9 @@ class Job:
133
133
  environment: Optional[Environment] = Environment.DEV,
134
134
  image: Optional[Image] = None,
135
135
  run_as: Optional[Union[str, User]] = None,
136
- resources: Resources = Resources(memory="100m", cpu=1),
136
+ resources: Resources = Resources(memory="128m", cpu=0.25),
137
137
  acl: Optional[ACL] = None,
138
+ python_version: str = "3.12",
138
139
  python_requirements: str = "",
139
140
  build_script_pre: str = "",
140
141
  build_script_post: str = "",
@@ -167,6 +168,7 @@ class Job:
167
168
  if image is None:
168
169
  image = Image(
169
170
  acl=self.acl,
171
+ python_version=python_version,
170
172
  python_requirements=python_requirements,
171
173
  build_script_pre=build_script_pre,
172
174
  build_script_post=build_script_post,
@@ -223,6 +225,8 @@ class Job:
223
225
  if isinstance(self.run_as, User)
224
226
  else self.run_as,
225
227
  "acl": self.acl.to_dict(),
228
+ "memory": self.resources.memory,
229
+ "cpu": self.resources.cpu,
226
230
  }
227
231
  if self.type != JobType.BATCH:
228
232
  job_dict["entrypoint"] = str(self.entrypoint) if self.entrypoint else None
@@ -105,7 +105,7 @@ class Schedule:
105
105
  match = re.match(r"^(.*?)\s*\((.*?)\)$", result)
106
106
  if match:
107
107
  cron_expression, schedule_expression = match.groups()
108
- self.cron_expression = cron_expression.strip()
108
+ self.cron_expression = "0 " + cron_expression.strip()
109
109
  self.schedule_expression = schedule_expression.strip()
110
110
  self.__is_set__ = True
111
111
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datatailr
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: Ready-to-Use Platform That Drives Business Insights
5
5
  Author-email: Datatailr <info@datatailr.com>
6
6
  License-Expression: MIT
@@ -10,23 +10,23 @@ datatailr/utils.py,sha256=mqnnERMyHNAuAgFY4Ry4O4yW0ZjCRtJbjfI5fXVqt2s,1524
10
10
  datatailr/version.py,sha256=N9K8ZxlwFFSz8XSgbgaTWZY4k2J0JKfj698nZ_O2pIU,536
11
11
  datatailr/wrapper.py,sha256=K9ZD76cWey_ikA6C5sKejwRaYBDln4QMg-RcoRGiuFc,7991
12
12
  datatailr/build/__init__.py,sha256=_dA7b4L6wsaAFaSxUoYSJ1oaRqDHDMR20kqoCocSOss,487
13
- datatailr/build/image.py,sha256=xeYKPR6usg0pqJNpbhsYI8t_BB2iWxhY0KBNTWqpb_Q,4939
14
- datatailr/sbin/datatailr_run.py,sha256=xJ5pZ_lEu_-d9liaCy6uO1Y01fg-Gotg66TCv36nSio,6115
13
+ datatailr/build/image.py,sha256=YC8ML-l-sj6TcIBY-DCx_vaeI_7SmL9fPFhHnuxzRh0,5509
14
+ datatailr/sbin/datatailr_run.py,sha256=OU2YTpi4bCRZ0WNMzHN1zzqvt5sh45Az2IGF-OSgp7A,6240
15
15
  datatailr/sbin/datatailr_run_app.py,sha256=AOkutzv4DeKfWZs-ZBciAMKnK4A05SfkVf1ZJnSSFwA,1231
16
- datatailr/sbin/datatailr_run_batch.py,sha256=UWnp96j_G66R_Cape7Bb-rbK6UBLF7Y5_mTlWyGJAVQ,1818
16
+ datatailr/sbin/datatailr_run_batch.py,sha256=u6b4v-sBDNBuvlVL-iey97dNvlsYaGyEKfG0SPnhpgU,1886
17
17
  datatailr/sbin/datatailr_run_excel.py,sha256=Gr_QZgqJrwgRVD9_o4v-2tbvU-QMvNHL7xUvFGhftFc,1163
18
18
  datatailr/sbin/datatailr_run_service.py,sha256=R8eNLN2SGnMtyfLy3vq9isUHr3dRzeBqESTquNK9Iho,1156
19
19
  datatailr/scheduler/__init__.py,sha256=qydHYVtEP6SUWd2CQ6FRdTdRWNz3SbYPJy4FK_wOvMk,1772
20
20
  datatailr/scheduler/arguments_cache.py,sha256=CydYR9o2pqfa4KsPTA1mJSBN-0YF47Q6AmODm4zAJQ4,6254
21
- datatailr/scheduler/base.py,sha256=9E4zmX7-gn8Ozz5iPAy1hlxEfPxUlw9UCNMHAULw9AY,14068
21
+ datatailr/scheduler/base.py,sha256=XZexeOGWHOSI0babRB8XCvAnL3fAQSXYWRfj7srMAkk,14240
22
22
  datatailr/scheduler/batch.py,sha256=77iUufBqRBau9Ku4IivLOKqh-lknclEak8jg2YhsX3c,16437
23
23
  datatailr/scheduler/batch_decorator.py,sha256=LqL1bsupWLn-YEQUvFJYae7R3ogrL5-VodyiiScrkRw,5806
24
24
  datatailr/scheduler/constants.py,sha256=5WWTsfwZ_BA8gVDOTa2AQX9DJ0NzfaWgtY3vrODS2-8,606
25
- datatailr/scheduler/schedule.py,sha256=vzXaBBKMVJeCGD0VxsRPeW80sYReJ83XxWzDHVgLibY,3734
25
+ datatailr/scheduler/schedule.py,sha256=0XJJen2nL1xplRs0Xbjwgq3T-0bFCOrJzkSALdio998,3741
26
26
  datatailr/scheduler/utils.py,sha256=up6oR2iwe6G52LkvgfO394xchXgCYNjOMGRQW3e8PQk,1082
27
- datatailr-0.1.16.dist-info/licenses/LICENSE,sha256=ikKP4_O-UD_b8FuNdKmbzTb6odd0JX085ZW_FAPN3VI,1066
28
- datatailr-0.1.16.dist-info/METADATA,sha256=7hw00HobS04PC5ahDWilCsthIl42Ie6STtdd4x9mpxk,5146
29
- datatailr-0.1.16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
- datatailr-0.1.16.dist-info/entry_points.txt,sha256=YqXfk2At-olW4PUSRkqvy_O3Mbv7uTKCCPuAAiz3Qbg,312
31
- datatailr-0.1.16.dist-info/top_level.txt,sha256=75gntW0X_SKpqxLL6hAPipvpk28GAhJBvoyqN_HohWU,10
32
- datatailr-0.1.16.dist-info/RECORD,,
27
+ datatailr-0.1.18.dist-info/licenses/LICENSE,sha256=ikKP4_O-UD_b8FuNdKmbzTb6odd0JX085ZW_FAPN3VI,1066
28
+ datatailr-0.1.18.dist-info/METADATA,sha256=q1VzkHtrMYwcuwyBEi3iZkIbOVtLdIMaR2uF5lmPOQ4,5146
29
+ datatailr-0.1.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ datatailr-0.1.18.dist-info/entry_points.txt,sha256=YqXfk2At-olW4PUSRkqvy_O3Mbv7uTKCCPuAAiz3Qbg,312
31
+ datatailr-0.1.18.dist-info/top_level.txt,sha256=75gntW0X_SKpqxLL6hAPipvpk28GAhJBvoyqN_HohWU,10
32
+ datatailr-0.1.18.dist-info/RECORD,,