91 lines
3.0 KiB
Python
91 lines
3.0 KiB
Python
from pathlib import Path
|
|
from website_generator.utils import PathMatcher
|
|
import typesystem
|
|
|
|
|
|
class PathField(typesystem.String):
|
|
|
|
errors = {
|
|
'type': 'Must be a string or instance of pathlib.Path.',
|
|
'null': 'May not be null.',
|
|
'blank': 'Must not be blank.',
|
|
'max_length': 'Must have no more than {max_length} characters.',
|
|
'min_length': 'Must have at least {min_length} characters.',
|
|
'pattern': 'Must match the pattern /{pattern}/.',
|
|
'format': 'Must be a valid {format}.',
|
|
'not_found': 'Path does not exist.',
|
|
'no_files': 'Path must not point to a file.',
|
|
'no_dirs': 'Path must not point to a directory.',
|
|
'no_symlinks': 'Path must not point to a symbolic link.',
|
|
}
|
|
|
|
def __init__(self,
|
|
*,
|
|
must_exist=True,
|
|
allow_files=True,
|
|
allow_folders=False,
|
|
allow_symlinks=True,
|
|
**kwargs):
|
|
super().__init__(**kwargs)
|
|
self.must_exist = must_exist
|
|
self.allow_files = must_exist and allow_files
|
|
self.allow_folders = must_exist and allow_folders
|
|
self.allow_symlinks = must_exist and allow_symlinks
|
|
|
|
def validate(self, value, *, strict=False):
|
|
if isinstance(value, Path):
|
|
value = str(value)
|
|
value = super().validate(value, strict=strict)
|
|
|
|
if not value:
|
|
return value
|
|
value = Path(value)
|
|
|
|
if not self.allow_symlinks and value.is_symlink():
|
|
self.validation_error("no_symlinks")
|
|
|
|
value = value.expanduser().resolve()
|
|
if self.must_exist and not value.exists():
|
|
self.validation_error("not_found")
|
|
if not self.allow_files and value.is_file():
|
|
self.validation_error("no_files")
|
|
if not self.allow_folders and value.is_dir():
|
|
self.validation_error("no_dirs")
|
|
|
|
return value
|
|
|
|
|
|
class PathMatcherField(typesystem.Union):
|
|
|
|
def __init__(self, *, **kwargs):
|
|
super().__init__([
|
|
typesystem.String(),
|
|
typesystem.Array(
|
|
items=typesystem.String(),
|
|
min_items=1,
|
|
),
|
|
typesystem.Object(
|
|
properties={
|
|
'include': typesystem.Union([
|
|
typesystem.String(),
|
|
typesystem.Array(
|
|
items=typesystem.String(),
|
|
min_items=1,
|
|
),
|
|
]),
|
|
'exclude': typesystem.Union([
|
|
typesystem.String(),
|
|
typesystem.Array(
|
|
items=typesystem.String(),
|
|
min_items=1,
|
|
),
|
|
]),
|
|
},
|
|
min_properties=1,
|
|
required=['include'],
|
|
),
|
|
], **kwargs)
|
|
|
|
def validate(self, *args, **kwargs):
|
|
return PathMatcher(super().validate(*args, **kwargs))
|