quantum-framework 0.18.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.
- quantum/__init__.py +1 -0
- quantum/cli/__init__.py +2 -0
- quantum/cli/admin.py +131 -0
- quantum/cli/check.py +223 -0
- quantum/cli/commands/__init__.py +15 -0
- quantum/cli/commands/build.py +414 -0
- quantum/cli/commands/dev.py +185 -0
- quantum/cli/commands/docs.py +329 -0
- quantum/cli/commands/lint.py +523 -0
- quantum/cli/commands/migrate.py +548 -0
- quantum/cli/commands/new.py +622 -0
- quantum/cli/commands/serve.py +190 -0
- quantum/cli/commands/test.py +193 -0
- quantum/cli/deploy.py +810 -0
- quantum/cli/hot_reload.py +951 -0
- quantum/cli/jobs.py +356 -0
- quantum/cli/mq.py +582 -0
- quantum/cli/pkg.py +390 -0
- quantum/cli/runner.py +565 -0
- quantum/cli/server_process.py +159 -0
- quantum/cli/utils.py +334 -0
- quantum/compiler/__init__.py +30 -0
- quantum/compiler/base_generator.py +367 -0
- quantum/compiler/cli.py +295 -0
- quantum/compiler/expression_transformer.py +444 -0
- quantum/compiler/javascript/__init__.py +10 -0
- quantum/compiler/javascript/generator.py +659 -0
- quantum/compiler/optimizer.py +270 -0
- quantum/compiler/python/__init__.py +10 -0
- quantum/compiler/python/generator.py +883 -0
- quantum/compiler/python/runtime.py +863 -0
- quantum/compiler/transpiler.py +330 -0
- quantum/core/__init__.py +3 -0
- quantum/core/ast_nodes.py +2619 -0
- quantum/core/config_env.py +54 -0
- quantum/core/docs_links.py +8 -0
- quantum/core/expression_diagnostics.py +87 -0
- quantum/core/expression_stdlib.py +208 -0
- quantum/core/expressions.py +677 -0
- quantum/core/features/agents/src/__init__.py +30 -0
- quantum/core/features/agents/src/ast_node.py +540 -0
- quantum/core/features/conditionals/src/__init__.py +8 -0
- quantum/core/features/conditionals/src/ast_node.py +68 -0
- quantum/core/features/data_import/src/__init__.py +0 -0
- quantum/core/features/data_import/src/ast_node.py +292 -0
- quantum/core/features/data_import/src/runtime.py +533 -0
- quantum/core/features/dump/src/__init__.py +12 -0
- quantum/core/features/dump/src/ast_node.py +106 -0
- quantum/core/features/dump/src/parser.py +61 -0
- quantum/core/features/dump/src/runtime.py +246 -0
- quantum/core/features/functions/src/__init__.py +8 -0
- quantum/core/features/functions/src/ast_node.py +149 -0
- quantum/core/features/game_engine_2d/src/__init__.py +19 -0
- quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
- quantum/core/features/game_engine_2d/src/parser.py +983 -0
- quantum/core/features/invocation/src/__init__.py +0 -0
- quantum/core/features/invocation/src/ast_node.py +147 -0
- quantum/core/features/invocation/src/runtime.py +332 -0
- quantum/core/features/knowledge_base/src/__init__.py +6 -0
- quantum/core/features/knowledge_base/src/ast_node.py +113 -0
- quantum/core/features/knowledge_base/src/parser.py +82 -0
- quantum/core/features/logging/src/__init__.py +12 -0
- quantum/core/features/logging/src/ast_node.py +111 -0
- quantum/core/features/logging/src/parser.py +50 -0
- quantum/core/features/logging/src/runtime.py +190 -0
- quantum/core/features/loops/src/__init__.py +8 -0
- quantum/core/features/loops/src/ast_node.py +60 -0
- quantum/core/features/query/src/__init__.py +0 -0
- quantum/core/features/query/src/query_validators.py +20 -0
- quantum/core/features/state_management/src/__init__.py +11 -0
- quantum/core/features/state_management/src/ast_node.py +121 -0
- quantum/core/features/terminal_engine/src/__init__.py +21 -0
- quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
- quantum/core/features/terminal_engine/src/parser.py +361 -0
- quantum/core/features/testing_engine/src/__init__.py +41 -0
- quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
- quantum/core/features/testing_engine/src/parser.py +604 -0
- quantum/core/features/theming/src/__init__.py +48 -0
- quantum/core/features/theming/src/ast_node.py +137 -0
- quantum/core/features/theming/src/presets.py +405 -0
- quantum/core/features/ui_engine/src/__init__.py +20 -0
- quantum/core/features/ui_engine/src/ast_nodes.py +1913 -0
- quantum/core/features/ui_engine/src/parser.py +1192 -0
- quantum/core/features/websocket/src/__init__.py +24 -0
- quantum/core/features/websocket/src/ast_node.py +247 -0
- quantum/core/guards.py +53 -0
- quantum/core/html_compat.py +299 -0
- quantum/core/parser.py +1551 -0
- quantum/core/parser_registry.py +213 -0
- quantum/core/parsers/__init__.py +76 -0
- quantum/core/parsers/ai/__init__.py +12 -0
- quantum/core/parsers/ai/agent_parser.py +106 -0
- quantum/core/parsers/ai/knowledge_parser.py +86 -0
- quantum/core/parsers/ai/llm_parser.py +78 -0
- quantum/core/parsers/ai/team_parser.py +88 -0
- quantum/core/parsers/base.py +322 -0
- quantum/core/parsers/composition/__init__.py +10 -0
- quantum/core/parsers/composition/import_parser.py +50 -0
- quantum/core/parsers/composition/slot_parser.py +48 -0
- quantum/core/parsers/control_flow/__init__.py +11 -0
- quantum/core/parsers/control_flow/if_parser.py +71 -0
- quantum/core/parsers/control_flow/loop_parser.py +105 -0
- quantum/core/parsers/control_flow/set_parser.py +93 -0
- quantum/core/parsers/data/__init__.py +12 -0
- quantum/core/parsers/data/data_parser.py +229 -0
- quantum/core/parsers/data/invoke_parser.py +133 -0
- quantum/core/parsers/data/query_parser.py +213 -0
- quantum/core/parsers/data/transaction_parser.py +86 -0
- quantum/core/parsers/events/__init__.py +9 -0
- quantum/core/parsers/events/dispatch_event_parser.py +44 -0
- quantum/core/parsers/forms/__init__.py +11 -0
- quantum/core/parsers/forms/action_parser.py +79 -0
- quantum/core/parsers/forms/flash_parser.py +34 -0
- quantum/core/parsers/forms/redirect_parser.py +33 -0
- quantum/core/parsers/functions/__init__.py +11 -0
- quantum/core/parsers/functions/function_parser.py +98 -0
- quantum/core/parsers/functions/param_parser.py +73 -0
- quantum/core/parsers/functions/return_parser.py +31 -0
- quantum/core/parsers/html/__init__.py +10 -0
- quantum/core/parsers/html/component_call_parser.py +130 -0
- quantum/core/parsers/html/html_parser.py +115 -0
- quantum/core/parsers/jobs/__init__.py +11 -0
- quantum/core/parsers/jobs/job_parser.py +71 -0
- quantum/core/parsers/jobs/schedule_parser.py +62 -0
- quantum/core/parsers/jobs/thread_parser.py +57 -0
- quantum/core/parsers/messaging/__init__.py +17 -0
- quantum/core/parsers/messaging/message_ack_parser.py +30 -0
- quantum/core/parsers/messaging/message_nack_parser.py +30 -0
- quantum/core/parsers/messaging/message_parser.py +114 -0
- quantum/core/parsers/messaging/queue_parser.py +61 -0
- quantum/core/parsers/messaging/websocket_parser.py +121 -0
- quantum/core/parsers/routing/__init__.py +9 -0
- quantum/core/parsers/routing/route_parser.py +41 -0
- quantum/core/parsers/scripting/__init__.py +12 -0
- quantum/core/parsers/scripting/pyclass_parser.py +62 -0
- quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
- quantum/core/parsers/scripting/pyimport_parser.py +52 -0
- quantum/core/parsers/scripting/python_parser.py +49 -0
- quantum/core/parsers/services/__init__.py +12 -0
- quantum/core/parsers/services/dump_parser.py +52 -0
- quantum/core/parsers/services/file_parser.py +48 -0
- quantum/core/parsers/services/log_parser.py +46 -0
- quantum/core/parsers/services/mail_parser.py +65 -0
- quantum/core/tiers.py +164 -0
- quantum/core/xml_lines.py +81 -0
- quantum/packages/__init__.py +28 -0
- quantum/packages/manager.py +413 -0
- quantum/packages/manifest.py +351 -0
- quantum/packages/registry.py +399 -0
- quantum/packages/resolver.py +336 -0
- quantum/plugins/__init__.py +33 -0
- quantum/plugins/hooks.py +329 -0
- quantum/plugins/loader.py +479 -0
- quantum/plugins/manifest.py +336 -0
- quantum/plugins/registry.py +371 -0
- quantum/runtime/__init__.py +25 -0
- quantum/runtime/action_handler.py +532 -0
- quantum/runtime/adapters/__init__.py +88 -0
- quantum/runtime/adapters/memory_adapter.py +690 -0
- quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
- quantum/runtime/adapters/redis_adapter.py +582 -0
- quantum/runtime/adapters/sqlite_adapter.py +414 -0
- quantum/runtime/agent_service.py +1133 -0
- quantum/runtime/ast_cache.py +506 -0
- quantum/runtime/auth_service.py +267 -0
- quantum/runtime/component.py +1048 -0
- quantum/runtime/component_composer.py +133 -0
- quantum/runtime/component_resolver.py +174 -0
- quantum/runtime/conditions.py +54 -0
- quantum/runtime/database_service.py +595 -0
- quantum/runtime/db_schema.py +100 -0
- quantum/runtime/dev_panel.py +178 -0
- quantum/runtime/email_service.py +162 -0
- quantum/runtime/error_handler.py +295 -0
- quantum/runtime/execution_context.py +283 -0
- quantum/runtime/executor_registry.py +178 -0
- quantum/runtime/executors/__init__.py +71 -0
- quantum/runtime/executors/ai/__init__.py +12 -0
- quantum/runtime/executors/ai/agent_executor.py +217 -0
- quantum/runtime/executors/ai/knowledge_executor.py +114 -0
- quantum/runtime/executors/ai/llm_executor.py +153 -0
- quantum/runtime/executors/ai/team_executor.py +171 -0
- quantum/runtime/executors/base.py +264 -0
- quantum/runtime/executors/control_flow/__init__.py +12 -0
- quantum/runtime/executors/control_flow/if_executor.py +98 -0
- quantum/runtime/executors/control_flow/loop_executor.py +308 -0
- quantum/runtime/executors/control_flow/redirect_executor.py +43 -0
- quantum/runtime/executors/control_flow/set_executor.py +464 -0
- quantum/runtime/executors/data/__init__.py +12 -0
- quantum/runtime/executors/data/data_executor.py +156 -0
- quantum/runtime/executors/data/invoke_executor.py +228 -0
- quantum/runtime/executors/data/query_executor.py +290 -0
- quantum/runtime/executors/data/transaction_executor.py +91 -0
- quantum/runtime/executors/jobs/__init__.py +11 -0
- quantum/runtime/executors/jobs/job_executor.py +190 -0
- quantum/runtime/executors/jobs/schedule_executor.py +132 -0
- quantum/runtime/executors/jobs/thread_executor.py +127 -0
- quantum/runtime/executors/messaging/__init__.py +17 -0
- quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
- quantum/runtime/executors/messaging/message_executor.py +174 -0
- quantum/runtime/executors/messaging/queue_executor.py +103 -0
- quantum/runtime/executors/messaging/websocket_executor.py +197 -0
- quantum/runtime/executors/scripting/__init__.py +11 -0
- quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
- quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
- quantum/runtime/executors/scripting/python_executor.py +249 -0
- quantum/runtime/executors/services/__init__.py +12 -0
- quantum/runtime/executors/services/dump_executor.py +72 -0
- quantum/runtime/executors/services/file_executor.py +89 -0
- quantum/runtime/executors/services/log_executor.py +77 -0
- quantum/runtime/executors/services/mail_executor.py +81 -0
- quantum/runtime/expression_cache.py +498 -0
- quantum/runtime/file_upload_service.py +326 -0
- quantum/runtime/function_registry.py +118 -0
- quantum/runtime/game_builder.py +166 -0
- quantum/runtime/game_code_generator.py +2371 -0
- quantum/runtime/game_templates.py +2006 -0
- quantum/runtime/godot_code_generator.py +4681 -0
- quantum/runtime/godot_templates.py +1449 -0
- quantum/runtime/job_executor.py +1599 -0
- quantum/runtime/knowledge_service.py +546 -0
- quantum/runtime/llm_cache.py +100 -0
- quantum/runtime/llm_providers.py +704 -0
- quantum/runtime/llm_service.py +287 -0
- quantum/runtime/local_server.py +28 -0
- quantum/runtime/logging_setup.py +141 -0
- quantum/runtime/message_broker.py +364 -0
- quantum/runtime/message_queue_service.py +571 -0
- quantum/runtime/param_validation.py +218 -0
- quantum/runtime/pypy_compat.py +317 -0
- quantum/runtime/python_bridge.py +698 -0
- quantum/runtime/query_validators.py +304 -0
- quantum/runtime/renderer.py +734 -0
- quantum/runtime/service_container.py +470 -0
- quantum/runtime/table_params.py +163 -0
- quantum/runtime/terminal_builder.py +76 -0
- quantum/runtime/terminal_code_generator.py +607 -0
- quantum/runtime/terminal_templates.py +243 -0
- quantum/runtime/testing_builder.py +77 -0
- quantum/runtime/testing_code_generator.py +833 -0
- quantum/runtime/testing_templates.py +85 -0
- quantum/runtime/ui_builder.py +222 -0
- quantum/runtime/ui_console.py +405 -0
- quantum/runtime/ui_desktop.py +56 -0
- quantum/runtime/ui_form_rules.py +193 -0
- quantum/runtime/ui_html_adapter.py +2567 -0
- quantum/runtime/ui_html_templates.py +2106 -0
- quantum/runtime/ui_mobile_adapter.py +1832 -0
- quantum/runtime/ui_mobile_templates.py +1003 -0
- quantum/runtime/ui_page_renderer.py +392 -0
- quantum/runtime/ui_pager.py +73 -0
- quantum/runtime/ui_table_edit.py +139 -0
- quantum/runtime/ui_textual_adapter.py +1866 -0
- quantum/runtime/ui_textual_templates.py +45 -0
- quantum/runtime/ui_tokens.py +465 -0
- quantum/runtime/ui_validator.py +365 -0
- quantum/runtime/ui_view.py +221 -0
- quantum/runtime/validators.py +256 -0
- quantum/runtime/web_server.py +2131 -0
- quantum/runtime/websocket_adapter.py +501 -0
- quantum/runtime/websocket_service.py +585 -0
- quantum/runtime/websocket_transport.py +289 -0
- quantum/runtime/wsgi.py +101 -0
- quantum/services.py +109 -0
- quantum/utils/__init__.py +1 -0
- quantum_admin/__init__.py +4 -0
- quantum_admin/assets/quantum-admin-connectors.js +123 -0
- quantum_admin/assets/quantum-admin.css +2058 -0
- quantum_admin/assets/quantum-source-highlight.js +106 -0
- quantum_admin/backend/__init__.py +4 -0
- quantum_admin/backend/audit_service.py +346 -0
- quantum_admin/backend/auth_service.py +394 -0
- quantum_admin/backend/component_discovery.py +766 -0
- quantum_admin/backend/config_generator.py +586 -0
- quantum_admin/backend/connector_service.py +1016 -0
- quantum_admin/backend/crud.py +557 -0
- quantum_admin/backend/database.py +226 -0
- quantum_admin/backend/db_setup_service.py +193 -0
- quantum_admin/backend/deploy_service.py +698 -0
- quantum_admin/backend/docker_service.py +422 -0
- quantum_admin/backend/environment_service.py +418 -0
- quantum_admin/backend/git_service.py +370 -0
- quantum_admin/backend/health_service.py +390 -0
- quantum_admin/backend/job_service.py +347 -0
- quantum_admin/backend/log_service.py +331 -0
- quantum_admin/backend/main.py +14426 -0
- quantum_admin/backend/models.py +986 -0
- quantum_admin/backend/pipeline_service.py +812 -0
- quantum_admin/backend/resource_manager.py +1118 -0
- quantum_admin/backend/schemas.py +419 -0
- quantum_admin/backend/secret_manager.py +277 -0
- quantum_admin/backend/settings_service.py +488 -0
- quantum_admin/backend/template_service.py +710 -0
- quantum_admin/backend/test_execution_service.py +364 -0
- quantum_admin/backend/test_generator.py +782 -0
- quantum_admin/backend/webhook_service.py +454 -0
- quantum_admin/backend/websocket_manager.py +360 -0
- quantum_admin/components/admin/_layout/AdminShell.q +121 -0
- quantum_admin/components/admin/agents.q +107 -0
- quantum_admin/components/admin/app/[name].q +558 -0
- quantum_admin/components/admin/applications.q +160 -0
- quantum_admin/components/admin/component/[...path].q +205 -0
- quantum_admin/components/admin/components.q +59 -0
- quantum_admin/components/admin/connectors.q +283 -0
- quantum_admin/components/admin/dashboard.q +86 -0
- quantum_admin/components/admin/database.q +95 -0
- quantum_admin/components/admin/features.q +69 -0
- quantum_admin/components/admin/index.q +12 -0
- quantum_admin/components/admin/jobs.q +75 -0
- quantum_admin/components/admin/login.q +65 -0
- quantum_admin/components/admin/logout.q +11 -0
- quantum_admin/components/admin/settings.q +174 -0
- quantum_admin/components/admin/source.q +45 -0
- quantum_admin/components/admin/tests.q +73 -0
- quantum_admin/run.py +13 -0
- quantum_admin/services/__init__.py +16 -0
- quantum_admin/services/_base.py +84 -0
- quantum_admin/services/_component_test_generator.py +205 -0
- quantum_admin/services/_yaml_editor.py +82 -0
- quantum_admin/services/apps.py +330 -0
- quantum_admin/services/auth.py +61 -0
- quantum_admin/services/components.py +210 -0
- quantum_admin/services/connectors.py +164 -0
- quantum_admin/services/projects.py +189 -0
- quantum_admin/services/repository.py +223 -0
- quantum_admin/services/settings.py +150 -0
- quantum_admin/services/yaml_import.py +118 -0
- quantum_framework-0.18.0.dist-info/METADATA +281 -0
- quantum_framework-0.18.0.dist-info/RECORD +333 -0
- quantum_framework-0.18.0.dist-info/WHEEL +5 -0
- quantum_framework-0.18.0.dist-info/entry_points.txt +2 -0
- quantum_framework-0.18.0.dist-info/licenses/LICENSE +21 -0
- quantum_framework-0.18.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Quantum Built-in Validators - Validation rules for q:set
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from typing import Any, Optional, Tuple
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ValidationError(Exception):
|
|
10
|
+
"""Raised when validation fails"""
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class QuantumValidators:
|
|
15
|
+
"""Built-in validators for common data types"""
|
|
16
|
+
|
|
17
|
+
# Regex patterns for built-in validators
|
|
18
|
+
PATTERNS = {
|
|
19
|
+
'email': r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
|
|
20
|
+
'url': r'^https?://[^\s/$.?#].[^\s]*$',
|
|
21
|
+
'cpf': r'^\d{3}\.\d{3}\.\d{3}-\d{2}$',
|
|
22
|
+
'cnpj': r'^\d{2}\.\d{3}\.\d{3}/\d{4}-\d{2}$',
|
|
23
|
+
'phone': r'^\(\d{2}\)\s?\d{4,5}-\d{4}$',
|
|
24
|
+
'cep': r'^\d{5}-\d{3}$',
|
|
25
|
+
'uuid': r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',
|
|
26
|
+
'creditcard': r'^\d{4}\s?\d{4}\s?\d{4}\s?\d{4}$',
|
|
27
|
+
'ipv4': r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$',
|
|
28
|
+
'ipv6': r'^([0-9a-fA-F]{0,4}:){7}[0-9a-fA-F]{0,4}$',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
def validate(value: Any, rule: str, **kwargs) -> Tuple[bool, Optional[str]]:
|
|
33
|
+
"""
|
|
34
|
+
Validate a value against a rule
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
value: Value to validate
|
|
38
|
+
rule: Validation rule name or regex pattern
|
|
39
|
+
**kwargs: Additional validation parameters
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Tuple[bool, Optional[str]]: (is_valid, error_message)
|
|
43
|
+
"""
|
|
44
|
+
if value is None:
|
|
45
|
+
return True, None # None is valid unless required=True
|
|
46
|
+
|
|
47
|
+
# Convert to string for pattern matching
|
|
48
|
+
value_str = str(value)
|
|
49
|
+
|
|
50
|
+
# Check if it's a built-in validator
|
|
51
|
+
if rule in QuantumValidators.PATTERNS:
|
|
52
|
+
pattern = QuantumValidators.PATTERNS[rule]
|
|
53
|
+
if re.match(pattern, value_str):
|
|
54
|
+
return True, None
|
|
55
|
+
else:
|
|
56
|
+
return False, f"Invalid {rule} format"
|
|
57
|
+
|
|
58
|
+
# Check if it's a custom regex pattern
|
|
59
|
+
if rule.startswith('^') or rule.startswith('.*'):
|
|
60
|
+
try:
|
|
61
|
+
if re.match(rule, value_str):
|
|
62
|
+
return True, None
|
|
63
|
+
else:
|
|
64
|
+
return False, f"Value does not match pattern: {rule}"
|
|
65
|
+
except re.error as e:
|
|
66
|
+
return False, f"Invalid regex pattern: {e}"
|
|
67
|
+
|
|
68
|
+
# Unknown validator
|
|
69
|
+
return False, f"Unknown validator: {rule}"
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def validate_cpf(cpf: str) -> Tuple[bool, Optional[str]]:
|
|
73
|
+
"""
|
|
74
|
+
Validate Brazilian CPF (with digit verification)
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
cpf: CPF string (xxx.xxx.xxx-xx)
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Tuple[bool, Optional[str]]: (is_valid, error_message)
|
|
81
|
+
"""
|
|
82
|
+
# Remove formatting
|
|
83
|
+
cpf_digits = re.sub(r'\D', '', cpf)
|
|
84
|
+
|
|
85
|
+
# Check length
|
|
86
|
+
if len(cpf_digits) != 11:
|
|
87
|
+
return False, "CPF must have 11 digits"
|
|
88
|
+
|
|
89
|
+
# Check for known invalid CPFs (all same digit)
|
|
90
|
+
if cpf_digits == cpf_digits[0] * 11:
|
|
91
|
+
return False, "Invalid CPF"
|
|
92
|
+
|
|
93
|
+
# Validate first check digit
|
|
94
|
+
sum_digits = sum(int(cpf_digits[i]) * (10 - i) for i in range(9))
|
|
95
|
+
check_digit_1 = (sum_digits * 10 % 11) % 10
|
|
96
|
+
|
|
97
|
+
if int(cpf_digits[9]) != check_digit_1:
|
|
98
|
+
return False, "Invalid CPF check digit"
|
|
99
|
+
|
|
100
|
+
# Validate second check digit
|
|
101
|
+
sum_digits = sum(int(cpf_digits[i]) * (11 - i) for i in range(10))
|
|
102
|
+
check_digit_2 = (sum_digits * 10 % 11) % 10
|
|
103
|
+
|
|
104
|
+
if int(cpf_digits[10]) != check_digit_2:
|
|
105
|
+
return False, "Invalid CPF check digit"
|
|
106
|
+
|
|
107
|
+
return True, None
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def validate_cnpj(cnpj: str) -> Tuple[bool, Optional[str]]:
|
|
111
|
+
"""
|
|
112
|
+
Validate Brazilian CNPJ (with digit verification)
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
cnpj: CNPJ string (xx.xxx.xxx/xxxx-xx)
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Tuple[bool, Optional[str]]: (is_valid, error_message)
|
|
119
|
+
"""
|
|
120
|
+
# Remove formatting
|
|
121
|
+
cnpj_digits = re.sub(r'\D', '', cnpj)
|
|
122
|
+
|
|
123
|
+
# Check length
|
|
124
|
+
if len(cnpj_digits) != 14:
|
|
125
|
+
return False, "CNPJ must have 14 digits"
|
|
126
|
+
|
|
127
|
+
# Check for known invalid CNPJs (all same digit)
|
|
128
|
+
if cnpj_digits == cnpj_digits[0] * 14:
|
|
129
|
+
return False, "Invalid CNPJ"
|
|
130
|
+
|
|
131
|
+
# Validate first check digit
|
|
132
|
+
weights_1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
|
|
133
|
+
sum_digits = sum(int(cnpj_digits[i]) * weights_1[i] for i in range(12))
|
|
134
|
+
check_digit_1 = (sum_digits % 11)
|
|
135
|
+
check_digit_1 = 0 if check_digit_1 < 2 else 11 - check_digit_1
|
|
136
|
+
|
|
137
|
+
if int(cnpj_digits[12]) != check_digit_1:
|
|
138
|
+
return False, "Invalid CNPJ check digit"
|
|
139
|
+
|
|
140
|
+
# Validate second check digit
|
|
141
|
+
weights_2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
|
|
142
|
+
sum_digits = sum(int(cnpj_digits[i]) * weights_2[i] for i in range(13))
|
|
143
|
+
check_digit_2 = (sum_digits % 11)
|
|
144
|
+
check_digit_2 = 0 if check_digit_2 < 2 else 11 - check_digit_2
|
|
145
|
+
|
|
146
|
+
if int(cnpj_digits[13]) != check_digit_2:
|
|
147
|
+
return False, "Invalid CNPJ check digit"
|
|
148
|
+
|
|
149
|
+
return True, None
|
|
150
|
+
|
|
151
|
+
@staticmethod
|
|
152
|
+
def validate_required(value: Any) -> Tuple[bool, Optional[str]]:
|
|
153
|
+
"""Check if value is not None/empty"""
|
|
154
|
+
if value is None:
|
|
155
|
+
return False, "This field is required"
|
|
156
|
+
if isinstance(value, str) and value.strip() == "":
|
|
157
|
+
return False, "This field cannot be empty"
|
|
158
|
+
if isinstance(value, (list, dict)) and len(value) == 0:
|
|
159
|
+
return False, "This field cannot be empty"
|
|
160
|
+
return True, None
|
|
161
|
+
|
|
162
|
+
@staticmethod
|
|
163
|
+
def validate_range(value: Any, range_str: str) -> Tuple[bool, Optional[str]]:
|
|
164
|
+
"""
|
|
165
|
+
Validate value is within range
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
value: Value to check
|
|
169
|
+
range_str: Range string like "0..100" or "2024-01-01..2025-12-31"
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Tuple[bool, Optional[str]]: (is_valid, error_message)
|
|
173
|
+
"""
|
|
174
|
+
if '..' not in range_str:
|
|
175
|
+
return False, "Invalid range format (use min..max)"
|
|
176
|
+
|
|
177
|
+
parts = range_str.split('..')
|
|
178
|
+
if len(parts) != 2:
|
|
179
|
+
return False, "Invalid range format (use min..max)"
|
|
180
|
+
|
|
181
|
+
min_val, max_val = parts
|
|
182
|
+
|
|
183
|
+
# Try numeric comparison
|
|
184
|
+
try:
|
|
185
|
+
num_value = float(value)
|
|
186
|
+
num_min = float(min_val)
|
|
187
|
+
num_max = float(max_val)
|
|
188
|
+
|
|
189
|
+
if num_min <= num_value <= num_max:
|
|
190
|
+
return True, None
|
|
191
|
+
else:
|
|
192
|
+
return False, f"Value must be between {min_val} and {max_val}"
|
|
193
|
+
except (ValueError, TypeError):
|
|
194
|
+
pass
|
|
195
|
+
|
|
196
|
+
# Try string comparison (for dates, etc.)
|
|
197
|
+
value_str = str(value)
|
|
198
|
+
if min_val <= value_str <= max_val:
|
|
199
|
+
return True, None
|
|
200
|
+
else:
|
|
201
|
+
return False, f"Value must be between {min_val} and {max_val}"
|
|
202
|
+
|
|
203
|
+
@staticmethod
|
|
204
|
+
def validate_enum(value: Any, enum_str: str) -> Tuple[bool, Optional[str]]:
|
|
205
|
+
"""
|
|
206
|
+
Validate value is in enum list
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
value: Value to check
|
|
210
|
+
enum_str: Comma-separated list like "pending,active,inactive"
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Tuple[bool, Optional[str]]: (is_valid, error_message)
|
|
214
|
+
"""
|
|
215
|
+
allowed_values = [v.strip() for v in enum_str.split(',')]
|
|
216
|
+
value_str = str(value)
|
|
217
|
+
|
|
218
|
+
if value_str in allowed_values:
|
|
219
|
+
return True, None
|
|
220
|
+
else:
|
|
221
|
+
return False, f"Value must be one of: {', '.join(allowed_values)}"
|
|
222
|
+
|
|
223
|
+
@staticmethod
|
|
224
|
+
def validate_min_max(value: Any, min_val: Optional[Any] = None, max_val: Optional[Any] = None) -> Tuple[bool, Optional[str]]:
|
|
225
|
+
"""Validate min/max constraints"""
|
|
226
|
+
try:
|
|
227
|
+
num_value = float(value)
|
|
228
|
+
|
|
229
|
+
if min_val is not None:
|
|
230
|
+
num_min = float(min_val)
|
|
231
|
+
if num_value < num_min:
|
|
232
|
+
return False, f"Value must be at least {min_val}"
|
|
233
|
+
|
|
234
|
+
if max_val is not None:
|
|
235
|
+
num_max = float(max_val)
|
|
236
|
+
if num_value > num_max:
|
|
237
|
+
return False, f"Value must be at most {max_val}"
|
|
238
|
+
|
|
239
|
+
return True, None
|
|
240
|
+
|
|
241
|
+
except (ValueError, TypeError):
|
|
242
|
+
return False, "Value must be numeric for min/max validation"
|
|
243
|
+
|
|
244
|
+
@staticmethod
|
|
245
|
+
def validate_length(value: str, minlength: Optional[int] = None, maxlength: Optional[int] = None) -> Tuple[bool, Optional[str]]:
|
|
246
|
+
"""Validate string length constraints"""
|
|
247
|
+
value_str = str(value)
|
|
248
|
+
length = len(value_str)
|
|
249
|
+
|
|
250
|
+
if minlength is not None and length < minlength:
|
|
251
|
+
return False, f"Value must be at least {minlength} characters"
|
|
252
|
+
|
|
253
|
+
if maxlength is not None and length > maxlength:
|
|
254
|
+
return False, f"Value must be at most {maxlength} characters"
|
|
255
|
+
|
|
256
|
+
return True, None
|