cuenca-validations 2.0.5.dev3__tar.gz → 2.0.5.dev5__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.
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/PKG-INFO +1 -1
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/__init__.py +2 -2
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/general.py +3 -3
- cuenca_validations-2.0.5.dev5/cuenca_validations/types/helpers.py +22 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/requests.py +2 -2
- cuenca_validations-2.0.5.dev5/cuenca_validations/version.py +1 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations.egg-info/PKG-INFO +1 -1
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/tests/test_types.py +54 -13
- cuenca_validations-2.0.5.dev3/cuenca_validations/types/helpers.py +0 -10
- cuenca_validations-2.0.5.dev3/cuenca_validations/version.py +0 -1
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/LICENSE +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/README.md +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/__init__.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/card_bins.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/errors.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/py.typed +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/card.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/enums.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/files.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/identities.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/morals.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/queries.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/typing.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/validators.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations.egg-info/SOURCES.txt +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations.egg-info/dependency_links.txt +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations.egg-info/requires.txt +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations.egg-info/top_level.txt +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/setup.cfg +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/setup.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/tests/__init__.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/tests/test_card.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/tests/test_errors.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/tests/test_helpers.py +0 -0
- {cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/tests/test_statement.py +0 -0
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/__init__.py
RENAMED
|
@@ -104,7 +104,7 @@ __all__ = [
|
|
|
104
104
|
'digits',
|
|
105
105
|
'get_state_name',
|
|
106
106
|
'uuid_field',
|
|
107
|
-
'
|
|
107
|
+
'LogConfig',
|
|
108
108
|
]
|
|
109
109
|
|
|
110
110
|
from .card import StrictPaymentCardNumber
|
|
@@ -153,7 +153,7 @@ from .enums import (
|
|
|
153
153
|
from .files import BatchFileMetadata
|
|
154
154
|
from .general import (
|
|
155
155
|
JSONEncoder,
|
|
156
|
-
|
|
156
|
+
LogConfig,
|
|
157
157
|
SantizedDict,
|
|
158
158
|
StrictPositiveInt,
|
|
159
159
|
digits,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
from base64 import urlsafe_b64encode
|
|
3
|
+
from typing import Callable, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic.fields import FieldInfo
|
|
6
|
+
|
|
7
|
+
from .general import LogConfig
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def uuid_field(prefix: str = '') -> Callable[[], str]:
|
|
11
|
+
def base64_uuid_func() -> str:
|
|
12
|
+
return prefix + urlsafe_b64encode(uuid.uuid4().bytes).decode()[:-2]
|
|
13
|
+
|
|
14
|
+
return base64_uuid_func
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_log_config(field: FieldInfo) -> Optional[LogConfig]:
|
|
18
|
+
"""Helper function to find LogConfig in field metadata"""
|
|
19
|
+
try:
|
|
20
|
+
return next(m for m in field.metadata if isinstance(m, LogConfig))
|
|
21
|
+
except StopIteration:
|
|
22
|
+
return None
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/requests.py
RENAMED
|
@@ -55,7 +55,7 @@ from .card import (
|
|
|
55
55
|
StrictPaymentCardNumber,
|
|
56
56
|
)
|
|
57
57
|
from .general import (
|
|
58
|
-
|
|
58
|
+
LogConfig,
|
|
59
59
|
SerializableAnyUrl,
|
|
60
60
|
SerializableHttpUrl,
|
|
61
61
|
StrictPositiveInt,
|
|
@@ -496,7 +496,7 @@ class UserUpdateRequest(BaseModel):
|
|
|
496
496
|
|
|
497
497
|
class UserLoginRequest(BaseRequest):
|
|
498
498
|
password: Annotated[
|
|
499
|
-
str,
|
|
499
|
+
str, LogConfig(masked=True)
|
|
500
500
|
] # Set password field to str for backward compatibility.
|
|
501
501
|
user_id: Optional[str] = Field(None, description='Deprecated field')
|
|
502
502
|
model_config = ConfigDict(
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.0.5.dev5'
|
|
@@ -6,7 +6,8 @@ from typing import Annotated
|
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
8
8
|
from freezegun import freeze_time
|
|
9
|
-
from pydantic import BaseModel, SecretStr, ValidationError
|
|
9
|
+
from pydantic import AfterValidator, BaseModel, SecretStr, ValidationError
|
|
10
|
+
from pydantic.fields import FieldInfo
|
|
10
11
|
|
|
11
12
|
from cuenca_validations.types import (
|
|
12
13
|
Address,
|
|
@@ -25,7 +26,9 @@ from cuenca_validations.types.enums import (
|
|
|
25
26
|
SessionType,
|
|
26
27
|
State,
|
|
27
28
|
)
|
|
28
|
-
from cuenca_validations.types.general import
|
|
29
|
+
from cuenca_validations.types.general import LogConfig, StrictPositiveInt
|
|
30
|
+
from cuenca_validations.types.helpers import get_log_config
|
|
31
|
+
from cuenca_validations.types.identities import Password
|
|
29
32
|
from cuenca_validations.types.requests import (
|
|
30
33
|
ApiKeyUpdateRequest,
|
|
31
34
|
BankAccountValidationRequest,
|
|
@@ -589,22 +592,60 @@ def test_strict_positive_int_invalid(value, expected_error, expected_message):
|
|
|
589
592
|
IntModel(value=value)
|
|
590
593
|
|
|
591
594
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
+
def validate_repeated_digits(password: str) -> str:
|
|
596
|
+
"""
|
|
597
|
+
Example of a custom validator
|
|
598
|
+
Check if the str contains repeated numbers
|
|
599
|
+
"""
|
|
600
|
+
import re
|
|
601
|
+
|
|
602
|
+
if re.search(r'(\d).*\1', password):
|
|
603
|
+
raise ValueError("str cannot contain repeated digits")
|
|
604
|
+
return password
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
class LogConfigModel(BaseModel):
|
|
608
|
+
password: Annotated[Password, LogConfig(masked=True)]
|
|
609
|
+
validated: Annotated[
|
|
610
|
+
str, AfterValidator(validate_repeated_digits), LogConfig(masked=True)
|
|
611
|
+
]
|
|
612
|
+
secret: Annotated[str, LogConfig(masked=True)]
|
|
613
|
+
partial_secret: Annotated[
|
|
614
|
+
str, LogConfig(masked=True, unmasked_chars_length=4)
|
|
615
|
+
]
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def test_log_config():
|
|
619
|
+
model = LogConfigModel(
|
|
620
|
+
password="Mypass123.",
|
|
621
|
+
validated="str123",
|
|
622
|
+
secret="super-secret",
|
|
623
|
+
partial_secret="1234567890",
|
|
624
|
+
)
|
|
595
625
|
|
|
626
|
+
password_field = LogConfigModel.model_fields["password"]
|
|
627
|
+
validated_field = LogConfigModel.model_fields["validated"]
|
|
628
|
+
secret_field = LogConfigModel.model_fields["secret"]
|
|
629
|
+
partial_field = LogConfigModel.model_fields["partial_secret"]
|
|
596
630
|
|
|
597
|
-
|
|
598
|
-
|
|
631
|
+
assert get_log_config(password_field).masked is True
|
|
632
|
+
assert get_log_config(password_field).unmasked_chars_length == 0
|
|
599
633
|
|
|
600
|
-
|
|
601
|
-
|
|
634
|
+
assert get_log_config(validated_field).masked is True
|
|
635
|
+
assert get_log_config(validated_field).unmasked_chars_length == 0
|
|
602
636
|
|
|
603
|
-
assert secret_field.
|
|
604
|
-
assert secret_field.
|
|
637
|
+
assert get_log_config(secret_field).masked is True
|
|
638
|
+
assert get_log_config(secret_field).unmasked_chars_length == 0
|
|
605
639
|
|
|
606
|
-
assert partial_field.
|
|
607
|
-
assert partial_field.
|
|
640
|
+
assert get_log_config(partial_field).masked is True
|
|
641
|
+
assert get_log_config(partial_field).unmasked_chars_length == 4
|
|
608
642
|
|
|
643
|
+
assert model.password.get_secret_value() == "Mypass123."
|
|
644
|
+
assert model.validated == "str123"
|
|
609
645
|
assert model.secret == "super-secret"
|
|
610
646
|
assert model.partial_secret == "1234567890"
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
def test_get_log_config_no_log_config():
|
|
650
|
+
field = FieldInfo(default=None)
|
|
651
|
+
assert get_log_config(field) is None
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import uuid
|
|
2
|
-
from base64 import urlsafe_b64encode
|
|
3
|
-
from typing import Callable
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def uuid_field(prefix: str = '') -> Callable[[], str]:
|
|
7
|
-
def base64_uuid_func() -> str:
|
|
8
|
-
return prefix + urlsafe_b64encode(uuid.uuid4().bytes).decode()[:-2]
|
|
9
|
-
|
|
10
|
-
return base64_uuid_func
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '2.0.5.dev3'
|
|
File without changes
|
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/__init__.py
RENAMED
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/card_bins.py
RENAMED
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/errors.py
RENAMED
|
File without changes
|
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/card.py
RENAMED
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/enums.py
RENAMED
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/files.py
RENAMED
|
File without changes
|
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/morals.py
RENAMED
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/types/queries.py
RENAMED
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/typing.py
RENAMED
|
File without changes
|
{cuenca_validations-2.0.5.dev3 → cuenca_validations-2.0.5.dev5}/cuenca_validations/validators.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
|
|
File without changes
|