osbot-utils 2.73.0__py3-none-any.whl → 2.74.0__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.
Files changed (122) hide show
  1. osbot_utils/helpers/flows/actions/Flow__Data.py +1 -1
  2. osbot_utils/helpers/flows/models/Flow_Run__Event.py +6 -5
  3. osbot_utils/helpers/flows/models/Schema__Flow__Artifact.py +1 -1
  4. osbot_utils/helpers/flows/models/Schema__Flow__Result.py +1 -1
  5. osbot_utils/helpers/flows/schemas/Schema__Flow__Data.py +1 -1
  6. osbot_utils/helpers/flows/schemas/Schema__Flow__Event.py +1 -1
  7. osbot_utils/helpers/flows/schemas/Schema__Flow__Log.py +1 -1
  8. osbot_utils/helpers/flows/schemas/Schema__Flow__Task__Data.py +1 -1
  9. osbot_utils/helpers/generators/Generator_Manager.py +1 -1
  10. osbot_utils/helpers/generators/Model__Generator_Target.py +1 -1
  11. osbot_utils/helpers/html/schemas/Schema__Html_Document.py +1 -1
  12. osbot_utils/helpers/llms/actions/LLM_Request__Execute.py +2 -1
  13. osbot_utils/helpers/llms/actions/Type_Safe__Schema_For__LLMs.py +10 -10
  14. osbot_utils/helpers/llms/builders/LLM_Request__Builder.py +3 -2
  15. osbot_utils/helpers/llms/builders/LLM_Request__Builder__Open_AI.py +2 -1
  16. osbot_utils/helpers/llms/builders/LLM_Request__Factory.py +1 -1
  17. osbot_utils/helpers/llms/cache/LLM_Cache__Path_Generator.py +7 -6
  18. osbot_utils/helpers/llms/cache/LLM_Request__Cache.py +10 -10
  19. osbot_utils/helpers/llms/cache/LLM_Request__Cache__File_System.py +5 -3
  20. osbot_utils/helpers/llms/cache/LLM_Request__Cache__Storage.py +2 -2
  21. osbot_utils/helpers/llms/cache/Virtual_Storage__Local__Folder.py +7 -7
  22. osbot_utils/helpers/llms/cache/Virtual_Storage__Sqlite.py +7 -7
  23. osbot_utils/helpers/llms/schemas/Safe_Str__LLM__Model_Name.py +1 -1
  24. osbot_utils/helpers/llms/schemas/Schema__LLM_Cache__Index.py +6 -5
  25. osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Data.py +2 -1
  26. osbot_utils/helpers/llms/schemas/Schema__LLM_Response.py +1 -1
  27. osbot_utils/helpers/llms/schemas/Schema__LLM_Response__Cache.py +7 -6
  28. osbot_utils/helpers/xml/rss/RSS__Feed__Parser.py +1 -1
  29. osbot_utils/helpers/xml/rss/RSS__Item.py +1 -1
  30. osbot_utils/type_safe/Type_Safe.py +11 -10
  31. osbot_utils/type_safe/Type_Safe__Base.py +3 -3
  32. osbot_utils/{helpers → type_safe/primitives}/safe_float/Safe_Float__Engineering.py +2 -1
  33. osbot_utils/{helpers → type_safe/primitives}/safe_float/Safe_Float__Money.py +1 -2
  34. osbot_utils/{helpers → type_safe/primitives}/safe_float/Safe_Float__Percentage_Exact.py +1 -1
  35. osbot_utils/{helpers → type_safe/primitives}/safe_int/Safe_Int.py +3 -3
  36. osbot_utils/{helpers → type_safe/primitives}/safe_int/__init__.py +1 -1
  37. osbot_utils/{helpers → type_safe/primitives}/safe_str/Safe_Str.py +3 -3
  38. osbot_utils/{helpers/safe_str → type_safe/primitives/safe_str/cryptography/hashes}/Safe_Str__Hash.py +3 -3
  39. osbot_utils/type_safe/primitives/safe_str/cryptography/hashes/Safe_Str__SHA1.py +26 -0
  40. osbot_utils/type_safe/primitives/safe_str/cryptography/hashes/Safe_Str__SHA1__Short.py +24 -0
  41. osbot_utils/type_safe/primitives/safe_str/cryptography/nacl/Safe_Str__NaCl__Private_Key.py +27 -0
  42. osbot_utils/type_safe/primitives/safe_str/cryptography/nacl/Safe_Str__NaCl__Public_Key.py +28 -0
  43. osbot_utils/type_safe/primitives/safe_str/cryptography/nacl/Schema__NaCl__Keys.py +8 -0
  44. osbot_utils/{helpers/safe_str → type_safe/primitives/safe_str/filesystem}/Safe_Str__File__Name.py +1 -1
  45. osbot_utils/{helpers/safe_str → type_safe/primitives/safe_str/filesystem}/Safe_Str__File__Path.py +1 -1
  46. osbot_utils/type_safe/primitives/safe_str/git/Safe_Str__Git__Branch.py +27 -0
  47. osbot_utils/type_safe/primitives/safe_str/git/Safe_Str__Git__Ref.py +63 -0
  48. osbot_utils/type_safe/primitives/safe_str/git/Safe_Str__Git__Ref_Base.py +73 -0
  49. osbot_utils/type_safe/primitives/safe_str/git/Safe_Str__Git__Tag.py +17 -0
  50. osbot_utils/{helpers/safe_str → type_safe/primitives/safe_str/git}/Safe_Str__Version.py +2 -2
  51. osbot_utils/type_safe/primitives/safe_str/github/Safe_Str__GitHub__Repo.py +46 -0
  52. osbot_utils/type_safe/primitives/safe_str/github/Safe_Str__GitHub__Repo_Name.py +35 -0
  53. osbot_utils/type_safe/primitives/safe_str/github/Safe_Str__GitHub__Repo_Owner.py +39 -0
  54. osbot_utils/type_safe/primitives/safe_str/github/__init__.py +0 -0
  55. osbot_utils/{helpers → type_safe/primitives}/safe_str/http/Safe_Str__Http__Content_Type.py +1 -1
  56. osbot_utils/{helpers → type_safe/primitives}/safe_str/http/Safe_Str__Http__ETag.py +1 -1
  57. osbot_utils/{helpers → type_safe/primitives}/safe_str/http/Safe_Str__Http__Last_Modified.py +1 -1
  58. osbot_utils/{helpers → type_safe/primitives}/safe_str/http/Safe_Str__Http__Text.py +1 -1
  59. osbot_utils/type_safe/primitives/safe_str/http/__init__.py +0 -0
  60. osbot_utils/{helpers → type_safe/primitives/safe_str/identifiers}/Guid.py +3 -2
  61. osbot_utils/type_safe/primitives/safe_str/identifiers/__init__.py +0 -0
  62. osbot_utils/{helpers/safe_str → type_safe/primitives/safe_str/text}/Safe_Str__Text.py +1 -1
  63. osbot_utils/{helpers/safe_str → type_safe/primitives/safe_str/text}/Safe_Str__Text__Dangerous.py +1 -1
  64. osbot_utils/type_safe/primitives/safe_str/text/__init__.py +0 -0
  65. osbot_utils/{helpers/safe_str/http → type_safe/primitives/safe_str/web}/Safe_Str__Html.py +1 -1
  66. osbot_utils/{helpers/safe_str → type_safe/primitives/safe_str/web}/Safe_Str__Url.py +1 -1
  67. osbot_utils/type_safe/primitives/safe_str/web/__init__.py +0 -0
  68. osbot_utils/{helpers/safe_int → type_safe/primitives/safe_uint}/Safe_UInt.py +2 -1
  69. osbot_utils/{helpers/safe_int → type_safe/primitives/safe_uint}/Safe_UInt__Byte.py +1 -1
  70. osbot_utils/{helpers/safe_int → type_safe/primitives/safe_uint}/Safe_UInt__FileSize.py +1 -1
  71. osbot_utils/{helpers/safe_int → type_safe/primitives/safe_uint}/Safe_UInt__Percentage.py +1 -1
  72. osbot_utils/{helpers/safe_int → type_safe/primitives/safe_uint}/Safe_UInt__Port.py +1 -1
  73. osbot_utils/type_safe/primitives/safe_uint/__init__.py +0 -0
  74. osbot_utils/type_safe/type_safe_core/__init__.py +0 -0
  75. osbot_utils/type_safe/{Type_Safe__Dict.py → type_safe_core/collections/Type_Safe__Dict.py} +4 -3
  76. osbot_utils/type_safe/type_safe_core/collections/__init__.py +0 -0
  77. osbot_utils/type_safe/type_safe_core/decorators/__init__.py +0 -0
  78. osbot_utils/type_safe/{decorators → type_safe_core/decorators}/type_safe.py +2 -1
  79. osbot_utils/type_safe/{Type_Safe__Method.py → type_safe_core/methods/Type_Safe__Method.py} +4 -5
  80. osbot_utils/type_safe/type_safe_core/methods/__init__.py +0 -0
  81. osbot_utils/type_safe/{shared → type_safe_core/shared}/Type_Safe__Annotations.py +1 -1
  82. osbot_utils/type_safe/{shared → type_safe_core/shared}/Type_Safe__Cache.py +3 -3
  83. osbot_utils/type_safe/{shared → type_safe_core/shared}/Type_Safe__Convert.py +3 -3
  84. osbot_utils/type_safe/{shared → type_safe_core/shared}/Type_Safe__Json_Compressor.py +6 -6
  85. osbot_utils/type_safe/{shared → type_safe_core/shared}/Type_Safe__Raise_Exception.py +1 -1
  86. osbot_utils/type_safe/{shared → type_safe_core/shared}/Type_Safe__Validation.py +8 -7
  87. osbot_utils/type_safe/type_safe_core/shared/__init__.py +0 -0
  88. osbot_utils/type_safe/{steps → type_safe_core/steps}/Type_Safe__Step__Class_Kwargs.py +8 -7
  89. osbot_utils/type_safe/{steps → type_safe_core/steps}/Type_Safe__Step__Default_Value.py +6 -6
  90. osbot_utils/type_safe/{steps → type_safe_core/steps}/Type_Safe__Step__From_Json.py +16 -17
  91. osbot_utils/type_safe/{steps → type_safe_core/steps}/Type_Safe__Step__Init.py +7 -6
  92. osbot_utils/type_safe/{steps → type_safe_core/steps}/Type_Safe__Step__Set_Attr.py +7 -7
  93. osbot_utils/type_safe/type_safe_core/steps/__init__.py +0 -0
  94. osbot_utils/utils/Files.py +2 -3
  95. osbot_utils/version +1 -1
  96. {osbot_utils-2.73.0.dist-info → osbot_utils-2.74.0.dist-info}/METADATA +3 -3
  97. {osbot_utils-2.73.0.dist-info → osbot_utils-2.74.0.dist-info}/RECORD +122 -98
  98. /osbot_utils/{helpers/safe_float → type_safe/primitives}/__init__.py +0 -0
  99. /osbot_utils/{helpers → type_safe/primitives}/safe_float/Safe_Float.py +0 -0
  100. /osbot_utils/{helpers/safe_str → type_safe/primitives/safe_float}/__init__.py +0 -0
  101. /osbot_utils/{helpers → type_safe/primitives/safe_int}/Timestamp_Now.py +0 -0
  102. /osbot_utils/{helpers/safe_str/schemas → type_safe/primitives/safe_str}/Enum__Safe_Str__Regex_Mode.py +0 -0
  103. /osbot_utils/{helpers/safe_str/http → type_safe/primitives/safe_str}/__init__.py +0 -0
  104. /osbot_utils/{helpers/safe_str/schemas → type_safe/primitives/safe_str/cryptography}/__init__.py +0 -0
  105. /osbot_utils/type_safe/{decorators → primitives/safe_str/cryptography/hashes}/__init__.py +0 -0
  106. /osbot_utils/type_safe/{methods → primitives/safe_str/cryptography/nacl}/__init__.py +0 -0
  107. /osbot_utils/type_safe/{shared → primitives/safe_str/filesystem}/__init__.py +0 -0
  108. /osbot_utils/type_safe/{steps → primitives/safe_str/git}/__init__.py +0 -0
  109. /osbot_utils/{helpers → type_safe/primitives/safe_str/identifiers}/Random_Guid.py +0 -0
  110. /osbot_utils/{helpers → type_safe/primitives/safe_str/identifiers}/Random_Guid_Short.py +0 -0
  111. /osbot_utils/{helpers → type_safe/primitives/safe_str/identifiers}/Safe_Id.py +0 -0
  112. /osbot_utils/{helpers/safe_str/http → type_safe/primitives/safe_str/web}/Safe_Str__IP_Address.py +0 -0
  113. /osbot_utils/type_safe/{Type_Safe__List.py → type_safe_core/collections/Type_Safe__List.py} +0 -0
  114. /osbot_utils/type_safe/{Type_Safe__Set.py → type_safe_core/collections/Type_Safe__Set.py} +0 -0
  115. /osbot_utils/type_safe/{Type_Safe__Tuple.py → type_safe_core/collections/Type_Safe__Tuple.py} +0 -0
  116. /osbot_utils/type_safe/{methods → type_safe_core/methods}/type_safe_property.py +0 -0
  117. /osbot_utils/type_safe/{shared → type_safe_core/shared}/Type_Safe__Json_Compressor__Type_Registry.py +0 -0
  118. /osbot_utils/type_safe/{shared → type_safe_core/shared}/Type_Safe__Not_Cached.py +0 -0
  119. /osbot_utils/type_safe/{shared → type_safe_core/shared}/Type_Safe__Shared__Variables.py +0 -0
  120. /osbot_utils/type_safe/{steps → type_safe_core/steps}/Type_Safe__Step__Default_Kwargs.py +0 -0
  121. {osbot_utils-2.73.0.dist-info → osbot_utils-2.74.0.dist-info}/LICENSE +0 -0
  122. {osbot_utils-2.73.0.dist-info → osbot_utils-2.74.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,28 @@
1
+ import re
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
+ from osbot_utils.type_safe.primitives.safe_str.Enum__Safe_Str__Regex_Mode import Enum__Safe_Str__Regex_Mode
4
+
5
+ TYPE_SAFE_STR__NACL__PUBLIC_KEY__REGEX = re.compile(r'^[a-fA-F0-9]{64}$')
6
+ TYPE_SAFE_STR__NACL__PUBLIC_KEY__LENGTH = 64 # 32 bytes as hex = 64 characters
7
+
8
+ # todo: refactor this with Safe_Str__NaCl__Private_Key since the code is just about the same
9
+ class Safe_Str__NaCl__Public_Key(Safe_Str):
10
+ """
11
+ Safe string class for NaCl (Curve25519) public keys in hexadecimal format.
12
+
13
+ NaCl public keys are 32 bytes (256 bits), represented as 64 hexadecimal characters.
14
+ These keys are used with libsodium/PyNaCl for asymmetric encryption using SealedBox.
15
+
16
+ Examples:
17
+ - "a1b2c3d4e5f6789012345678901234567890abcdefabcdefabcdefabcdefabcd"
18
+ - "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"
19
+
20
+ Security Note: Public keys can be safely shared and transmitted.
21
+ """
22
+ regex = TYPE_SAFE_STR__NACL__PUBLIC_KEY__REGEX
23
+ regex_mode = Enum__Safe_Str__Regex_Mode.MATCH
24
+ max_length = TYPE_SAFE_STR__NACL__PUBLIC_KEY__LENGTH
25
+ exact_length = True
26
+ allow_empty = False
27
+ trim_whitespace = True
28
+ strict_validation = True
@@ -0,0 +1,8 @@
1
+ from osbot_utils.type_safe.Type_Safe import Type_Safe
2
+ from osbot_utils.type_safe.primitives.safe_str.cryptography.nacl.Safe_Str__NaCl__Private_Key import Safe_Str__NaCl__Private_Key
3
+ from osbot_utils.type_safe.primitives.safe_str.cryptography.nacl.Safe_Str__NaCl__Public_Key import Safe_Str__NaCl__Public_Key
4
+
5
+
6
+ class Schema__NaCl__Keys(Type_Safe):
7
+ public_key : Safe_Str__NaCl__Public_Key = None
8
+ private_key: Safe_Str__NaCl__Private_Key = None
@@ -1,5 +1,5 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
3
 
4
4
  TYPE_SAFE_STR__FILE__NAME__REGEX = re.compile(r'[^a-zA-Z0-9_\-. ]')
5
5
 
@@ -1,5 +1,5 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
3
 
4
4
  TYPE_SAFE_STR__FILE_PATH__REGEX = re.compile(r'[^a-zA-Z0-9_\-./\\ ]') # Allow alphanumerics, underscores, hyphens, dots, slashes, and spaces
5
5
  TYPE_SAFE_STR__FILE_PATH__MAX_LENGTH = 1024
@@ -0,0 +1,27 @@
1
+ from osbot_utils.type_safe.primitives.safe_str.git.Safe_Str__Git__Ref_Base import Safe_Str__Git__Ref_Base
2
+
3
+
4
+ class Safe_Str__Git__Branch(Safe_Str__Git__Ref_Base):
5
+ """
6
+ Safe string class for GitHub branch names.
7
+
8
+ Follows git-check-ref-format rules with additional branch-specific restrictions:
9
+ - Cannot start with a dash '-' (branch-specific rule)
10
+
11
+ Examples:
12
+ - "main", "master", "develop"
13
+ - "feature/oauth-login"
14
+ - "bugfix/issue-123"
15
+ - "release/v2.0"
16
+ """
17
+
18
+ def __new__(cls, value=None):
19
+ result = super().__new__(cls, value)
20
+
21
+ if result:
22
+ # Additional branch-specific rule: cannot start with dash
23
+ # (from git check-ref-format --branch documentation)
24
+ if result.startswith('-'):
25
+ raise ValueError(f"Branch name cannot start with dash: {result}")
26
+
27
+ return result
@@ -0,0 +1,63 @@
1
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.cryptography.hashes.Safe_Str__SHA1 import Safe_Str__SHA1
3
+ from osbot_utils.type_safe.primitives.safe_str.cryptography.hashes.Safe_Str__SHA1__Short import Safe_Str__SHA1__Short
4
+ from osbot_utils.type_safe.primitives.safe_str.git.Safe_Str__Git__Branch import Safe_Str__Git__Branch
5
+ from osbot_utils.type_safe.primitives.safe_str.git.Safe_Str__Git__Tag import Safe_Str__Git__Tag
6
+
7
+
8
+ class Safe_Str__Git__Ref(Safe_Str):
9
+ """
10
+ Safe string class for any valid Git reference (branch, tag, or commit SHA).
11
+
12
+ This class validates that a string is a syntactically valid Git reference
13
+ without attempting to classify what type of reference it is.
14
+
15
+ A value is accepted if it passes validation as ANY of:
16
+ - A 40-character SHA (Safe_Str__SHA1)
17
+ - A 7-character short SHA (Safe_Str__SHA1__Short)
18
+ - A valid Git branch name (Safe_Str__Git__Branch)
19
+ - A valid Git tag name (Safe_Str__Git__Tag)
20
+
21
+ Used in GitHub API calls like:
22
+ - /repos/{owner}/{repo}/zipball/{ref}
23
+ - /repos/{owner}/{repo}/git/ref/{ref}
24
+ - /repos/{owner}/{repo}/commits/{ref}
25
+ """
26
+ max_length = 255
27
+ allow_empty = False
28
+ trim_whitespace = True
29
+
30
+ def __new__(cls, value=None):
31
+ # First, do basic Safe_Str processing
32
+ if value is None:
33
+ if cls.allow_empty:
34
+ value = ""
35
+ else:
36
+ raise ValueError(f"in {cls.__name__}, value cannot be None when allow_empty is False")
37
+
38
+ if not isinstance(value, str):
39
+ value = str(value)
40
+
41
+ if cls.trim_whitespace:
42
+ value = value.strip()
43
+
44
+ if not cls.allow_empty and (value is None or value == ""):
45
+ raise ValueError("Value cannot be empty when allow_empty is False")
46
+
47
+ if len(value) > cls.max_length:
48
+ raise ValueError(f"Value exceeds maximum length of {cls.max_length} characters (was {len(value)})")
49
+
50
+
51
+ validators = [('SHA' , Safe_Str__SHA1 ), # we will try to validate as different ref types
52
+ ('short SHA', Safe_Str__SHA1__Short ), # If ANY of these validation succeeds, accept the value
53
+ ('branch' , Safe_Str__Git__Branch ),
54
+ ('tag' , Safe_Str__Git__Tag )]
55
+
56
+ for validator_name, validator_class in validators:
57
+ try:
58
+ sanitized_value = validator_class(value) # Validation succeeded - use the sanitized value
59
+ return str.__new__(cls, sanitized_value) # return since it is a valid ref
60
+ except ValueError:
61
+ continue # This validator didn't accept it, try the next one
62
+
63
+ raise ValueError(f"Invalid Git ref: '{value}' is not a valid SHA, branch, or tag name") # None of the validators accepted it - it's not a valid ref
@@ -0,0 +1,73 @@
1
+ import re
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
+
4
+
5
+ TYPE_SAFE_STR__GIT_REF__REGEX = re.compile(r'[\x00-\x1f\x7f ~^:?*\[\]\\]')
6
+ TYPE_SAFE_STR__GIT_REF__MAX_LENGTH = 255
7
+
8
+ class Safe_Str__Git__Ref_Base(Safe_Str):
9
+ """
10
+ Base class for Git references following git-check-ref-format rules.
11
+
12
+ Git reference rules (from git-check-ref-format https://git-scm.com/docs/git-check-ref-format):
13
+ 1. Can include slash `/` for hierarchical grouping, but no slash-separated
14
+ component can begin with a dot `.` or end with `.lock`
15
+ 2. Cannot have two consecutive dots `..` anywhere
16
+ 3. Cannot have ASCII control characters, space, tilde `~`, caret `^`,
17
+ colon `:`, question-mark `?`, asterisk `*`, or open bracket `[`
18
+ 4. Cannot begin or end with a slash `/` or contain multiple consecutive slashes
19
+ 5. Cannot end with a dot `.`
20
+ 6. Cannot contain a sequence `@{`
21
+ 7. Cannot be the single character `@`
22
+ 8. Cannot contain a backslash `\`
23
+ """
24
+ regex = TYPE_SAFE_STR__GIT_REF__REGEX
25
+ max_length = TYPE_SAFE_STR__GIT_REF__MAX_LENGTH
26
+ allow_empty = False
27
+ trim_whitespace = True
28
+ allow_all_replacement_char = True
29
+
30
+ def __new__(cls, value=None):
31
+ result = super().__new__(cls, value)
32
+
33
+ if result:
34
+ # Rule: Cannot be the single character '@'
35
+ if result == '@':
36
+ raise ValueError(f"Reference cannot be the single character '@': {result}")
37
+
38
+ # Rule: Cannot have two consecutive dots '..'
39
+ if '..' in result:
40
+ raise ValueError(f"Reference cannot contain consecutive dots '..': {result}")
41
+
42
+ # Rule: Cannot contain sequence '@{'
43
+ if '@{' in result:
44
+ raise ValueError(f"Reference cannot contain '@{{': {result}")
45
+
46
+ # Rule: Cannot begin or end with a slash
47
+ if result.startswith('/') or result.endswith('/'):
48
+ raise ValueError(f"Reference cannot start or end with slash: {result}")
49
+
50
+ # Rule: Cannot contain multiple consecutive slashes
51
+ if '//' in result:
52
+ raise ValueError(f"Reference cannot contain consecutive slashes: {result}")
53
+
54
+ # Rule: Cannot end with a dot
55
+ if result.endswith('.'):
56
+ raise ValueError(f"Reference cannot end with dot: {result}")
57
+
58
+ # Rule: No slash-separated component can begin with '.' or end with '.lock'
59
+ if '/' in result:
60
+ components = result.split('/')
61
+ for component in components:
62
+ if component.startswith('.'):
63
+ raise ValueError(f"Path component cannot start with dot: {component}")
64
+ if component.endswith('.lock'):
65
+ raise ValueError(f"Path component cannot end with '.lock': {component}")
66
+ else:
67
+ # Single component (no slashes)
68
+ if result.startswith('.'):
69
+ raise ValueError(f"Reference cannot start with dot: {result}")
70
+ if result.endswith('.lock'):
71
+ raise ValueError(f"Reference cannot end with '.lock': {result}")
72
+
73
+ return result
@@ -0,0 +1,17 @@
1
+ from osbot_utils.type_safe.primitives.safe_str.git.Safe_Str__Git__Ref_Base import Safe_Str__Git__Ref_Base
2
+
3
+ class Safe_Str__Git__Tag(Safe_Str__Git__Ref_Base):
4
+ """
5
+ Safe string class for GitHub tag names.
6
+
7
+ Follows git-check-ref-format rules for tags.
8
+ Tags have the same rules as general Git references.
9
+
10
+ Examples:
11
+ - "v1.0.0", "v2.3.4"
12
+ - "release-1.0.0"
13
+ - "2024.01.15"
14
+ - "stable", "latest"
15
+ """
16
+ pass
17
+
@@ -1,6 +1,6 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
3
- from osbot_utils.helpers.safe_str.schemas.Enum__Safe_Str__Regex_Mode import Enum__Safe_Str__Regex_Mode
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
+ from osbot_utils.type_safe.primitives.safe_str.Enum__Safe_Str__Regex_Mode import Enum__Safe_Str__Regex_Mode
4
4
 
5
5
  TYPE_SAFE_STR__VERSION__REGEX = re.compile(r'^v(\d{1,3})\.(\d{1,3})\.(\d{1,3})$') # Regex to match versions like v0.1.1 or v999.999.999
6
6
  TYPE_SAFE_STR__VERSION__MAX_LENGTH = 12 # Max length for 'v999.999.999'
@@ -0,0 +1,46 @@
1
+ import re
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
+ from osbot_utils.type_safe.primitives.safe_str.github.Safe_Str__GitHub__Repo_Name import Safe_Str__GitHub__Repo_Name
4
+ from osbot_utils.type_safe.primitives.safe_str.github.Safe_Str__GitHub__Repo_Owner import Safe_Str__GitHub__Repo_Owner
5
+
6
+ TYPE_SAFE_STR__GITHUB__REPO__REGEX = re.compile(r'[^a-zA-Z0-9\-_./]')
7
+ TYPE_SAFE_STR__GITHUB__REPO__MAX_LENGTH = 140 # 39 (owner) + 1 (/) + 100 (repo)
8
+
9
+ class Safe_Str__GitHub__Repo(Safe_Str):
10
+ """
11
+ Safe string class for full GitHub repository identifiers in owner/repo format.
12
+
13
+ Examples:
14
+ - "octocat/Hello-World"
15
+ - "microsoft/vscode"
16
+ - "owasp-sbot/OSBot-Utils"
17
+
18
+ This class leverages Safe_Str__GitHub__Repo_Owner and Safe_Str__GitHub__Repo_Name
19
+ for validation of the individual components.
20
+ """
21
+ regex = TYPE_SAFE_STR__GITHUB__REPO__REGEX
22
+ max_length = TYPE_SAFE_STR__GITHUB__REPO__MAX_LENGTH
23
+ allow_empty = False
24
+ trim_whitespace = True
25
+ allow_all_replacement_char = False
26
+ repo_owner : Safe_Str__GitHub__Repo_Owner = None # note: due to the str override these will not show in the Pycharm code hints (but they will work)
27
+ repo_name : Safe_Str__GitHub__Repo_Name = None
28
+
29
+ def __new__(cls, value=None):
30
+ result = super().__new__(cls, value)
31
+
32
+ if result:
33
+ if '/' not in result: # Check for the required forward slash
34
+ raise ValueError(f"GitHub repository must be in 'owner/repo' format: {result}")
35
+
36
+
37
+ parts = result.split('/') # Split and validate components using the dedicated classes
38
+ if len(parts) != 2:
39
+ raise ValueError(f"GitHub repository must be in 'owner/repo' format: {result}")
40
+
41
+ owner_part, repo_part = parts
42
+
43
+ result.repo_owner = Safe_Str__GitHub__Repo_Owner(owner_part) # Validate using the dedicated classes (and store the references)
44
+ result.repo_name = Safe_Str__GitHub__Repo_Name(repo_part ) # This will raise appropriate errors if validation fails
45
+
46
+ return result
@@ -0,0 +1,35 @@
1
+ import re
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
+
4
+ TYPE_SAFE_STR__GITHUB__REPO_NAME__REGEX = re.compile(r'[^a-zA-Z0-9\-_.]')
5
+ TYPE_SAFE_STR__GITHUB__REPO_NAME__MAX_LENGTH = 100
6
+
7
+ class Safe_Str__GitHub__Repo_Name(Safe_Str):
8
+ """
9
+ Safe string class for GitHub repository names.
10
+
11
+ GitHub repository name rules:
12
+ - May contain alphanumeric characters, hyphens, underscores, and periods
13
+ - Maximum length of 100 characters
14
+ - Cannot be empty
15
+ """
16
+ regex = TYPE_SAFE_STR__GITHUB__REPO_NAME__REGEX
17
+ max_length = TYPE_SAFE_STR__GITHUB__REPO_NAME__MAX_LENGTH
18
+ allow_empty = False
19
+ trim_whitespace = True
20
+ allow_all_replacement_char = False
21
+
22
+ def __new__(cls, value=None):
23
+ result = super().__new__(cls, value)
24
+
25
+ # Additional validation
26
+ if result:
27
+ # Check if it's just periods (reserved names)
28
+ if result in ['.', '..']:
29
+ raise ValueError(f"Invalid repository name: {result}")
30
+
31
+ # Check for all replacement characters
32
+ if set(result) == {'_'} and len(result) > 0:
33
+ raise ValueError(f"Invalid repository name: {result}")
34
+
35
+ return result
@@ -0,0 +1,39 @@
1
+ import re
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
+
4
+ TYPE_SAFE_STR__GITHUB__REPO_OWNER__REGEX = re.compile(r'[^a-zA-Z0-9\-]')
5
+ TYPE_SAFE_STR__GITHUB__REPO_OWNER__MAX_LENGTH = 39
6
+
7
+ class Safe_Str__GitHub__Repo_Owner(Safe_Str):
8
+ """
9
+ Safe string class for GitHub repository owners (users or organizations).
10
+
11
+ GitHub username/organization rules:
12
+ - May only contain alphanumeric characters or hyphens
13
+ - Cannot have multiple consecutive hyphens
14
+ - Cannot begin or end with a hyphen
15
+ - Maximum length of 39 characters
16
+ """
17
+ regex = TYPE_SAFE_STR__GITHUB__REPO_OWNER__REGEX
18
+ max_length = TYPE_SAFE_STR__GITHUB__REPO_OWNER__MAX_LENGTH
19
+ allow_empty = False
20
+ trim_whitespace = True
21
+ allow_all_replacement_char = False
22
+
23
+ def __new__(cls, value=None):
24
+ result = super().__new__(cls, value)
25
+
26
+
27
+ if result: # Additional GitHub-specific validation
28
+ if result.startswith('-') or result.endswith('-'): # Check for leading/trailing hyphens
29
+ raise ValueError(f"GitHub owner name cannot start or end with a hyphen: {result}")
30
+
31
+ if '--' in result: # Check for consecutive hyphens
32
+ raise ValueError(f"GitHub owner name cannot contain consecutive hyphens: {result}")
33
+
34
+ if result.replace('_', '') == '': # Check for all underscores (sanitized invalid input)
35
+ raise ValueError(f"Invalid GitHub owner name: {result}")
36
+
37
+ return result
38
+
39
+
@@ -1,5 +1,5 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
3
 
4
4
  TYPE_SAFE_STR__HTTP__CONTENT_TYPE__REGEX = re.compile(r'[^a-zA-Z0-9/\-+.;= ]')
5
5
  TYPE_SAFE_STR__HTTP__CONTENT_TYPE__MAX_LENGTH = 256
@@ -1,5 +1,5 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
3
 
4
4
  TYPE_SAFE_STR__HTTP__ETAG__REGEX = re.compile(r'[^a-zA-Z0-9"\/\-_.:]') # Allow alphanumerics, quotes, slashes, hyphens, underscores, periods, colons
5
5
  TYPE_SAFE_STR__HTTP__ETAG__MAX_LENGTH = 128
@@ -1,5 +1,5 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
3
 
4
4
  TYPE_SAFE_STR__HTTP__LAST_MODIFIED__REGEX = re.compile(r'[^a-zA-Z0-9:, -]')
5
5
  TYPE_SAFE_STR__HTTP__LAST_MODIFIED__MAX_LENGTH = 64
@@ -1,5 +1,5 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
3
 
4
4
 
5
5
  TYPE_SAFE_STR__TEXT__MAX_LENGTH = 1048576 # Define the size constant - 1 megabyte in bytes
@@ -1,9 +1,10 @@
1
1
  import uuid
2
- from osbot_utils.utils.Misc import is_guid
2
+ from osbot_utils.type_safe.Type_Safe__Primitive import Type_Safe__Primitive
3
+ from osbot_utils.utils.Misc import is_guid
3
4
 
4
5
  GUID__NAMESPACE = uuid.UUID('2cfec064-537a-4ff7-8fdc-2fc9e2606f3d')
5
6
 
6
- class Guid(str):
7
+ class Guid(Type_Safe__Primitive, str):
7
8
  def __new__(cls, value: str):
8
9
  if not isinstance(value, str): # Check if the value is a string
9
10
  raise ValueError(f'in Guid: value provided was not a string: {value}') # if not raise a ValueError
@@ -1,5 +1,5 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
3
 
4
4
  TYPE_SAFE_STR__TEXT__MAX_LENGTH = 4096
5
5
  TYPE_SAFE_STR__TEXT__REGEX = r'[^a-zA-Z0-9_ ()\[\]\-+=:;,.?]'
@@ -1,5 +1,5 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
3
 
4
4
  TYPE_SAFE_STR__TEXT__DANGEROUS__MAX_LENGTH = 65536
5
5
  TYPE_SAFE_STR__TEXT__DANGEROUS__REGEX = r'[^a-zA-Z0-9_\s!@#$%^&*()\[\]{}\-+=:;,.?"/\\<>\']'
@@ -1,5 +1,5 @@
1
1
  import re
2
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
2
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
3
3
 
4
4
  # Define the size constant
5
5
  TYPE_SAFE_STR__HTML__MAX_LENGTH = 1048576 # 1 megabyte in bytes
@@ -1,6 +1,6 @@
1
1
 
2
2
  import re
3
- from osbot_utils.helpers.safe_str.Safe_Str import Safe_Str
3
+ from osbot_utils.type_safe.primitives.safe_str.Safe_Str import Safe_Str
4
4
 
5
5
  TYPE_SAFE_STR__URL__MAX_LENGTH = 2048 # Common maximum URL length
6
6
  TYPE_SAFE_STR__URL__REGEX = re.compile(r'^(?!https?://).*|[^a-zA-Z0-9:/\-._~&=?#+%@]') # Allow characters valid in URLs
@@ -1,4 +1,5 @@
1
- from osbot_utils.helpers.safe_int.Safe_Int import Safe_Int
1
+ from osbot_utils.type_safe.primitives.safe_int.Safe_Int import Safe_Int
2
+
2
3
 
3
4
  class Safe_UInt(Safe_Int): # Unsigned Integer - only accepts non-negative integer values
4
5
 
@@ -1,4 +1,4 @@
1
- from osbot_utils.helpers.safe_int.Safe_UInt import Safe_UInt
1
+ from osbot_utils.type_safe.primitives.safe_uint.Safe_UInt import Safe_UInt
2
2
 
3
3
  TYPE_SAFE_UINT__BYTE__MIN_VALUE = 0
4
4
  TYPE_SAFE_UINT__BYTE__MAX_VALUE = 255
@@ -1,4 +1,4 @@
1
- from osbot_utils.helpers.safe_int.Safe_UInt import Safe_UInt
1
+ from osbot_utils.type_safe.primitives.safe_uint.Safe_UInt import Safe_UInt
2
2
 
3
3
  TYPE_SAFE_UINT__FILE_SIZE__MIN_VALUE = 0
4
4
  TYPE_SAFE_UINT__FILE_SIZE__MAX_VALUE = 2 ** 63 - 1 # Max file size on most systems
@@ -1,4 +1,4 @@
1
- from osbot_utils.helpers.safe_int.Safe_UInt import Safe_UInt
1
+ from osbot_utils.type_safe.primitives.safe_uint.Safe_UInt import Safe_UInt
2
2
 
3
3
  TYPE_SAFE_UINT__PERCENTAGE__MIN_VALUE = 0
4
4
  TYPE_SAFE_UINT__PERCENTAGE__MAX_VALUE = 100
@@ -1,4 +1,4 @@
1
- from osbot_utils.helpers.safe_int.Safe_UInt import Safe_UInt
1
+ from osbot_utils.type_safe.primitives.safe_uint.Safe_UInt import Safe_UInt
2
2
 
3
3
  TYPE_SAFE_UINT__PORT__MIN_VALUE = 0
4
4
  TYPE_SAFE_UINT__PORT__MAX_VALUE = 65535
File without changes
File without changes
@@ -1,6 +1,7 @@
1
- from typing import Type
2
- from osbot_utils.type_safe.Type_Safe__List import Type_Safe__List
3
- from osbot_utils.type_safe.Type_Safe__Base import Type_Safe__Base
1
+ from typing import Type
2
+ from osbot_utils.type_safe.Type_Safe__Base import Type_Safe__Base
3
+ from osbot_utils.type_safe.type_safe_core.collections.Type_Safe__List import Type_Safe__List
4
+
4
5
 
5
6
  class Type_Safe__Dict(Type_Safe__Base, dict):
6
7
  def __init__(self, expected_key_type, expected_value_type, *args, **kwargs):
@@ -1,5 +1,6 @@
1
1
  import functools # For wrapping functions
2
- from osbot_utils.type_safe.Type_Safe__Method import Type_Safe__Method
2
+ from osbot_utils.type_safe.type_safe_core.methods.Type_Safe__Method import Type_Safe__Method
3
+
3
4
 
4
5
  def type_safe(func): # Main decorator function
5
6
  type_checker = Type_Safe__Method(func) # Create type checker instance
@@ -1,8 +1,7 @@
1
- import inspect # For function introspection
2
- from enum import Enum
3
- from typing import get_args, get_origin, Union, List, Any, Dict # For type hinting utilities
4
-
5
- from osbot_utils.type_safe.shared.Type_Safe__Shared__Variables import IMMUTABLE_TYPES
1
+ import inspect # For function introspection
2
+ from enum import Enum
3
+ from typing import get_args, get_origin, Union, List, Any, Dict # For type hinting utilities
4
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Shared__Variables import IMMUTABLE_TYPES
6
5
 
7
6
 
8
7
  class Type_Safe__Method: # Class to handle method type safety validation
@@ -1,4 +1,4 @@
1
- from osbot_utils.type_safe.shared.Type_Safe__Cache import type_safe_cache
1
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Cache import type_safe_cache
2
2
 
3
3
 
4
4
  class Type_Safe__Annotations:
@@ -1,7 +1,7 @@
1
1
  import inspect
2
- from weakref import WeakKeyDictionary
3
- from osbot_utils.type_safe.shared.Type_Safe__Not_Cached import type_safe_not_cached
4
- from osbot_utils.type_safe.shared.Type_Safe__Shared__Variables import IMMUTABLE_TYPES
2
+ from weakref import WeakKeyDictionary
3
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Not_Cached import type_safe_not_cached
4
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Shared__Variables import IMMUTABLE_TYPES
5
5
 
6
6
 
7
7
  class Type_Safe__Cache:
@@ -1,6 +1,6 @@
1
- from typing import get_args
2
- from osbot_utils.type_safe.shared.Type_Safe__Cache import type_safe_cache
3
- from osbot_utils.utils.Objects import base_classes_names
1
+ from typing import get_args
2
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Cache import type_safe_cache
3
+ from osbot_utils.utils.Objects import base_classes_names
4
4
 
5
5
 
6
6
  class Type_Safe__Convert:
@@ -1,9 +1,9 @@
1
- from typing import Dict, Any, Type
2
- from osbot_utils.type_safe.Type_Safe__Base import Type_Safe__Base
3
- from osbot_utils.type_safe.Type_Safe import Type_Safe
4
- from osbot_utils.type_safe.shared.Type_Safe__Cache import type_safe_cache
5
- from osbot_utils.type_safe.shared.Type_Safe__Json_Compressor__Type_Registry import Type_Safe__Json_Compressor__Type_Registry
6
- from osbot_utils.utils.Objects import class_full_name
1
+ from typing import Dict, Any, Type
2
+ from osbot_utils.type_safe.Type_Safe__Base import Type_Safe__Base
3
+ from osbot_utils.type_safe.Type_Safe import Type_Safe
4
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Cache import type_safe_cache
5
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Json_Compressor__Type_Registry import Type_Safe__Json_Compressor__Type_Registry
6
+ from osbot_utils.utils.Objects import class_full_name
7
7
 
8
8
  class Type_Safe__Json_Compressor(Type_Safe__Base):
9
9
 
@@ -1,4 +1,4 @@
1
- from osbot_utils.type_safe.shared.Type_Safe__Shared__Variables import IMMUTABLE_TYPES
1
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Shared__Variables import IMMUTABLE_TYPES
2
2
 
3
3
 
4
4
  class Type_Safe__Raise_Exception:
@@ -2,13 +2,14 @@ import collections
2
2
  import inspect
3
3
  import types
4
4
  import typing
5
- from enum import EnumMeta
6
- from typing import Any, Annotated, Optional, get_args, get_origin, ForwardRef, Type, Dict, _GenericAlias
7
- from osbot_utils.type_safe.Type_Safe__Primitive import Type_Safe__Primitive
8
- from osbot_utils.type_safe.shared.Type_Safe__Annotations import type_safe_annotations
9
- from osbot_utils.type_safe.shared.Type_Safe__Cache import type_safe_cache
10
- from osbot_utils.type_safe.shared.Type_Safe__Shared__Variables import IMMUTABLE_TYPES
11
- from osbot_utils.type_safe.shared.Type_Safe__Raise_Exception import type_safe_raise_exception
5
+ from enum import EnumMeta
6
+ from typing import Any, Annotated, Optional, get_args, get_origin, ForwardRef, Type, Dict, _GenericAlias
7
+ from osbot_utils.type_safe.Type_Safe__Primitive import Type_Safe__Primitive
8
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Annotations import type_safe_annotations
9
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Cache import type_safe_cache
10
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Raise_Exception import type_safe_raise_exception
11
+ from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Shared__Variables import IMMUTABLE_TYPES
12
+
12
13
 
13
14
  class Type_Safe__Validation:
14
15