datatailr 0.1.0__py3-none-any.whl → 0.1.2__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/user.py ADDED
@@ -0,0 +1,201 @@
1
+ # *************************************************************************
2
+ #
3
+ # Copyright (c) 2025 - Datatailr Inc.
4
+ # All Rights Reserved.
5
+ #
6
+ # This file is part of Datatailr and subject to the terms and conditions
7
+ # defined in 'LICENSE.txt'. Unauthorized copying and/or distribution
8
+ # of this file, in parts or full, via any medium is strictly prohibited.
9
+ # *************************************************************************
10
+
11
+ from typing import Optional
12
+
13
+ from datatailr import dt__User
14
+
15
+
16
+ class User:
17
+ """Representing a Datatailr User
18
+ This class provides methods to interact with the Datatailr User API.
19
+ It allows you to create, update, delete, and manage users within the Datatailr platform.
20
+ Attributes:
21
+ first_name (str): The first name of the user.
22
+ last_name (str): The last name of the user.
23
+ name (str): The username of the user.
24
+ email (str): The email address of the user.
25
+ user_id (int): The unique identifier for the user.
26
+ primary_group_id (int): The primary group of the user.
27
+ is_system_user (bool): Indicates if the user is a system user.
28
+ Static Methods:
29
+ signed_user() -> Optional['User']:
30
+ Retrieve the currently signed-in user, if available.
31
+ add(name: str, first_name: str = None, last_name: str = None, email: str = None, password: str = None, primary_group_id: int = None, is_system_user: bool = False) -> 'User':
32
+ Create a new user with the specified username, first name, last name, and email.
33
+ get(name: str) -> 'User':
34
+ Retrieve a user by their username.
35
+ exists(name: str) -> bool:
36
+ Check if a user exists by their username.
37
+ ls() -> list:
38
+ List all users available in the Datatailr platform.
39
+ remove(name: str) -> None:
40
+ Remove a user by their username.
41
+ Instance Methods:
42
+ verify() -> None:
43
+ Refresh the user information from the Datatailr API.
44
+ """
45
+
46
+ # Datatailr User API Client
47
+ __client__ = dt__User()
48
+
49
+ def __init__(self, name):
50
+ self.__name = name
51
+ self.__first_name = None
52
+ self.__last_name = None
53
+ self.__email = None
54
+ self.__user_id = None
55
+ self.__primary_group_id = None
56
+ self.__is_system_user = False
57
+ self.__expiry__ = None
58
+ self.__signature__ = None
59
+
60
+ self.__refresh__()
61
+
62
+ def __repr__(self):
63
+ return (
64
+ f"User(name={self.name}, first_name={self.first_name}, "
65
+ f"last_name={self.last_name}, email={self.email}, "
66
+ f"user_id={self.user_id}, primary_group_id={self.primary_group_id}, "
67
+ f"is_system_user={self.is_system_user})"
68
+ )
69
+
70
+ def __str__(self):
71
+ return f"<User: {self.name} | {self.user_id}>"
72
+
73
+ def __eq__(self, other):
74
+ if not isinstance(other, User):
75
+ return NotImplemented
76
+ return (
77
+ self.user_id == other.user_id
78
+ and self.name == other.name
79
+ and self.email == other.email
80
+ and self.primary_group_id == other.primary_group_id
81
+ and self.is_system_user == other.is_system_user
82
+ and self.first_name == other.first_name
83
+ and self.last_name == other.last_name
84
+ )
85
+
86
+ def __refresh__(self):
87
+ if not self.name:
88
+ raise ValueError("Name is not set. Cannot refresh user.")
89
+ user = self.__client__.get(self.name)
90
+ if user:
91
+ self.__name = user["name"]
92
+ self.__first_name = user["first_name"]
93
+ self.__last_name = user["last_name"]
94
+ self.__email = user.get("email")
95
+ self.__user_id = user["user_id"]
96
+ self.__primary_group_id = user["primary_group_id"]
97
+ self.__is_system_user = user["is_system"]
98
+
99
+ @property
100
+ def first_name(self):
101
+ return self.__first_name
102
+
103
+ @property
104
+ def last_name(self):
105
+ return self.__last_name
106
+
107
+ @property
108
+ def name(self):
109
+ return self.__name
110
+
111
+ @property
112
+ def email(self):
113
+ return self.__email
114
+
115
+ @property
116
+ def user_id(self):
117
+ return self.__user_id
118
+
119
+ @property
120
+ def primary_group_id(self):
121
+ return self.__primary_group_id
122
+
123
+ @property
124
+ def primary_group(self):
125
+ if self.__primary_group_id is not None:
126
+ from datatailr.group import Group
127
+
128
+ return Group.get(self.__primary_group_id)
129
+ return None
130
+
131
+ @property
132
+ def is_system_user(self):
133
+ return self.__is_system_user
134
+
135
+ @staticmethod
136
+ def get(name: str) -> Optional["User"]:
137
+ return User(name)
138
+
139
+ @staticmethod
140
+ def signed_user() -> "User":
141
+ user_signature_and_expiry = User.__client__.signed_user()
142
+ if user_signature_and_expiry:
143
+ user = User(name=user_signature_and_expiry["name"])
144
+ user.__expiry__ = user_signature_and_expiry["expiry"]
145
+ user.__signature__ = user_signature_and_expiry["signature"]
146
+ return user
147
+ raise PermissionError(
148
+ "No signed user found. Please ensure you are signed in to Datatailr."
149
+ )
150
+
151
+ @staticmethod
152
+ def add(
153
+ name: str,
154
+ first_name: str,
155
+ last_name: str,
156
+ email: str,
157
+ password: str,
158
+ primary_group: int,
159
+ is_system_user: bool = False,
160
+ ) -> Optional["User"]:
161
+ if is_system_user:
162
+ if password is not None:
163
+ raise Warning(
164
+ "Password is not required for system users. It will be ignored."
165
+ )
166
+ User.__client__.add(
167
+ name,
168
+ first_name=first_name,
169
+ last_name=last_name,
170
+ email=email,
171
+ primary_group=primary_group,
172
+ system=is_system_user,
173
+ )
174
+ else:
175
+ User.__client__.add(
176
+ name,
177
+ first_name=first_name,
178
+ last_name=last_name,
179
+ email=email,
180
+ password=password,
181
+ primary_group=primary_group,
182
+ system=is_system_user,
183
+ )
184
+ return User.get(name)
185
+
186
+ @staticmethod
187
+ def exists(name: str) -> bool:
188
+ return User.__client__.exists(name)
189
+
190
+ @staticmethod
191
+ def ls() -> list:
192
+ users = User.__client__.ls()
193
+ return [User.get(user["name"]) for user in users]
194
+
195
+ @staticmethod
196
+ def remove(name: str) -> None:
197
+ User.__client__.rm(name)
198
+ return None
199
+
200
+ def verify(self) -> None:
201
+ return self.__client__.verify(self.name, self.__expiry__, self.__signature__)
datatailr/utils.py ADDED
@@ -0,0 +1,35 @@
1
+ # *************************************************************************
2
+ #
3
+ # Copyright (c) 2025 - Datatailr Inc.
4
+ # All Rights Reserved.
5
+ #
6
+ # This file is part of Datatailr and subject to the terms and conditions
7
+ # defined in 'LICENSE.txt'. Unauthorized copying and/or distribution
8
+ # of this file, in parts or full, via any medium is strictly prohibited.
9
+ # *************************************************************************
10
+
11
+ import shutil
12
+ from enum import Enum
13
+
14
+
15
+ class Environment(Enum):
16
+ """
17
+ Enum representing different environments for DataTailr jobs.
18
+ """
19
+
20
+ DEV = "dev"
21
+ PRE = "pre"
22
+ PROD = "prod"
23
+
24
+ def __str__(self):
25
+ return self.value
26
+
27
+ def __repr__(self):
28
+ return f"Environment.{self.name}('{self.value}')"
29
+
30
+
31
+ def is_dt_installed():
32
+ """
33
+ Check if DataTailr is installed by looking for the 'dt' command in the system PATH.
34
+ """
35
+ return shutil.which("dt") is not None
datatailr/version.py ADDED
@@ -0,0 +1,14 @@
1
+ import importlib.metadata
2
+
3
+ try:
4
+ __version__ = importlib.metadata.version("datatailr")
5
+ except importlib.metadata.PackageNotFoundError:
6
+ import toml # type: ignore
7
+
8
+ try:
9
+ # load the version from pyproject.toml which is located two levels up relative to this file
10
+ this_file_path = __file__
11
+ pyproject_path = this_file_path.rsplit("/", 3)[0] + "/pyproject.toml"
12
+ __version__ = toml.load(pyproject_path)["project"]["version"]
13
+ except (FileNotFoundError, KeyError):
14
+ __version__ = "unknown"
datatailr/wrapper.py ADDED
@@ -0,0 +1,204 @@
1
+ # *************************************************************************
2
+ #
3
+ # Copyright (c) 2025 - Datatailr Inc.
4
+ # All Rights Reserved.
5
+ #
6
+ # This file is part of Datatailr and subject to the terms and conditions
7
+ # defined in 'LICENSE.txt'. Unauthorized copying and/or distribution
8
+ # of this file, in parts or full, via any medium is strictly prohibited.
9
+ # *************************************************************************
10
+
11
+ import json
12
+ import os
13
+ import subprocess
14
+
15
+ from datatailr.utils import is_dt_installed
16
+
17
+ if is_dt_installed() or os.path.exists("/opt/datatailr/etc/api.json"):
18
+ API_JSON_PATH = os.path.join("/opt", "datatailr", "etc", "api.json")
19
+ CLI_TOOL = "dt"
20
+ else:
21
+ # For running local tests, use api.json from the repo and a mock CLI tool
22
+ API_JSON_PATH = os.path.join(
23
+ os.path.dirname(__file__), "..", "..", "..", "..", "dt", "api.json"
24
+ )
25
+ CLI_TOOL = "echo"
26
+
27
+
28
+ def type_map(arg_type):
29
+ mapping = {
30
+ "String": "str",
31
+ "file": "str",
32
+ "boolean": "bool",
33
+ "int": "int",
34
+ "float": "float",
35
+ }
36
+ return mapping.get(arg_type, "str")
37
+
38
+
39
+ def add_quotes(arg):
40
+ """Add quotes to the argument if it contains spaces or special characters."""
41
+ if isinstance(arg, str) and (" " in arg or '"' in arg or "'" in arg):
42
+ return f'"{arg}"'
43
+ return str(arg)
44
+
45
+
46
+ def make_method(cmd_name, sub_name, sub_def):
47
+ arg_names = sub_def.get("non_options", {}).get("arg_names", [])
48
+ arg_types = sub_def.get("non_options", {}).get("arg_types", [])
49
+ min_args = sub_def.get("non_options", {}).get("min", len(arg_names))
50
+ max_args = sub_def.get("non_options", {}).get("max", len(arg_names))
51
+ options = sub_def.get("options", [])
52
+ option_names = [opt[1] for opt in options]
53
+ description = sub_def.get("description", "")
54
+ help_text = sub_def.get("help", "")
55
+ return_type = "str"
56
+
57
+ # Build docstring
58
+ doc = f"""{description}\n\n{help_text}\n"""
59
+ if arg_names:
60
+ doc += "\nArgs:\n"
61
+ for n, t in zip(arg_names, arg_types):
62
+ doc += f" {n} ({type_map(t)}):\n"
63
+ if options:
64
+ doc += "\nOptions:\n"
65
+ for opt in options:
66
+ short, long, opt_type = opt[:3]
67
+ doc += f" --{long} ({opt_type})\n"
68
+ doc += f"\nReturns:\n {return_type}\n"
69
+
70
+ def method(self, *args, **kwargs):
71
+ # Accept required args as either positional or keyword arguments
72
+ all_args = list(args)
73
+ used_kwargs = set()
74
+ kwargs = {k.replace("_", "-"): v for k, v in kwargs.items()}
75
+ # Fill missing positional args from kwargs if available
76
+ for i in range(len(all_args), len(arg_names)):
77
+ arg_name = arg_names[i]
78
+ if arg_name in kwargs:
79
+ all_args.append(kwargs[arg_name])
80
+ used_kwargs.add(arg_name)
81
+ # Argument count check
82
+ missing = []
83
+ if len(all_args) < min_args:
84
+ for i in range(len(all_args), min_args):
85
+ if i < len(arg_names):
86
+ missing.append(
87
+ f"{arg_names[i]}: {type_map(arg_types[i]) if i < len(arg_types) else 'str'}"
88
+ )
89
+ if not (min_args <= len(all_args) <= max_args):
90
+ msg = f"{cmd_name}{' ' + sub_name if sub_name else ''} expects between {min_args} and {max_args} arguments, got {len(all_args)}."
91
+ if missing:
92
+ msg += f" Missing: {', '.join(missing)}"
93
+ raise TypeError(msg)
94
+ # Argument type check
95
+ for i, (arg, expected_type) in enumerate(zip(all_args, arg_types)):
96
+ py_type = eval(type_map(expected_type))
97
+ if not isinstance(arg, py_type):
98
+ raise TypeError(
99
+ f"Argument '{arg_names[i]}' must be of type {py_type.__name__}, got {type(arg).__name__}"
100
+ )
101
+ # Disallow unexpected kwargs (only allow options and used arg-names)
102
+ allowed_kwargs = set(option_names) | set(arg_names)
103
+ unexpected_kwargs = set(kwargs.keys()) - allowed_kwargs
104
+ if unexpected_kwargs:
105
+ raise TypeError(
106
+ f"{cmd_name}{' ' + sub_name if sub_name else ''} got unexpected keyword arguments: {', '.join(unexpected_kwargs)}. Expected: {', '.join(allowed_kwargs)}"
107
+ )
108
+ cmd = [self.cli_tool, cmd_name]
109
+ if sub_name:
110
+ cmd.append(sub_name)
111
+ for arg in all_args:
112
+ cmd.append(add_quotes(str(arg)))
113
+ # Only pass option kwargs (not those used for required args)
114
+ if "json" in allowed_kwargs:
115
+ kwargs["json"] = True # Ensure JSON output if 'json' is an option
116
+ for k, v in kwargs.items():
117
+ if k in option_names:
118
+ # Find the option definition
119
+ opt_def = next((opt for opt in options if opt[1] == k), None)
120
+ if opt_def and opt_def[2] == "no_argument":
121
+ if v:
122
+ cmd.append(f"--{k}")
123
+ # If v is False, omit it (do nothing)
124
+ else:
125
+ # For options that require a value
126
+ cmd.append(f"--{k}={v}")
127
+ result = subprocess.run(cmd, capture_output=True, text=True)
128
+ if result.returncode != 0:
129
+ raise RuntimeError(f"Command failed: {' '.join(cmd)}\n{result.stderr}")
130
+ try:
131
+ return json.loads(result.stdout) if result.stdout else None
132
+ except json.JSONDecodeError:
133
+ return result.stdout.strip()
134
+
135
+ method.__doc__ = doc
136
+ return method
137
+
138
+
139
+ def create_class(cmd_name, command):
140
+ class_name = cmd_name.capitalize()
141
+ sub_commands = command.get("sub_commands", {})
142
+ # Create a new class with only cli_tool attribute
143
+ cls = type(class_name, (object,), {"cli_tool": CLI_TOOL})
144
+ if sub_commands:
145
+ for sub_name, sub_def in sub_commands.items():
146
+ sub_name = (
147
+ sub_name # Convert hyphens to underscores for Python method names
148
+ )
149
+ method = make_method(cmd_name, sub_name, sub_def)
150
+ setattr(cls, sub_name.replace("-", "_"), method)
151
+ else:
152
+ method = make_method(cmd_name, None, command)
153
+ setattr(cls, cmd_name, method)
154
+ return cls
155
+
156
+
157
+ # Load API JSON and create classes at import time
158
+ if os.path.exists(API_JSON_PATH):
159
+ with open(API_JSON_PATH, "r") as f:
160
+ api = json.load(f)
161
+
162
+ for cmd_name, command in api.items():
163
+ cls = create_class(cmd_name, command)
164
+ globals()["dt__" + cmd_name.capitalize()] = cls
165
+
166
+
167
+ class mock_cli_tool:
168
+ """
169
+ Mock CLI tool for local usage of the DataTailr platform.
170
+ This function simulates the CLI tool behavior by returning a predefined response.
171
+ """
172
+
173
+ # make it possible to use any function, even if it doesn't eist in the class
174
+ def mock_method(self, name, *args, **kwargs):
175
+ def fun(*args, **kwargs):
176
+ return {"mocked": name, "args": args, "kwargs": kwargs}
177
+
178
+ return fun
179
+
180
+ def __getattr__(self, name):
181
+ return self.mock_method(name)
182
+
183
+
184
+ dt__User = globals().get("dt__User", mock_cli_tool)
185
+ dt__Group = globals().get("dt__Group", mock_cli_tool)
186
+ dt__Job = globals().get("dt__Job", mock_cli_tool)
187
+ dt__Blob = globals().get("dt__Blob", mock_cli_tool)
188
+ dt__Dns = globals().get("dt__Dns", mock_cli_tool)
189
+ dt__System = globals().get("dt__System", mock_cli_tool)
190
+ dt__Sms = globals().get("dt__Sms", mock_cli_tool)
191
+ dt__Group = globals().get("dt__Group", mock_cli_tool)
192
+ dt__Job = globals().get("dt__Job", mock_cli_tool)
193
+ dt__Blob = globals().get("dt__Blob", mock_cli_tool)
194
+ dt__Dns = globals().get("dt__Dns", mock_cli_tool)
195
+ dt__System = globals().get("dt__System", mock_cli_tool)
196
+ dt__Sms = globals().get("dt__Sms", mock_cli_tool)
197
+ dt__Email = globals().get("dt__Email", mock_cli_tool)
198
+ dt__Kv = globals().get("dt__Kv", mock_cli_tool)
199
+ dt__Log = globals().get("dt__Log", mock_cli_tool)
200
+ dt__Node = globals().get("dt__Node", mock_cli_tool)
201
+ dt__Tag = globals().get("dt__Tag", mock_cli_tool)
202
+ dt__Registry = globals().get("dt__Registry", mock_cli_tool)
203
+ dt__Service = globals().get("dt__Service", mock_cli_tool)
204
+ dt__Settings = globals().get("dt__Settings", mock_cli_tool)
@@ -0,0 +1,24 @@
1
+ Metadata-Version: 2.4
2
+ Name: datatailr
3
+ Version: 0.1.2
4
+ Summary: The datatailr package
5
+ Author-email: Datatailr <pypi@datatailr.com>
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.7
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Provides-Extra: dev
13
+ Requires-Dist: ruff; extra == "dev"
14
+ Requires-Dist: pre-commit; extra == "dev"
15
+ Requires-Dist: mypy; extra == "dev"
16
+ Requires-Dist: types-setuptools; extra == "dev"
17
+ Requires-Dist: toml; extra == "dev"
18
+ Dynamic: license-file
19
+
20
+ # datatailr
21
+
22
+ Datatailr empowers your team to streamline analytics and data workflows from idea to production without infrastructure hurdles.
23
+
24
+ Visit [our website](https://www.datatailr.com/) for more!
@@ -0,0 +1,29 @@
1
+ datatailr/__init__.py,sha256=Z_lrDoLOnfiVlVcp5a-jCmjCNsA3Ypne0Lkv6tOTxjA,1390
2
+ datatailr/acl.py,sha256=gLuzw6FLFYLVoyXOS_oHMfd5uGKKzlDqR1WBdN_AGwQ,2862
3
+ datatailr/blob.py,sha256=VImsbKBaYP6oG2Wiy4oPr6zxtUibEHpfI8p8nE1wj14,3195
4
+ datatailr/dt_json.py,sha256=oos6hwC4UxT4TEbbXNSozQGhwnc_bfpo-Y2rj24ks9A,1422
5
+ datatailr/errors.py,sha256=0CHvBOlzvDWoePk_preMy2qKlsztKCuQNdaQDbhNyaU,204
6
+ datatailr/group.py,sha256=-zDktOVhbGfmNn-3eMqDSyL6Sr2uz0gkHmCHtMrHMnA,4391
7
+ datatailr/logging.py,sha256=b3Uaumdo1ZZOaTnD-7iH1rlieWsllQSijNn9rX4svuo,3053
8
+ datatailr/user.py,sha256=2N9HzeHixwZ_Hsu0VM7YYbyJCoemGW9eASzT1rriycQ,6615
9
+ datatailr/utils.py,sha256=eHXOc7VwIUR8ryn5jBmw5QI00ARERJwXV5oICdVRnmQ,937
10
+ datatailr/version.py,sha256=N9K8ZxlwFFSz8XSgbgaTWZY4k2J0JKfj698nZ_O2pIU,536
11
+ datatailr/wrapper.py,sha256=Sm6OruuwOKx2tA01ftFEvp4Hfl9yWY_BVXwHbWCTRzE,8141
12
+ datatailr/build/__init__.py,sha256=_dA7b4L6wsaAFaSxUoYSJ1oaRqDHDMR20kqoCocSOss,487
13
+ datatailr/build/image.py,sha256=P2MiGxpzuZ6hOm9JubkLoOq-RdzKYnXbKJHiryIbJeA,3103
14
+ datatailr/sbin/run_job.py,sha256=B3H3UI3zpll7zVm7lZLsfPtnRlA6jjk8s_D_w89pvC4,2175
15
+ datatailr/scheduler/__init__.py,sha256=YtCnv9vuX-EPGr3WBXvXJIlLsZ94mW1dBzI6h7Yjcu0,1009
16
+ datatailr/scheduler/arguments_cache.py,sha256=-JnAWXfHMSSkYJx8iYt9JgvdPgR-1Z8DcN5Kvcx9Amo,4574
17
+ datatailr/scheduler/base.py,sha256=trsW3ETK0X00qoYYRHQrkfxoHEWhwgTrsJFVrhu6saY,7623
18
+ datatailr/scheduler/batch.py,sha256=daxFRl5894Hb3cKEm_pubXchNwN8qjVuFi0G-zMj-kI,10712
19
+ datatailr/scheduler/batch_decorator.py,sha256=o6DAEODwsfYx9uYwjnaJZ9iUmqbFH2wMh-jz_L5bgNo,4598
20
+ datatailr/scheduler/constants.py,sha256=ISG5uMnVPbGbjaaulU0xdmSggnd-DMr9ed0WTAZSUmU,604
21
+ datatailr/scheduler/utils.py,sha256=YHtAc5sCwfgiClr5G6R3hfAjdlrFdnNW2l-3XwPZLXM,1070
22
+ datatailr-0.1.2.dist-info/licenses/LICENSE,sha256=ikKP4_O-UD_b8FuNdKmbzTb6odd0JX085ZW_FAPN3VI,1066
23
+ test_module/__init__.py,sha256=OF9XaL3RKdbWD5Ug4L-ufLqbykSt_rTK6gqZr4uBJ8g,576
24
+ test_module/test_submodule.py,sha256=O07fFbzJEy5rf1vdlYzPvs8v0IxHFg-CaYMqaHkskbc,1294
25
+ datatailr-0.1.2.dist-info/METADATA,sha256=yfNet0SvA-XFRMQa8YYFJRduScQFdB3j4wVEz7XU3oQ,774
26
+ datatailr-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ datatailr-0.1.2.dist-info/entry_points.txt,sha256=4lNE9VXvztJdIQsODI308v9FRzkVgmMu-VKGEceNxJs,59
28
+ datatailr-0.1.2.dist-info/top_level.txt,sha256=UZOKaWS1kZGGwV7hP476-EcSUJBNspxVSSp9WqtORzk,22
29
+ datatailr-0.1.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.8.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ run_dt_job = datatailr.sbin.run_job:main
@@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
-
@@ -0,0 +1,2 @@
1
+ datatailr
2
+ test_module
@@ -0,0 +1,17 @@
1
+ # *************************************************************************
2
+ #
3
+ # Copyright (c) 2025 - Datatailr Inc.
4
+ # All Rights Reserved.
5
+ #
6
+ # This file is part of Datatailr and subject to the terms and conditions
7
+ # defined in 'LICENSE.txt'. Unauthorized copying and/or distribution
8
+ # of this file, in parts or full, via any medium is strictly prohibited.
9
+ # *************************************************************************
10
+
11
+ from .test_submodule import foo
12
+ from .test_submodule import test_function as test_function
13
+
14
+ __all__ = [
15
+ "test_function",
16
+ "foo",
17
+ ]
@@ -0,0 +1,38 @@
1
+ # *************************************************************************
2
+ #
3
+ # Copyright (c) 2025 - Datatailr Inc.
4
+ # All Rights Reserved.
5
+ #
6
+ # This file is part of Datatailr and subject to the terms and conditions
7
+ # defined in 'LICENSE.txt'. Unauthorized copying and/or distribution
8
+ # of this file, in parts or full, via any medium is strictly prohibited.
9
+ # *************************************************************************
10
+
11
+ from datatailr.logging import DatatailrLogger
12
+ from datatailr.scheduler import batch
13
+
14
+ logger = DatatailrLogger(__name__).get_logger()
15
+
16
+
17
+ @batch()
18
+ def foo():
19
+ logger.info(f"Running foo from {__name__}")
20
+ return "Hello from foo in test_submodule"
21
+
22
+
23
+ @batch()
24
+ def test_function(a, b, rundate=None):
25
+ """Test function for the submodule."""
26
+ logger.info(f"Running test_function from test_submodule, {__name__}")
27
+ logger.info(f"Arguments: a={a}, b={b}, rundate={rundate}")
28
+
29
+ return f"args: ({a}, {b}, {rundate}), kwargs: {{}}"
30
+
31
+
32
+ @batch()
33
+ def another_test_function(x, y, z=None, rundate=None):
34
+ """Another test function for the submodule."""
35
+ logger.info(f"Running another_test_function from test_submodule, {__name__}")
36
+ logger.info(f"Arguments: x={x}, y={y}, z={z}, rundate={rundate}")
37
+
38
+ return f"args: ({x}, {y}, {z}), kwargs: {{}}"
@@ -1,17 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: datatailr
3
- Version: 0.1.0
4
- Summary: The datatailr package
5
- Author-email: Datatailr <pypi@datatailr.com>
6
- License: MIT
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: License :: OSI Approved :: MIT License
9
- Classifier: Operating System :: OS Independent
10
- Requires-Python: >=3.7
11
- Description-Content-Type: text/markdown
12
- License-File: LICENSE
13
- Dynamic: license-file
14
-
15
- # datatailr
16
-
17
- The `datatailr` package
@@ -1,6 +0,0 @@
1
- datatailr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- datatailr-0.1.0.dist-info/licenses/LICENSE,sha256=RGBbm4j6UR3pvhbGx7porzVKR7gDuOpSEd00uQUYKJ8,1067
3
- datatailr-0.1.0.dist-info/METADATA,sha256=puop6KUrNKeB15tCjT80efuCoZthXEL9hT0ZCmB-9gk,433
4
- datatailr-0.1.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
5
- datatailr-0.1.0.dist-info/top_level.txt,sha256=75gntW0X_SKpqxLL6hAPipvpk28GAhJBvoyqN_HohWU,10
6
- datatailr-0.1.0.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- datatailr