python-sdk-remote 0.0.190b3356__tar.gz → 0.0.193b3590__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.
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/PKG-INFO +1 -1
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/__init__.py +2 -2
- python_sdk_remote-0.0.190b3356/python_sdk_remote/src/our_environment_variable_exception.py → python_sdk_remote-0.0.193b3590/python_sdk_remote/src/environment_variable_exception.py +1 -5
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/unified_json.py +2 -6
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/utilities.py +127 -28
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote.egg-info/PKG-INFO +1 -1
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote.egg-info/SOURCES.txt +0 -8
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/setup.py +2 -2
- python_sdk_remote-0.0.190b3356/python_sdk_remote/src/dot_env_files.py +0 -80
- python_sdk_remote-0.0.190b3356/python_sdk_remote/src/environment.py +0 -21
- python_sdk_remote-0.0.190b3356/python_sdk_remote/src/environment_variable_exception.py +0 -2
- python_sdk_remote-0.0.190b3356/python_sdk_remote/src/filesystem.py +0 -15
- python_sdk_remote-0.0.190b3356/python_sdk_remote/src/masking.py +0 -8
- python_sdk_remote-0.0.190b3356/python_sdk_remote/src/our_environment_variable.py +0 -96
- python_sdk_remote-0.0.190b3356/python_sdk_remote/src/personal_repo.py +0 -31
- python_sdk_remote-0.0.190b3356/python_sdk_remote/src/username.py +0 -11
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/README.md +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/pyproject.toml +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/constants.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/constants_src_mini_logger_and_logger.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/datetime_range.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/filename.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/generic_crud.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/http_response.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/is_test_data.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/item.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/mini_logger.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/our_obfuscation.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/our_object.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/our_objects.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/our_objects_local.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/our_objects_remote.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/our_request.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/our_request_old.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/valid_json_versions.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/validate_environment.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/version.py +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote.egg-info/dependency_links.txt +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote.egg-info/requires.txt +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote.egg-info/top_level.txt +0 -0
- {python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/setup.cfg +0 -0
{python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/__init__.py
RENAMED
|
@@ -10,7 +10,7 @@ from .utilities import (
|
|
|
10
10
|
get_environment_name,
|
|
11
11
|
get_brand_name,
|
|
12
12
|
our_get_env,
|
|
13
|
-
|
|
13
|
+
EnvironmentVariableException,
|
|
14
14
|
our_set_env,
|
|
15
15
|
our_delete_env,
|
|
16
16
|
to_dict,
|
|
@@ -83,7 +83,7 @@ __all__ = [
|
|
|
83
83
|
'get_environment_name',
|
|
84
84
|
'get_brand_name',
|
|
85
85
|
'our_get_env',
|
|
86
|
-
'
|
|
86
|
+
'EnvironmentVariableException',
|
|
87
87
|
'our_set_env',
|
|
88
88
|
'our_delete_env',
|
|
89
89
|
'to_dict',
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
class
|
|
1
|
+
class EnvironmentVariableException(Exception):
|
|
2
2
|
"""Raised when a required environment variable is missing or empty.
|
|
3
3
|
|
|
4
4
|
A specific exception (rather than a generic Exception) so callers can catch
|
|
5
5
|
exactly this case; shared by our_get_env / our_delete_env for consistency.
|
|
6
6
|
"""
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# Backward compatibility: the name before the Our prefix
|
|
10
|
-
EnvironmentVariableException = OurEnvironmentVariableException
|
|
@@ -5,8 +5,9 @@ from .valid_json_versions import valid_json_versions
|
|
|
5
5
|
# Alias validate_json
|
|
6
6
|
class UnifiedJson:
|
|
7
7
|
def __init__(self, data: dict, json_version: str):
|
|
8
|
+
# TODO Move this code to UnifiedJson.is_valid_json() method and call it
|
|
8
9
|
# TODO Write function/method both in TypeScript and Python to validate JSON i.e. to make sure there is version field in the upper level (Like in AWS JSON)
|
|
9
|
-
if not
|
|
10
|
+
if json_version not in valid_json_versions:
|
|
10
11
|
raise Exception(
|
|
11
12
|
f"version {json_version} is not in valid_json_versions {valid_json_versions}, "
|
|
12
13
|
f"please make sure you run sql2code."
|
|
@@ -14,11 +15,6 @@ class UnifiedJson:
|
|
|
14
15
|
self.json_version = json_version
|
|
15
16
|
self.data = data
|
|
16
17
|
|
|
17
|
-
@staticmethod
|
|
18
|
-
def is_valid_json(json_version: str) -> bool:
|
|
19
|
-
is_valid_json_result = json_version in valid_json_versions
|
|
20
|
-
return is_valid_json_result
|
|
21
|
-
|
|
22
18
|
def get_unified_json(self):
|
|
23
19
|
get_unified_json_result = {"version": self.json_version, "data": self.data}
|
|
24
20
|
return get_unified_json_result
|
{python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/utilities.py
RENAMED
|
@@ -17,18 +17,7 @@ from .version import PACKAGE_VERSION
|
|
|
17
17
|
|
|
18
18
|
from .mini_logger import MiniLogger as logger
|
|
19
19
|
|
|
20
|
-
from .
|
|
21
|
-
# Split out of this file, imported here so utilities.<name> keeps working
|
|
22
|
-
from .dot_env_files import ( # noqa: F401
|
|
23
|
-
DOT_ENV_FILENAME, _get_env_or_dot_env, add_to_file_if_not_existed, get_dot_env_file_value,
|
|
24
|
-
get_our_dot_env_filenames, update_dot_env_example)
|
|
25
|
-
from .environment import get_environment_name # noqa: F401
|
|
26
|
-
from .filesystem import _find_nearest_file # noqa: F401
|
|
27
|
-
from .masking import _mask # noqa: F401
|
|
28
|
-
from .our_environment_variable import our_delete_env, our_get_env, our_set_env # noqa: F401
|
|
29
|
-
from .personal_repo import ( # noqa: F401
|
|
30
|
-
PERSONAL_REPO_DIRECTORY_SUFFIX, PERSONAL_REPO_DOT_ENV_DIRECTORY, get_personal_repo_path)
|
|
31
|
-
from .username import _get_username_from_full_name # noqa: F401
|
|
20
|
+
from .environment_variable_exception import EnvironmentVariableException
|
|
32
21
|
|
|
33
22
|
load_dotenv()
|
|
34
23
|
# Load environment variables from .env file
|
|
@@ -138,33 +127,31 @@ def is_valid_time_range(time_range: tuple) -> bool:
|
|
|
138
127
|
|
|
139
128
|
|
|
140
129
|
# Enhanced URL validation with support for both str and URL types
|
|
141
|
-
|
|
142
|
-
|
|
143
130
|
def validate_url(url: Union[str, object]) -> bool:
|
|
144
131
|
"""
|
|
145
132
|
Validate URL format.
|
|
146
|
-
|
|
133
|
+
|
|
147
134
|
Args:
|
|
148
135
|
url: URL string or URL object to validate
|
|
149
|
-
|
|
136
|
+
|
|
150
137
|
Returns:
|
|
151
138
|
bool: True if URL is valid, False otherwise
|
|
152
139
|
"""
|
|
153
140
|
logger.start(object={"url": url, "url_type": type(url).__name__})
|
|
154
|
-
|
|
141
|
+
|
|
155
142
|
# Handle URL object (if using yarl or similar library)
|
|
156
143
|
if hasattr(url, 'scheme') and hasattr(url, 'host'):
|
|
157
144
|
is_valid_url = bool(url.scheme and url.host)
|
|
158
145
|
logger.end(object={"is_valid_url": is_valid_url, "source": "url_object"})
|
|
159
146
|
return is_valid_url
|
|
160
|
-
|
|
147
|
+
|
|
161
148
|
# Handle string URL
|
|
162
149
|
if url is not None and url != "":
|
|
163
150
|
parsed_url = urlparse(str(url))
|
|
164
151
|
is_valid_url = bool(parsed_url.scheme and parsed_url.netloc)
|
|
165
152
|
else:
|
|
166
153
|
is_valid_url = True # Empty URL is considered valid (optional field)
|
|
167
|
-
|
|
154
|
+
|
|
168
155
|
logger.end(object={"is_valid_url": is_valid_url, "source": "string_parsing"})
|
|
169
156
|
return is_valid_url
|
|
170
157
|
|
|
@@ -319,6 +306,110 @@ def is_datetime_in_datetime_range(check_datetime: datetime, datetime_range: Tupl
|
|
|
319
306
|
return is_datetime_in_datetime_range_result
|
|
320
307
|
|
|
321
308
|
|
|
309
|
+
# TODO shall we rename the function _file_ to _key_value_file_
|
|
310
|
+
def add_to_file_if_not_existed(file: str, key: str, value: Optional[str]) -> None:
|
|
311
|
+
logger.start(object={"file": file, "key": key, "value": value})
|
|
312
|
+
if not os.path.exists(file):
|
|
313
|
+
with open(file, "w") as f:
|
|
314
|
+
f.write(f"{key}={value}\n")
|
|
315
|
+
else:
|
|
316
|
+
with open(file, "r") as f:
|
|
317
|
+
lines = f.readlines()
|
|
318
|
+
if f"{key}=" not in lines:
|
|
319
|
+
with open(file, "a") as f:
|
|
320
|
+
f.write(f"{key}={value}\n")
|
|
321
|
+
logger.end()
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def update_dot_env_example(key: str, value: Optional[str]):
|
|
325
|
+
# Avoid recursion by checking environment directly
|
|
326
|
+
env_name = os.getenv("ENVIRONMENT_NAME", "").lower()
|
|
327
|
+
if env_name == "play1":
|
|
328
|
+
return
|
|
329
|
+
add_to_file_if_not_existed(file=".env.example", key=key, value=value)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
# TODO If running in a lower environment(i.e. local1, play1) if key do not exit in Personal Repo relevant .env.{environment_} or value diffrent update Personal Repo (create new and comment the old record)
|
|
333
|
+
# TODO If running in a lower environment(i.e. local1, play1) update .env.example with the key without the value
|
|
334
|
+
# TODO If running in a lower environment(i.e. local1, play1) and the key do not exist look for it in the Team Member Personal Repo and copy both the key and value to the repo .env.{environment_name} file
|
|
335
|
+
# TODO move all our_*_env() to our_env.py
|
|
336
|
+
# TODO shall we rename optional_prefix to prefix?
|
|
337
|
+
def our_get_env(key: str, default: Optional[str] = None, raise_if_not_found: bool = True,
|
|
338
|
+
raise_if_empty: bool = False, optional_prefix: Optional[str] = None) -> Optional[str]:
|
|
339
|
+
"""
|
|
340
|
+
Get environment variable with optional prefix fallback.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
key: Environment variable name
|
|
344
|
+
default: Default value if not found
|
|
345
|
+
raise_if_not_found: Raise exception if variable not found and no default
|
|
346
|
+
raise_if_empty: Raise exception if variable is empty
|
|
347
|
+
optional_prefix: Try with this prefix first, then without it
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
Environment variable value
|
|
351
|
+
"""
|
|
352
|
+
logger.start(object={"key": key, "default": default,
|
|
353
|
+
"raise_if_not_found": raise_if_not_found,
|
|
354
|
+
"raise_if_empty": raise_if_empty,
|
|
355
|
+
"optional_prefix": optional_prefix})
|
|
356
|
+
|
|
357
|
+
# Try with prefix first if provided
|
|
358
|
+
if optional_prefix:
|
|
359
|
+
prefixed_key = f"{optional_prefix}_{key}"
|
|
360
|
+
env_var = os.getenv(prefixed_key)
|
|
361
|
+
if env_var is not None:
|
|
362
|
+
logger.end(object={"env_var": env_var, "used_prefix": True})
|
|
363
|
+
return env_var.strip('"\'') if isinstance(env_var, str) else env_var
|
|
364
|
+
|
|
365
|
+
# Try without prefix
|
|
366
|
+
env_var = os.getenv(key, default)
|
|
367
|
+
|
|
368
|
+
if ((raise_if_not_found and key not in os.environ and default is None)
|
|
369
|
+
or (raise_if_empty and not env_var and not default)):
|
|
370
|
+
raise EnvironmentVariableException(f"Environment variable {key} not found - please check your .env file") # noqa: E501
|
|
371
|
+
|
|
372
|
+
# Strip quotes from env_var if present
|
|
373
|
+
if env_var and isinstance(env_var, str):
|
|
374
|
+
env_var = env_var.strip('"\'')
|
|
375
|
+
|
|
376
|
+
update_dot_env_example(key, value=default)
|
|
377
|
+
logger.end(object={"env_var": env_var})
|
|
378
|
+
return env_var
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def our_set_env(key: str, value: str) -> None:
|
|
382
|
+
"""
|
|
383
|
+
Set an environment variable, routed through the logger so the system can
|
|
384
|
+
track which repos/tests write which env vars (cf. our_get_env).
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
key: Environment variable name
|
|
388
|
+
value: Value to set
|
|
389
|
+
"""
|
|
390
|
+
logger.start(object={"key": key, "value": value})
|
|
391
|
+
os.environ[key] = value
|
|
392
|
+
logger.end(object={"key": key})
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def our_delete_env(key: str, raise_if_not_found: bool = False) -> None:
|
|
396
|
+
"""
|
|
397
|
+
Delete an environment variable if present, routed through the logger
|
|
398
|
+
(cf. our_get_env / our_set_env).
|
|
399
|
+
|
|
400
|
+
Args:
|
|
401
|
+
key: Environment variable name
|
|
402
|
+
raise_if_not_found: Raise if the variable is not set
|
|
403
|
+
"""
|
|
404
|
+
logger.start(object={"key": key,
|
|
405
|
+
"raise_if_not_found": raise_if_not_found})
|
|
406
|
+
if key in os.environ:
|
|
407
|
+
del os.environ[key]
|
|
408
|
+
elif raise_if_not_found:
|
|
409
|
+
raise EnvironmentVariableException(f"Environment variable {key} not found") # noqa: E501
|
|
410
|
+
logger.end(object={"key": key})
|
|
411
|
+
|
|
412
|
+
|
|
322
413
|
def get_brand_name(raise_if_not_found: bool = True,
|
|
323
414
|
raise_if_empty: bool = False) -> Optional[str]:
|
|
324
415
|
get_brand_name_result = our_get_env("BRAND_NAME",
|
|
@@ -327,6 +418,19 @@ def get_brand_name(raise_if_not_found: bool = True,
|
|
|
327
418
|
return get_brand_name_result
|
|
328
419
|
|
|
329
420
|
|
|
421
|
+
def get_environment_name(raise_if_not_found: bool = True,
|
|
422
|
+
raise_if_empty: bool = False) -> Optional[str]:
|
|
423
|
+
environment_name = our_get_env("ENVIRONMENT_NAME",
|
|
424
|
+
raise_if_not_found=raise_if_not_found,
|
|
425
|
+
raise_if_empty=raise_if_empty)
|
|
426
|
+
try:
|
|
427
|
+
EnvironmentName(environment_name) # if invalid, raises ValueError: x is not a valid EnvironmentName
|
|
428
|
+
except ValueError:
|
|
429
|
+
# Shows the current PACKAGE_VERSION for debugging
|
|
430
|
+
raise Exception(f"python-sdk-remote {PACKAGE_VERSION} get_environment_name(): Invalid EnvironmentName: {environment_name} either misspelling or you need the environment in a few places such as url-remote-python-package environment_name_enum.py ...")
|
|
431
|
+
return environment_name
|
|
432
|
+
|
|
433
|
+
|
|
330
434
|
def get_product_user_identifier(raise_if_not_found: bool = True,
|
|
331
435
|
raise_if_empty: bool = False) -> Optional[str]:
|
|
332
436
|
get_product_user_identifier_result = our_get_env("PRODUCT_USER_IDENTIFIER",
|
|
@@ -339,7 +443,7 @@ def get_product_user_password(raise_if_not_found: bool = True,
|
|
|
339
443
|
raise_if_empty: bool = False) -> Optional[str]:
|
|
340
444
|
"""
|
|
341
445
|
Get product user password from environment variables.
|
|
342
|
-
|
|
446
|
+
|
|
343
447
|
Note: PRODUCT_USER_PASSWORD is preferred over PRODUCT_PASSWORD (deprecated).
|
|
344
448
|
This function maintains backward compatibility.
|
|
345
449
|
"""
|
|
@@ -357,8 +461,6 @@ def get_product_user_password(raise_if_not_found: bool = True,
|
|
|
357
461
|
|
|
358
462
|
|
|
359
463
|
# Database-specific functions - Consider moving to database package when it's created
|
|
360
|
-
|
|
361
|
-
|
|
362
464
|
def get_sql_hostname(raise_if_not_found: bool = True,
|
|
363
465
|
raise_if_empty: bool = False) -> Optional[str]:
|
|
364
466
|
get_sql_hostname_result = our_get_env("RDS_HOSTNAME",
|
|
@@ -379,8 +481,6 @@ def get_sql_password(raise_if_empty: bool = False) -> Optional[str]:
|
|
|
379
481
|
|
|
380
482
|
|
|
381
483
|
# Dialog-specific function - Consider moving to dialog repo when it's created
|
|
382
|
-
|
|
383
|
-
|
|
384
484
|
def get_dialog_jwt_secret_key() -> Optional[str]:
|
|
385
485
|
get_dialog_jwt_secret_key_result = our_get_env("DIALOG_JWT_SECRET_KEY", raise_if_empty=True)
|
|
386
486
|
return get_dialog_jwt_secret_key_result
|
|
@@ -407,13 +507,13 @@ def decode_jwt(token: str, key: str) -> dict:
|
|
|
407
507
|
def obfuscate_log_dict(log_dict: dict) -> dict:
|
|
408
508
|
"""
|
|
409
509
|
Obfuscate sensitive keys in log dictionaries for security.
|
|
410
|
-
|
|
510
|
+
|
|
411
511
|
Obfuscates keys containing:
|
|
412
512
|
- password, secret, token, jwt
|
|
413
513
|
- email (with variations like e-mail, e_mail)
|
|
414
514
|
- phone, name (first/last/nick/user etc.)
|
|
415
515
|
- address, ssn
|
|
416
|
-
|
|
516
|
+
|
|
417
517
|
In play1 environment, returns original dict for debugging purposes.
|
|
418
518
|
"""
|
|
419
519
|
environment_name = get_environment_name()
|
|
@@ -433,7 +533,6 @@ def obfuscate_log_dict(log_dict: dict) -> dict:
|
|
|
433
533
|
|
|
434
534
|
# Tests for the following functions are implemented in utilities_test.py
|
|
435
535
|
|
|
436
|
-
|
|
437
536
|
def remove_digits(text: str) -> str:
|
|
438
537
|
remove_digits_result = ''.join(i for i in text if not i.isdigit())
|
|
439
538
|
return remove_digits_result
|
|
@@ -489,7 +588,7 @@ def validate_arguments(args: dict) -> None:
|
|
|
489
588
|
def reformat_time_string(input_str: str) -> str:
|
|
490
589
|
"""
|
|
491
590
|
Reformat time string from compact format to HH:MM:SS:MS format.
|
|
492
|
-
|
|
591
|
+
|
|
493
592
|
Example:
|
|
494
593
|
"1234" -> "12:34:00:00"
|
|
495
594
|
"123456" -> "12:34:56:00"
|
|
@@ -10,19 +10,13 @@ python_sdk_remote/src/__init__.py
|
|
|
10
10
|
python_sdk_remote/src/constants.py
|
|
11
11
|
python_sdk_remote/src/constants_src_mini_logger_and_logger.py
|
|
12
12
|
python_sdk_remote/src/datetime_range.py
|
|
13
|
-
python_sdk_remote/src/dot_env_files.py
|
|
14
|
-
python_sdk_remote/src/environment.py
|
|
15
13
|
python_sdk_remote/src/environment_variable_exception.py
|
|
16
14
|
python_sdk_remote/src/filename.py
|
|
17
|
-
python_sdk_remote/src/filesystem.py
|
|
18
15
|
python_sdk_remote/src/generic_crud.py
|
|
19
16
|
python_sdk_remote/src/http_response.py
|
|
20
17
|
python_sdk_remote/src/is_test_data.py
|
|
21
18
|
python_sdk_remote/src/item.py
|
|
22
|
-
python_sdk_remote/src/masking.py
|
|
23
19
|
python_sdk_remote/src/mini_logger.py
|
|
24
|
-
python_sdk_remote/src/our_environment_variable.py
|
|
25
|
-
python_sdk_remote/src/our_environment_variable_exception.py
|
|
26
20
|
python_sdk_remote/src/our_obfuscation.py
|
|
27
21
|
python_sdk_remote/src/our_object.py
|
|
28
22
|
python_sdk_remote/src/our_objects.py
|
|
@@ -30,9 +24,7 @@ python_sdk_remote/src/our_objects_local.py
|
|
|
30
24
|
python_sdk_remote/src/our_objects_remote.py
|
|
31
25
|
python_sdk_remote/src/our_request.py
|
|
32
26
|
python_sdk_remote/src/our_request_old.py
|
|
33
|
-
python_sdk_remote/src/personal_repo.py
|
|
34
27
|
python_sdk_remote/src/unified_json.py
|
|
35
|
-
python_sdk_remote/src/username.py
|
|
36
28
|
python_sdk_remote/src/utilities.py
|
|
37
29
|
python_sdk_remote/src/valid_json_versions.py
|
|
38
30
|
python_sdk_remote/src/validate_environment.py
|
|
@@ -8,9 +8,9 @@ package_dir = PACKAGE_NAME.replace("-", "_")
|
|
|
8
8
|
setuptools.setup(
|
|
9
9
|
name=PACKAGE_NAME,
|
|
10
10
|
# Every feature branch needs its own free beta: PyPI never accepts a version twice, and
|
|
11
|
-
# dev's literal is always one that has already been published.
|
|
11
|
+
# dev's literal is always one that has already been published. b3590 is this branch's
|
|
12
12
|
# Jira id. GA stays a [pub] commit on dev.
|
|
13
|
-
version='0.0.
|
|
13
|
+
version='0.0.193b3590', # https://pypi.org/project/python-sdk-remote#history
|
|
14
14
|
author="Circles",
|
|
15
15
|
author_email="info@circlez.ai",
|
|
16
16
|
description="PyPI Package for Circles Python SDK Local Python",
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
from dotenv import dotenv_values
|
|
5
|
-
|
|
6
|
-
from .filesystem import _find_nearest_file
|
|
7
|
-
from .masking import _mask
|
|
8
|
-
from .mini_logger import MiniLogger as logger
|
|
9
|
-
from .personal_repo import PERSONAL_REPO_DOT_ENV_DIRECTORY, get_personal_repo_path
|
|
10
|
-
|
|
11
|
-
DOT_ENV_FILENAME = ".env"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def get_dot_env_file_value(dot_env_filename: str, key: str) -> Optional[str]:
|
|
15
|
-
"""The value of key in a .env file, None when the file or the key is missing"""
|
|
16
|
-
if not os.path.isfile(dot_env_filename):
|
|
17
|
-
return None
|
|
18
|
-
return dotenv_values(dot_env_filename).get(key)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def get_our_dot_env_filenames(start_directory: Optional[str] = None, environment_name: Optional[str] = None,
|
|
22
|
-
personal_repo_path: Optional[str] = None) -> list:
|
|
23
|
-
"""The .env files our_get_env() looks in, in this order: the project's .env.<ENVIRONMENT_NAME> and .env (the nearest
|
|
24
|
-
ones from the current directory up), then the personal repo's .config/circlez.ai/.env.<ENVIRONMENT_NAME> and
|
|
25
|
-
.config/circlez.ai/.env"""
|
|
26
|
-
# Not get_environment_name(), which calls our_get_env()
|
|
27
|
-
environment_name = environment_name or os.environ.get("ENVIRONMENT_NAME")
|
|
28
|
-
dot_env_basenames = ([f"{DOT_ENV_FILENAME}.{environment_name}"] if environment_name else []) + [DOT_ENV_FILENAME]
|
|
29
|
-
dot_env_filenames = []
|
|
30
|
-
for dot_env_basename in dot_env_basenames:
|
|
31
|
-
dot_env_filename = _find_nearest_file(dot_env_basename, start_directory)
|
|
32
|
-
if dot_env_filename:
|
|
33
|
-
dot_env_filenames.append(dot_env_filename)
|
|
34
|
-
personal_repo_path = personal_repo_path or get_personal_repo_path()
|
|
35
|
-
if personal_repo_path:
|
|
36
|
-
for dot_env_basename in dot_env_basenames:
|
|
37
|
-
dot_env_filename = os.path.join(personal_repo_path, PERSONAL_REPO_DOT_ENV_DIRECTORY, dot_env_basename)
|
|
38
|
-
if os.path.isfile(dot_env_filename) and dot_env_filename not in dot_env_filenames:
|
|
39
|
-
dot_env_filenames.append(dot_env_filename)
|
|
40
|
-
return dot_env_filenames
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def _get_env_or_dot_env(key: str) -> Optional[str]:
|
|
44
|
-
"""The environment variable, otherwise its value in the .env files of get_our_dot_env_filenames(), which is then
|
|
45
|
-
set in the environment so the next lookup does not read the files again"""
|
|
46
|
-
env_var = os.getenv(key)
|
|
47
|
-
if env_var is not None:
|
|
48
|
-
return env_var
|
|
49
|
-
for dot_env_filename in get_our_dot_env_filenames():
|
|
50
|
-
dot_env_value = get_dot_env_file_value(dot_env_filename, key)
|
|
51
|
-
if dot_env_value:
|
|
52
|
-
os.environ[key] = dot_env_value
|
|
53
|
-
logger.info(f"our_get_env() found {key}={_mask(dot_env_value)} in {dot_env_filename}")
|
|
54
|
-
return dot_env_value
|
|
55
|
-
return None
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# TODO shall we rename the function _file_ to _key_value_file_
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def add_to_file_if_not_existed(file: str, key: str, value: Optional[str]) -> None:
|
|
62
|
-
logger.start(object={"file": file, "key": key, "value": value})
|
|
63
|
-
if not os.path.exists(file):
|
|
64
|
-
with open(file, "w") as f:
|
|
65
|
-
f.write(f"{key}={value}\n")
|
|
66
|
-
else:
|
|
67
|
-
with open(file, "r") as f:
|
|
68
|
-
lines = f.readlines()
|
|
69
|
-
if f"{key}=" not in lines:
|
|
70
|
-
with open(file, "a") as f:
|
|
71
|
-
f.write(f"{key}={value}\n")
|
|
72
|
-
logger.end()
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def update_dot_env_example(key: str, value: Optional[str]):
|
|
76
|
-
# Avoid recursion by checking environment directly
|
|
77
|
-
env_name = os.getenv("ENVIRONMENT_NAME", "").lower()
|
|
78
|
-
if env_name == "play1":
|
|
79
|
-
return
|
|
80
|
-
add_to_file_if_not_existed(file=".env.example", key=key, value=value)
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
|
-
from url_remote.environment_name_enum import EnvironmentName
|
|
4
|
-
|
|
5
|
-
from .our_environment_variable import our_get_env
|
|
6
|
-
from .version import PACKAGE_VERSION
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def get_environment_name(raise_if_not_found: bool = True,
|
|
10
|
-
raise_if_empty: bool = False) -> Optional[str]:
|
|
11
|
-
environment_name = our_get_env("ENVIRONMENT_NAME",
|
|
12
|
-
raise_if_not_found=raise_if_not_found,
|
|
13
|
-
raise_if_empty=raise_if_empty)
|
|
14
|
-
try:
|
|
15
|
-
EnvironmentName(environment_name) # if invalid, raises ValueError: x is not a valid EnvironmentName
|
|
16
|
-
except ValueError:
|
|
17
|
-
# Shows the current PACKAGE_VERSION for debugging
|
|
18
|
-
raise Exception(f"python-sdk-remote {PACKAGE_VERSION} get_environment_name(): Invalid EnvironmentName: "
|
|
19
|
-
f"{environment_name} either misspelling or you need the environment in a few places such as "
|
|
20
|
-
"url-remote-python-package environment_name_enum.py ...")
|
|
21
|
-
return environment_name
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def _find_nearest_file(filename: str, start_directory: Optional[str] = None) -> Optional[str]:
|
|
6
|
-
"""The nearest filename from start_directory (default: the current directory) up, as python-dotenv finds .env"""
|
|
7
|
-
directory = os.path.abspath(start_directory or os.getcwd())
|
|
8
|
-
while True:
|
|
9
|
-
candidate = os.path.join(directory, filename)
|
|
10
|
-
if os.path.isfile(candidate):
|
|
11
|
-
return candidate
|
|
12
|
-
parent_directory = os.path.dirname(directory)
|
|
13
|
-
if parent_directory == directory:
|
|
14
|
-
return None
|
|
15
|
-
directory = parent_directory
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
from .dot_env_files import _get_env_or_dot_env, update_dot_env_example
|
|
5
|
-
from .masking import _mask
|
|
6
|
-
from .mini_logger import MiniLogger as logger
|
|
7
|
-
from .our_environment_variable_exception import OurEnvironmentVariableException
|
|
8
|
-
|
|
9
|
-
# TODO If running in a lower environment(i.e. local1, play1) if key do not exit in Personal Repo relevant
|
|
10
|
-
# .env.{environment_} or value diffrent update Personal Repo (create new and comment the old record)
|
|
11
|
-
# TODO If running in a lower environment(i.e. local1, play1) update .env.example with the key without the value
|
|
12
|
-
# TODO If running in a lower environment(i.e. local1, play1) and the key do not exist look for it in the Team Member
|
|
13
|
-
# Personal Repo and copy both the key and value to the repo .env.{environment_name} file
|
|
14
|
-
# TODO move all our_*_env() to our_env.py
|
|
15
|
-
# TODO shall we rename optional_prefix to prefix?
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def our_get_env(key: str, default: Optional[str] = None, raise_if_not_found: bool = True,
|
|
19
|
-
raise_if_empty: bool = False, optional_prefix: Optional[str] = None) -> Optional[str]:
|
|
20
|
-
"""
|
|
21
|
-
Get environment variable with optional prefix fallback.
|
|
22
|
-
|
|
23
|
-
Args:
|
|
24
|
-
key: Environment variable name
|
|
25
|
-
default: Default value if not found
|
|
26
|
-
raise_if_not_found: Raise exception if variable not found and no default
|
|
27
|
-
raise_if_empty: Raise exception if variable is empty
|
|
28
|
-
optional_prefix: Try with this prefix first, then without it
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
Environment variable value
|
|
32
|
-
"""
|
|
33
|
-
logger.start(object={"key": key, "default": default,
|
|
34
|
-
"raise_if_not_found": raise_if_not_found,
|
|
35
|
-
"raise_if_empty": raise_if_empty,
|
|
36
|
-
"optional_prefix": optional_prefix})
|
|
37
|
-
|
|
38
|
-
# A key missing in the environment is looked for in the project's .env.<ENVIRONMENT_NAME> and .env, then in the
|
|
39
|
-
# personal repo's .config/circlez.ai/.env.<ENVIRONMENT_NAME> and .env (as PowerShell Get-OurEnvironmentVariable and
|
|
40
|
-
# TypeScript ourGetEnv)
|
|
41
|
-
# Try with prefix first if provided
|
|
42
|
-
if optional_prefix:
|
|
43
|
-
prefixed_key = f"{optional_prefix}_{key}"
|
|
44
|
-
env_var = _get_env_or_dot_env(prefixed_key)
|
|
45
|
-
if env_var is not None:
|
|
46
|
-
logger.end(object={"env_var": _mask(env_var), "used_prefix": True})
|
|
47
|
-
return env_var.strip('"\'') if isinstance(env_var, str) else env_var
|
|
48
|
-
|
|
49
|
-
# Try without prefix
|
|
50
|
-
env_var = _get_env_or_dot_env(key)
|
|
51
|
-
if env_var is None:
|
|
52
|
-
env_var = default
|
|
53
|
-
|
|
54
|
-
if ((raise_if_not_found and key not in os.environ and default is None)
|
|
55
|
-
or (raise_if_empty and not env_var and not default)):
|
|
56
|
-
raise OurEnvironmentVariableException(f"Environment variable {key} not found - please check your .env file") # noqa: E501
|
|
57
|
-
|
|
58
|
-
# Strip quotes from env_var if present
|
|
59
|
-
if env_var and isinstance(env_var, str):
|
|
60
|
-
env_var = env_var.strip('"\'')
|
|
61
|
-
|
|
62
|
-
update_dot_env_example(key, value=default)
|
|
63
|
-
logger.end(object={"env_var": _mask(env_var)})
|
|
64
|
-
return env_var
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def our_set_env(key: str, value: str) -> None:
|
|
68
|
-
"""
|
|
69
|
-
Set an environment variable, routed through the logger so the system can
|
|
70
|
-
track which repos/tests write which env vars (cf. our_get_env).
|
|
71
|
-
|
|
72
|
-
Args:
|
|
73
|
-
key: Environment variable name
|
|
74
|
-
value: Value to set
|
|
75
|
-
"""
|
|
76
|
-
logger.start(object={"key": key, "value": value})
|
|
77
|
-
os.environ[key] = value
|
|
78
|
-
logger.end(object={"key": key})
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def our_delete_env(key: str, raise_if_not_found: bool = False) -> None:
|
|
82
|
-
"""
|
|
83
|
-
Delete an environment variable if present, routed through the logger
|
|
84
|
-
(cf. our_get_env / our_set_env).
|
|
85
|
-
|
|
86
|
-
Args:
|
|
87
|
-
key: Environment variable name
|
|
88
|
-
raise_if_not_found: Raise if the variable is not set
|
|
89
|
-
"""
|
|
90
|
-
logger.start(object={"key": key,
|
|
91
|
-
"raise_if_not_found": raise_if_not_found})
|
|
92
|
-
if key in os.environ:
|
|
93
|
-
del os.environ[key]
|
|
94
|
-
elif raise_if_not_found:
|
|
95
|
-
raise OurEnvironmentVariableException(f"Environment variable {key} not found") # noqa: E501
|
|
96
|
-
logger.end(object={"key": key})
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
from .username import _get_username_from_full_name
|
|
5
|
-
|
|
6
|
-
PERSONAL_REPO_DIRECTORY_SUFFIX = "-circlez.ai"
|
|
7
|
-
# The directory of the .env files in the personal repo
|
|
8
|
-
PERSONAL_REPO_DOT_ENV_DIRECTORY = os.path.join(".config", "circlez.ai")
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def get_personal_repo_path() -> Optional[str]:
|
|
12
|
-
"""The personal repo (i.e. /repos/circlez/tal-circlez.ai), as PowerShell Get-PersonalRepoDirectory:
|
|
13
|
-
PERSONAL_REPO_PATH when set, otherwise <REPOS_ORGANIZATION_BASE>/<username>-circlez.ai with the username from
|
|
14
|
-
FULL_NAME, otherwise the only *-circlez.ai directory in REPOS_ORGANIZATION_BASE. None when it cannot be found"""
|
|
15
|
-
personal_repo_path = os.environ.get("PERSONAL_REPO_PATH")
|
|
16
|
-
if personal_repo_path:
|
|
17
|
-
return personal_repo_path
|
|
18
|
-
repos_organization_base = os.environ.get("REPOS_ORGANIZATION_BASE")
|
|
19
|
-
if not repos_organization_base or not os.path.isdir(repos_organization_base):
|
|
20
|
-
return None
|
|
21
|
-
full_name = os.environ.get("FULL_NAME")
|
|
22
|
-
username = _get_username_from_full_name(full_name) if full_name else None
|
|
23
|
-
if username:
|
|
24
|
-
personal_repo_path = os.path.join(repos_organization_base, username + PERSONAL_REPO_DIRECTORY_SUFFIX)
|
|
25
|
-
if os.path.isdir(personal_repo_path):
|
|
26
|
-
return personal_repo_path
|
|
27
|
-
personal_repo_paths = [os.path.join(repos_organization_base, directory)
|
|
28
|
-
for directory in os.listdir(repos_organization_base)
|
|
29
|
-
if directory.endswith(PERSONAL_REPO_DIRECTORY_SUFFIX)
|
|
30
|
-
and os.path.isdir(os.path.join(repos_organization_base, directory))]
|
|
31
|
-
return personal_repo_paths[0] if len(personal_repo_paths) == 1 else None
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def _get_username_from_full_name(full_name: str) -> Optional[str]:
|
|
5
|
-
# Same as PowerShell User.psm1 Get-OurUsername
|
|
6
|
-
if full_name == "Tal Rosenberger":
|
|
7
|
-
return "tal"
|
|
8
|
-
name_parts = full_name.split()
|
|
9
|
-
if len(name_parts) != 2:
|
|
10
|
-
return None
|
|
11
|
-
return f"{name_parts[0]}.{name_parts[1][0]}".lower()
|
|
File without changes
|
|
File without changes
|
{python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/filename.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/item.py
RENAMED
|
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
|
{python_sdk_remote-0.0.190b3356 → python_sdk_remote-0.0.193b3590}/python_sdk_remote/src/version.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|