fast-validators 0.1.0__py3-none-win_amd64.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.
@@ -0,0 +1,24 @@
1
+ """
2
+ Validators package for content validation in file operations.
3
+
4
+ This package provides a validation system for different file formats
5
+ to ensure content integrity after text replacement operations.
6
+ """
7
+
8
+ from .base_validator import BaseValidator
9
+ from .json_validator import JsonValidator
10
+ from .yaml_validator import YamlValidator
11
+ from .php_validator import PhpValidator
12
+ from .go_validator import GoValidator
13
+ from .js_ts_validator import JS_TS_Validator
14
+ from .validators_catalog import ValidatorsCatalog
15
+
16
+ __all__ = [
17
+ 'BaseValidator',
18
+ 'JsonValidator',
19
+ 'YamlValidator',
20
+ 'PhpValidator',
21
+ 'GoValidator',
22
+ 'JS_TS_Validator',
23
+ 'ValidatorsCatalog'
24
+ ]
Binary file
Binary file
@@ -0,0 +1,73 @@
1
+ import os
2
+ import ctypes
3
+ import platform
4
+ from enum import IntEnum
5
+ from pathlib import Path
6
+
7
+
8
+ class Language(IntEnum):
9
+ CPP = 0
10
+ # _DEPRECATED_JAVASCRIPT = 1
11
+ # _DEPRECATED_TYPESCRIPT = 2
12
+ PHP = 3
13
+ GO = 4
14
+ # _DEPRECATED_TSX = 5
15
+
16
+
17
+ def validate_syntax(source_code: str, language: Language, filename: str = "<code>") -> tuple[bool, str]:
18
+ # filename is used for display in error messages
19
+
20
+ lang_id = int(language)
21
+ debug_dump = False
22
+ c_result = _lib.validate_code(
23
+ source_code.encode("utf-8"),
24
+ filename.encode("utf-8"),
25
+ lang_id,
26
+ debug_dump,
27
+ )
28
+ try:
29
+ if not c_result.has_error:
30
+ return True, ""
31
+ return False, c_result.formatted_report.decode("utf-8")
32
+ finally:
33
+ _lib.free_validation_result(c_result)
34
+
35
+
36
+ # --- Private ctypes Implementation ---
37
+
38
+ class _Validation_Result(ctypes.Structure):
39
+ _fields_ = [
40
+ ("has_error", ctypes.c_bool ),
41
+ ("lineno", ctypes.c_uint32),
42
+ ("column", ctypes.c_uint32),
43
+ ("end_lineno", ctypes.c_uint32),
44
+ ("end_column", ctypes.c_uint32),
45
+ ("message", ctypes.c_char_p),
46
+ ("formatted_report", ctypes.c_char_p),
47
+ ]
48
+
49
+
50
+ CURRENT_OS = platform.system().lower()
51
+
52
+ def _load_library(name: str):
53
+ if CURRENT_OS == "darwin":
54
+ LIB_EXT = ".dylib"
55
+ elif CURRENT_OS == "windows":
56
+ LIB_EXT = ".dll"
57
+ else:
58
+ LIB_EXT = ".so"
59
+
60
+ lib_path = Path(__file__).parent / f"{name}{LIB_EXT}"
61
+ if not lib_path.exists():
62
+ raise ImportError(f"Cannot find compiled library at {lib_path}. "
63
+ "Please build it first.")
64
+
65
+ return ctypes.CDLL(os.fsdecode(lib_path))
66
+
67
+ _lib = _load_library("_validator_tree")
68
+
69
+ _lib.validate_code.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint8, ctypes.c_bool]
70
+ _lib.validate_code.restype = _Validation_Result
71
+
72
+ _lib.free_validation_result.argtypes = [_Validation_Result]
73
+ _lib.free_validation_result.restype = None
@@ -0,0 +1,33 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ class BaseValidator(ABC):
4
+ """
5
+ Abstract base class for content validators.
6
+ Each validator checks specific file format validity.
7
+ """
8
+
9
+ @abstractmethod
10
+ def validate(self, new_text: str, filename: str) -> tuple[bool, str]:
11
+ """
12
+ Validate the content for correctness.
13
+
14
+ Args:
15
+ new_text: The content to validate
16
+ filename: The target filename (for context)
17
+
18
+ Returns:
19
+ tuple: (is_valid: bool, error_message: str)
20
+ - is_valid: True if content is valid, False otherwise
21
+ - error_message: Empty string if valid, error description if invalid
22
+ """
23
+ pass
24
+
25
+ @property
26
+ @abstractmethod
27
+ def supported_extensions(self) -> list[str]:
28
+ """Return list of file extensions this validator supports"""
29
+ pass
30
+
31
+ def get_validation_name(self) -> str:
32
+ """Return human-readable name of this validator"""
33
+ return self.__class__.__name__
@@ -0,0 +1,25 @@
1
+ from .base_validator import BaseValidator
2
+
3
+ try:
4
+ from ._validator_tree import validate_syntax, Language
5
+ LIBRARY_MISSING_ERROR = ""
6
+ except (ImportError, OSError) as e:
7
+ LIBRARY_MISSING_ERROR = (
8
+ "The GO validator component could not be loaded.\n"
9
+ "Please ensure the library has been built by running 'python nob.py build'.\n"
10
+ f"Details: {e}"
11
+ )
12
+
13
+ class GoValidator(BaseValidator):
14
+ @property
15
+ def supported_extensions(self) -> list[str]:
16
+ return [".go"]
17
+
18
+ def validate(self, new_text: str, filename: str) -> tuple[bool, str]:
19
+ if LIBRARY_MISSING_ERROR:
20
+ return False, LIBRARY_MISSING_ERROR
21
+
22
+ try:
23
+ return validate_syntax(new_text, Language.GO, filename)
24
+ except Exception as e:
25
+ return False, f"An unexpected error occurred while validating {filename}: {str(e)}"
@@ -0,0 +1,50 @@
1
+ import ctypes
2
+ from pathlib import Path
3
+ from .base_validator import BaseValidator
4
+
5
+ try:
6
+ from ._validator_tree import _load_library
7
+
8
+ _lib = _load_library("_validator_js_ts")
9
+
10
+ _lib.validate.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
11
+ _lib.validate.restype = ctypes.c_void_p
12
+
13
+ _lib.free_result.argtypes = [ctypes.c_void_p]
14
+ _lib.free_result.restype = None
15
+
16
+ LIBRARY_MISSING_ERROR = ""
17
+ except (ImportError, OSError) as e:
18
+ LIBRARY_MISSING_ERROR = (
19
+ "The JavaScript/TypeScript validator could not be loaded. "
20
+ "Please ensure the library has been built.\n"
21
+ f"Details: {e}"
22
+ )
23
+
24
+
25
+ class JS_TS_Validator(BaseValidator):
26
+ @property
27
+ def supported_extensions(self) -> list[str]:
28
+ return ['.js', '.jsx', '.mjs', '.cjs', '.ts', '.tsx', '.mts', '.cts']
29
+
30
+ def validate(self, new_text: str, filename: str) -> tuple[bool, str]:
31
+ if LIBRARY_MISSING_ERROR:
32
+ return False, LIBRARY_MISSING_ERROR
33
+
34
+ try:
35
+ error_address = _lib.validate(
36
+ new_text.encode("utf-8"),
37
+ filename.encode("utf-8")
38
+ )
39
+
40
+ try:
41
+ if not error_address:
42
+ return True, ""
43
+
44
+ error_string_ptr = ctypes.cast(error_address, ctypes.c_char_p)
45
+ error_message = error_string_ptr.value.decode("utf-8")
46
+ return False, error_message
47
+ finally:
48
+ _lib.free_result(error_address)
49
+ except Exception as e:
50
+ return False, f"An unexpected error occurred while validating {filename}: {str(e)}"
@@ -0,0 +1,32 @@
1
+ import json
2
+ from .base_validator import BaseValidator
3
+
4
+ class JsonValidator(BaseValidator):
5
+ """Validator for JSON file content"""
6
+
7
+ def validate(self, new_text: str, filename: str) -> tuple[bool, str]:
8
+ """
9
+ Validate JSON syntax and structure.
10
+
11
+ Returns:
12
+ tuple: (is_valid, error_message)
13
+ """
14
+ try:
15
+ json.loads(new_text)
16
+ return True, ""
17
+ except json.JSONDecodeError as e:
18
+ error_msg = self._format_json_error(e, filename)
19
+ return False, error_msg
20
+ except Exception as e:
21
+ return False, f"Unexpected error validating JSON in {filename}: {str(e)}"
22
+
23
+ @property
24
+ def supported_extensions(self) -> list[str]:
25
+ return ['.json', '.jsonl', '.geojson']
26
+
27
+ def _format_json_error(self, error: json.JSONDecodeError, filename: str) -> str:
28
+ """Format JSON parsing error for user display"""
29
+ return (f"JSON validation failed for {filename}:\n"
30
+ f"Error: {error.msg}\n"
31
+ f"Line: {error.lineno}, Column: {error.colno}\n"
32
+ f"Position: {error.pos}")
@@ -0,0 +1,25 @@
1
+ from .base_validator import BaseValidator
2
+
3
+ try:
4
+ from ._validator_tree import validate_syntax, Language
5
+ LIBRARY_MISSING_ERROR = ""
6
+ except (ImportError, OSError) as e:
7
+ LIBRARY_MISSING_ERROR = (
8
+ "The PHP validator component could not be loaded.\n"
9
+ "Please ensure the library has been built by running 'python nob.py build'.\n"
10
+ f"Details: {e}"
11
+ )
12
+
13
+ class PhpValidator(BaseValidator):
14
+ @property
15
+ def supported_extensions(self) -> list[str]:
16
+ return [".php", ".phtml", ".phps", ".php3", ".php4", ".php5", ".php7", ".php8", ".pht"]
17
+
18
+ def validate(self, new_text: str, filename: str) -> tuple[bool, str]:
19
+ if LIBRARY_MISSING_ERROR:
20
+ return False, LIBRARY_MISSING_ERROR
21
+
22
+ try:
23
+ return validate_syntax(new_text, Language.PHP, filename)
24
+ except Exception as e:
25
+ return False, f"An unexpected error occurred while validating {filename}: {str(e)}"
@@ -0,0 +1,190 @@
1
+ import ast
2
+ import re
3
+ import sys
4
+ from typing import List, Tuple, Set
5
+ from .base_validator import BaseValidator
6
+
7
+ class PythonValidator(BaseValidator):
8
+ """Validator for Python code content"""
9
+
10
+ # Potentially dangerous patterns to check for
11
+ DANGEROUS_PATTERNS = [
12
+ (r'\beval\s*\(', 'Use of eval() can be dangerous'),
13
+ (r'\bexec\s*\(', 'Use of exec() can be dangerous'),
14
+ (r'__import__\s*\(', 'Dynamic imports with __import__ should be used carefully'),
15
+ (r'\bcompile\s*\(', 'Use of compile() should be reviewed'),
16
+ (r'subprocess\.call\s*\(.*shell\s*=\s*True', 'subprocess with shell=True can be dangerous'),
17
+ (r'os\.system\s*\(', 'os.system() can be dangerous, consider subprocess instead'),
18
+ (r'input\s*\(.*\beval\b', 'eval() in input() is dangerous'),
19
+ ]
20
+
21
+ def validate(self, new_text: str, filename: str) -> Tuple[bool, str]:
22
+ """
23
+ Validate Python code syntax and basic quality checks.
24
+
25
+ Returns:
26
+ tuple: (is_valid, error_message)
27
+ """
28
+ try:
29
+ # Handle empty or whitespace-only content
30
+ if not new_text or new_text.strip() == "":
31
+ return True, ""
32
+
33
+ # Check if file contains only comments and whitespace
34
+ if self._is_comments_only(new_text):
35
+ return True, ""
36
+
37
+ # 1. Syntax validation using AST
38
+ syntax_valid, syntax_error = self._validate_syntax(new_text, filename)
39
+ if not syntax_valid:
40
+ return False, syntax_error
41
+
42
+ # 2. Import validation
43
+ import_valid, import_error = self._validate_imports(new_text, filename)
44
+ if not import_valid:
45
+ return False, import_error
46
+
47
+ # 3. Basic code quality checks
48
+ quality_valid, quality_error = self._validate_code_quality(new_text, filename)
49
+ if not quality_valid:
50
+ return False, quality_error
51
+
52
+ # 4. Security checks (warnings, not failures)
53
+ security_warnings = self._check_security_patterns(new_text, filename)
54
+ if security_warnings:
55
+ # For now, just return warnings as part of error message
56
+ # In production, you might want to handle warnings differently
57
+ return False, f"Security warnings in {filename}:\n" + "\n".join(security_warnings)
58
+
59
+ return True, ""
60
+
61
+ except Exception as e:
62
+ return False, f"Unexpected error validating Python code in {filename}: {str(e)}"
63
+
64
+ @property
65
+ def supported_extensions(self) -> List[str]:
66
+ return ['.py', '.pyw']
67
+
68
+ def _validate_syntax(self, code: str, filename: str) -> Tuple[bool, str]:
69
+ """Validate Python syntax using AST parsing"""
70
+ try:
71
+ ast.parse(code, filename=filename)
72
+ return True, ""
73
+ except SyntaxError as e:
74
+ # Check if this is a tabs/spaces mixing error
75
+ if "inconsistent use of tabs and spaces" in str(e):
76
+ return False, f"Mixed tabs and spaces for indentation in {filename}"
77
+ error_msg = self._format_syntax_error(e, filename)
78
+ return False, error_msg
79
+ except Exception as e:
80
+ return False, f"Syntax validation failed for {filename}: {str(e)}"
81
+
82
+ def _validate_imports(self, code: str, filename: str) -> Tuple[bool, str]:
83
+ """Validate import statements"""
84
+ try:
85
+ tree = ast.parse(code, filename=filename)
86
+
87
+ # Check for problematic import patterns
88
+ for node in ast.walk(tree):
89
+ if isinstance(node, ast.Import):
90
+ for alias in node.names:
91
+ if alias.name.startswith('.'):
92
+ return False, f"Invalid import in {filename} line {node.lineno}: relative import '{alias.name}' not allowed in import statement"
93
+
94
+ elif isinstance(node, ast.ImportFrom):
95
+ # Check for excessive relative imports (4 or more dots)
96
+ if node.level and node.level >= 4:
97
+ return False, f"Excessive relative import in {filename} line {node.lineno}: too many parent directory references"
98
+
99
+ # Check for star imports (warning level)
100
+ for alias in node.names:
101
+ if alias.name == '*':
102
+ # This could be a warning instead of error
103
+ pass
104
+
105
+ return True, ""
106
+
107
+ except Exception as e:
108
+ return False, f"Import validation failed for {filename}: {str(e)}"
109
+
110
+ def _validate_code_quality(self, code: str, filename: str) -> Tuple[bool, str]:
111
+ """Basic code quality checks"""
112
+ lines = code.split('\n')
113
+
114
+ # Check for mixed tabs and spaces
115
+ has_tabs = any('\t' in line for line in lines)
116
+ has_spaces_indent = any(line.startswith(' ') for line in lines if line.strip())
117
+
118
+ if has_tabs and has_spaces_indent:
119
+ return False, f"Mixed tabs and spaces for indentation in {filename}"
120
+
121
+ # Check for extremely long lines (configurable threshold)
122
+ max_line_length = 1000
123
+ for i, line in enumerate(lines, 1):
124
+ if len(line) > max_line_length:
125
+ return False, f"Line too long in {filename} line {i}: {len(line)} characters (max {max_line_length})"
126
+
127
+ # Check for basic structure issues
128
+ try:
129
+ tree = ast.parse(code, filename=filename)
130
+
131
+ # Check for functions/classes with no content (only pass/docstring)
132
+ for node in ast.walk(tree):
133
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
134
+ if len(node.body) == 1:
135
+ first_stmt = node.body[0]
136
+ if isinstance(first_stmt, ast.Pass):
137
+ # This is just a warning, not an error
138
+ pass
139
+ elif isinstance(first_stmt, ast.Expr) and isinstance(first_stmt.value, ast.Constant):
140
+ # Just a docstring, might want to warn
141
+ pass
142
+
143
+ return True, ""
144
+
145
+ except Exception as e:
146
+ return False, f"Code quality validation failed for {filename}: {str(e)}"
147
+
148
+ def _check_security_patterns(self, code: str, filename: str) -> List[str]:
149
+ """Check for potentially dangerous code patterns"""
150
+ warnings = []
151
+
152
+ for pattern, message in self.DANGEROUS_PATTERNS:
153
+ matches = re.finditer(pattern, code, re.IGNORECASE | re.MULTILINE)
154
+ for match in matches:
155
+ # Find line number
156
+ line_num = code[:match.start()].count('\n') + 1
157
+ warnings.append(f"Line {line_num}: {message}")
158
+
159
+ return warnings
160
+
161
+ def _is_comments_only(self, code: str) -> bool:
162
+ """Check if code contains only comments and whitespace"""
163
+ lines = code.split('\n')
164
+ for line in lines:
165
+ stripped = line.strip()
166
+ if stripped and not stripped.startswith('#'):
167
+ return False
168
+ return True
169
+
170
+ def _format_syntax_error(self, error: SyntaxError, filename: str) -> str:
171
+ """Format syntax error for user display"""
172
+ error_details = [f"Python syntax error in {filename}:"]
173
+
174
+ if error.msg:
175
+ error_details.append(f"Error: {error.msg}")
176
+
177
+ if error.lineno:
178
+ error_details.append(f"Line: {error.lineno}")
179
+
180
+ if error.offset:
181
+ error_details.append(f"Column: {error.offset}")
182
+
183
+ if error.text:
184
+ error_details.append(f"Code: {error.text.strip()}")
185
+ if error.offset:
186
+ # Add pointer to error location
187
+ pointer = ' ' * (error.offset - 1) + '^'
188
+ error_details.append(f" {pointer}")
189
+
190
+ return "\n".join(error_details)
@@ -0,0 +1,78 @@
1
+ import os
2
+ from .base_validator import BaseValidator
3
+ from .json_validator import JsonValidator
4
+ from .yaml_validator import YamlValidator
5
+ from .python_validator import PythonValidator
6
+ from .php_validator import PhpValidator
7
+ from .go_validator import GoValidator
8
+ from .js_ts_validator import JS_TS_Validator
9
+
10
+ class ValidatorsCatalog:
11
+ """
12
+ Central registry for all file content validators.
13
+ Uses simple includes instead of complex registration methods.
14
+ """
15
+
16
+ def __init__(self):
17
+ # Simple includes - just instantiate the validators we want
18
+ self._validators = [
19
+ JsonValidator(),
20
+ YamlValidator(),
21
+ PythonValidator(),
22
+ PhpValidator(),
23
+ GoValidator(),
24
+ JS_TS_Validator(),
25
+ ]
26
+
27
+ # Build extension to validator mapping for fast lookup
28
+ self._extension_map = {}
29
+ for validator in self._validators:
30
+ for ext in validator.supported_extensions:
31
+ self._extension_map[ext.lower()] = validator
32
+
33
+ def validate_content(self, new_text: str, filename: str) -> tuple[bool, str]:
34
+ """
35
+ Validate content for a specific file.
36
+
37
+ Args:
38
+ new_text: The new content to validate
39
+ filename: The target filename (used to determine validator)
40
+
41
+ Returns:
42
+ tuple: (is_valid: bool, error_message: str)
43
+ """
44
+ validator = self.get_validator_for_file(filename)
45
+ if validator is None:
46
+ # No validator found for this file type - consider it valid
47
+ return True, ""
48
+
49
+ return validator.validate(new_text, filename)
50
+
51
+ def get_validator_for_file(self, filename: str) -> BaseValidator:
52
+ """Get appropriate validator based on file extension"""
53
+ if not filename:
54
+ return None
55
+
56
+ # Extract file extension
57
+ _, ext = os.path.splitext(filename)
58
+ ext = ext.lower()
59
+
60
+ return self._extension_map.get(ext)
61
+
62
+ def get_supported_extensions(self) -> list[str]:
63
+ """Get list of all supported file extensions"""
64
+ return list(self._extension_map.keys())
65
+
66
+ def get_validator(self, filename: str) -> BaseValidator:
67
+ """Get appropriate validator based on file extension (alias for get_validator_for_file)"""
68
+ return self.get_validator_for_file(filename)
69
+
70
+ def get_validators_info(self) -> list[dict]:
71
+ """Get information about all registered validators"""
72
+ info = []
73
+ for validator in self._validators:
74
+ info.append({
75
+ 'name': validator.get_validation_name(),
76
+ 'extensions': validator.supported_extensions
77
+ })
78
+ return info
@@ -0,0 +1,85 @@
1
+ import yaml
2
+ from .base_validator import BaseValidator
3
+
4
+ class YamlValidator(BaseValidator):
5
+ """Validator for YAML file content"""
6
+
7
+ def validate(self, new_text: str, filename: str) -> tuple[bool, str]:
8
+ """
9
+ Validate YAML syntax and structure.
10
+
11
+ Returns:
12
+ tuple: (is_valid, error_message)
13
+ """
14
+ try:
15
+ # Handle empty or whitespace-only content
16
+ if not new_text or new_text.strip() == "":
17
+ return True, ""
18
+
19
+ # Check for duplicate keys using a custom loader
20
+ self._check_duplicate_keys(new_text)
21
+
22
+ # Load YAML with safe loader - handle multi-document YAML
23
+ docs = list(yaml.safe_load_all(new_text))
24
+ return True, ""
25
+ except yaml.YAMLError as e:
26
+ error_msg = self._format_yaml_error(e, filename)
27
+ return False, error_msg
28
+ except Exception as e:
29
+ return False, f"Unexpected error validating YAML in {filename}: {str(e)}"
30
+
31
+ @property
32
+ def supported_extensions(self) -> list[str]:
33
+ return ['.yaml', '.yml']
34
+
35
+ def _check_duplicate_keys(self, yaml_content: str):
36
+ """Check for duplicate keys in YAML content"""
37
+ class DuplicateKeyLoader(yaml.SafeLoader):
38
+ def construct_mapping(self, node, deep=False):
39
+ mapping = {}
40
+ for key_node, value_node in node.value:
41
+ key = self.construct_object(key_node, deep=deep)
42
+ if key in mapping:
43
+ raise yaml.constructor.ConstructorError(
44
+ None, None,
45
+ f"found duplicate key: {key}",
46
+ key_node.start_mark
47
+ )
48
+ value = self.construct_object(value_node, deep=deep)
49
+ mapping[key] = value
50
+ return mapping
51
+
52
+ try:
53
+ # Load all documents in case of multi-document YAML
54
+ docs = list(yaml.load_all(yaml_content, Loader=DuplicateKeyLoader))
55
+ except yaml.constructor.ConstructorError as e:
56
+ if "duplicate key" in str(e):
57
+ raise yaml.YAMLError(f"duplicate key found: {str(e)}")
58
+
59
+ def _format_yaml_error(self, error: yaml.YAMLError, filename: str) -> str:
60
+ """Format YAML parsing error for user display"""
61
+ error_details = []
62
+ error_details.append(f"yaml validation failed for {filename}:")
63
+
64
+ if hasattr(error, 'problem'):
65
+ problem = error.problem
66
+ # Replace \\t with 'tab' for better readability - handle all possible patterns
67
+ problem = problem.replace("'\\\\t'", "'tab'")
68
+ problem = problem.replace('\\\\t', 'tab')
69
+ problem = problem.replace("'\\t'", "'tab'")
70
+ problem = problem.replace('\\t', 'tab')
71
+ error_details.append(f"problem: {problem}")
72
+
73
+ if hasattr(error, 'problem_mark'):
74
+ mark = error.problem_mark
75
+ error_details.append(f"line: {mark.line + 1}, column: {mark.column + 1}")
76
+
77
+ if hasattr(error, 'context'):
78
+ error_details.append(f"context: {error.context}")
79
+
80
+ # Handle duplicate key errors
81
+ error_str = str(error)
82
+ if "duplicate key" in error_str.lower():
83
+ error_details = [f"yaml validation failed for {filename}:", f"duplicate key detected"]
84
+
85
+ return "\n".join(error_details)
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.1
2
+ Name: fast_validators
3
+ Version: 0.1.0
4
+ Summary: Code validators (manual wheel build)
5
+ Requires-Dist: PyYAML (~=6.0)
@@ -0,0 +1,15 @@
1
+ fast_validators-0.1.0.dist-info/METADATA,sha256=PxLy04HTrokj1OeseiRteVSc_hO6nR4miMPg5NG_4Hk,140
2
+ fast_validators-0.1.0.dist-info/RECORD,,
3
+ fast_validators-0.1.0.dist-info/WHEEL,sha256=_bOreq1gx9SJE5Dzh5pOxe8hEzRe-UVEK4LPtxfwHI0,160
4
+ fast_validators/__init__.py,sha256=NYsyPj5Z127_nvU5oyl6lIIgxzHEfzj2NdMG-ISxDmY,691
5
+ fast_validators/_validator_js_ts.dll,sha256=Ti_YrlqSLAHpQ6usgODti4miePdGrGi388jPL12sT_w,18341888
6
+ fast_validators/_validator_tree.dll,sha256=c44X05uSjdZy5PlfkxQfUHMgOAznGM2jn1oShtenxyY,6605312
7
+ fast_validators/_validator_tree.py,sha256=DTRCMUdnaigXNH8bI9fgo3ir599T0jfA4UEUILP51JA,2087
8
+ fast_validators/base_validator.py,sha256=7F_E5Xio837F2AudbDlW2wZ84amVHop-ytCt6LVZAiA,1078
9
+ fast_validators/go_validator.py,sha256=geAS04Dl9s-21CII7Q-xpE0jpC1ojp0ZwQZru_hMh-w,893
10
+ fast_validators/js_ts_validator.py,sha256=QKpQ_hCwcAQv4Rhdp7A9iuW9vy6aCfS5109-Jih6nEc,1651
11
+ fast_validators/json_validator.py,sha256=PfLMaenjRh25jnK1S7qF5qtQjp4bO1L_HN-Hi_QGsZY,1162
12
+ fast_validators/php_validator.py,sha256=O7bVc4vVYgSMouMiGACZZCw9FtiYPwaSdbFQM41BJl4,969
13
+ fast_validators/python_validator.py,sha256=cbiotwfeLXugHRk4wyaSxUdN_h43UHPyCvZiXzKyrhQ,8439
14
+ fast_validators/validators_catalog.py,sha256=lYWTWGUgur3-hLGQoQ2yg7FCTW2Vls4HDm5Nr6GLTxo,2772
15
+ fast_validators/yaml_validator.py,sha256=KyRCIYHyQtTeYmvSJoTtchDs_L-DveQ5zy5T_RJ8ang,3519
@@ -0,0 +1,6 @@
1
+ Wheel-Version: 1.0
2
+ Generator: ship.py (manual)
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_amd64
5
+ Tag: py3-none-mingw_x86_64_clang
6
+ Tag: py3-none-mingw_x86_64