Skip to content
This repository has been archived by the owner on Oct 11, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1 from binary-butterfly/cleanup-version-0.3
Browse files Browse the repository at this point in the history
Small cleanups and improvements for version 0.3
  • Loading branch information
binaryDiv authored Aug 5, 2021
2 parents 9f52d91 + 95d3e5d commit e079680
Show file tree
Hide file tree
Showing 65 changed files with 355 additions and 274 deletions.
16 changes: 16 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[paths]
source =
src
*/site-packages

[run]
branch = True
source = wtfjson

[report]
show_missing = True

[html]
directory = reports/coverage_html/
skip_empty = True
show_contexts = True
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ __pycache__/
/venv
/.tox
/.eggs
/.coverage
/build
/dist
/reports
/src/wtfjson.egg-info
26 changes: 26 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.PHONY: all tox open-coverage clean clean-all

# Default target
all: tox


# Test suite
# ----------
tox:
tox

flake8:
tox -e flake8

# Open HTML coverage report in browser
open-coverage:
$(or $(BROWSER),firefox) ./reports/coverage_html/index.html


# Cleanup
# -------
clean:
rm -rf .coverage reports

clean-all: clean
rm -rf .tox .eggs venv
12 changes: 11 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
[pytest]
python_files = *Test.py
addopts =
-ra
--import-mode=importlib
--cov-context=test
--cov-report=

testpaths = tests
python_files = *_test.py *Test.py
python_classes = *Test

# Fail on warnings
filterwarnings = error
6 changes: 3 additions & 3 deletions src/wtfjson/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
Use of this source code is governed by an MIT-style license that can be found in the LICENSE.txt.
"""

from .DictInput import DictInput
from .ListInput import ListInput

from .abstract_input import AbstractInput
from .dict_input import DictInput
from .list_input import ListInput
52 changes: 52 additions & 0 deletions src/wtfjson/abstract_input.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# encoding: utf-8

"""
binary butterfly validator
Copyright (c) 2021, binary butterfly GmbH
Use of this source code is governed by an MIT-style license that can be found in the LICENSE.txt.
"""

from abc import ABC, abstractmethod

from .exceptions import NotValidated, InvalidData


class AbstractInput(ABC):
_errors: dict
_validated: bool = False

def __init__(self):
self._errors = {}
self._validated = False

@abstractmethod # pragma: nocover
def validate(self) -> bool:
raise NotImplementedError()

@property
def has_errors(self) -> bool:
if not self._validated:
raise NotValidated()
return len(self._errors.keys()) > 0

@property
def errors(self) -> dict:
if not self._validated:
raise NotValidated()
return self._errors

def _ensure_validated(self) -> None:
if not self._validated:
raise NotValidated()
if self.has_errors:
raise InvalidData()

@property
@abstractmethod # pragma: nocover
def data(self):
raise NotImplementedError()

@property
@abstractmethod # pragma: nocover
def out(self):
raise NotImplementedError()
41 changes: 9 additions & 32 deletions src/wtfjson/DictInput.py → src/wtfjson/dict_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,23 @@
Use of this source code is governed by an MIT-style license that can be found in the LICENSE.txt.
"""

from abc import ABC
from typing import List, Any, Optional

from .abstract_input import AbstractInput
from .fields import UnboundField
from .validators import Validator
from .exceptions import NotValidated, InvalidData
from .util import unset_value


class DictInput(ABC):
class DictInput(AbstractInput):
_fields: dict
_errors: dict
_validated: bool = False
_validators: List[Validator]

def __init__(self, data: Any):
super().__init__()

# first: init vars
self._fields = {}
self._errors = {}
self._validators = []

# second: init fields
Expand All @@ -49,45 +47,24 @@ def validate(self) -> bool:
return not self.has_errors

def populate_obj(self, obj, exclude: Optional[List[str]] = None):
if not self._validated:
raise NotValidated()
if self.has_errors:
raise InvalidData()
self._ensure_validated()
for field_name, field in self._fields.items():
if exclude is None or field_name not in exclude:
if field.out is not unset_value:
setattr(obj, field.populate_to if field.populate_to else field_name, field.out)

def to_dataclass(self, dataclass):
self._ensure_validated()
if hasattr(dataclass, 'from_dict'):
return dataclass.from_dict(**self.out)
return dataclass(**self.out)

@property
def has_errors(self) -> bool:
if not self._validated:
raise NotValidated()
return len(self._errors.keys()) > 0

@property
def errors(self) -> dict:
if not self._validated:
raise NotValidated()
return self._errors

@property
def data(self):
if not self._validated:
raise NotValidated()
if self.has_errors:
raise InvalidData()
return {field_name: field.data for field_name, field in self._fields.items()} #TODO: get fields back
self._ensure_validated()
return {field_name: field.data for field_name, field in self._fields.items()} # TODO: get fields back

@property
def out(self):
if not self._validated:
raise NotValidated()
if self.has_errors:
raise InvalidData()
self._ensure_validated()
return {field_name: field.out for field_name, field in self._fields.items() if field.out is not unset_value}

2 changes: 1 addition & 1 deletion src/wtfjson/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class NotValidated(Exception):

class InvalidData(Exception):
"""
will be thrown if somebodu tries to access data which is not there
will be thrown if somebody tries to access data which is not there
"""
pass

Expand Down
Empty file.
24 changes: 12 additions & 12 deletions src/wtfjson/fields/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
Use of this source code is governed by an MIT-style license that can be found in the LICENSE.txt.
"""

from .Field import Field
from .UnboundField import UnboundField
from .BooleanField import BooleanField
from .StringField import StringField
from .IntegerField import IntegerField
from .EnumField import EnumField
from .DecimalField import DecimalField
from .ListField import ListField
from .ObjectField import ObjectField
from .DateField import DateField
from .DateTimeField import DateTimeField
from .FloatField import FloatField
from .field import Field
from .unbound_field import UnboundField
from .boolean_field import BooleanField
from .string_field import StringField
from .integer_field import IntegerField
from .enum_field import EnumField
from .decimal_field import DecimalField
from .list_field import ListField
from .object_field import ObjectField
from .date_field import DateField
from .date_time_field import DateTimeField
from .float_field import FloatField
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
"""

from ..fields import Field
from ..validators import Type
from ..validators import IsType


class BooleanField(Field):
pre_validators = [
Type(data_type=bool)
IsType(data_type=bool)
]
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@

from typing import Union
from datetime import date

from ..fields import Field
from ..validators import Type, Date
from ..validators import IsType, Date
from ..util import UnsetValue


class DateField(Field):
pre_validators = [
Type(data_type=str),
IsType(data_type=str),
Date()
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@

from typing import Union
from datetime import datetime

from ..fields import Field
from ..validators import Type, DateTime
from ..validators import IsType, DateTime
from ..util import UnsetValue


class DateTimeField(Field):
def __init__(self, localized: bool = False, accept_utc=False, *args, **kwargs):
super().__init__(*args, **kwargs)
self.pre_validators = [
Type(data_type=str),
IsType(data_type=str),
DateTime(localized=localized, accept_utc=accept_utc)
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@

from typing import Union
from decimal import Decimal

from ..fields import Field
from ..validators import Type, DecimalValidator
from ..validators import IsType, DecimalValidator
from ..util import UnsetValue


class DecimalField(Field):
pre_validators = [
Type(data_type=str),
IsType(data_type=str),
DecimalValidator()
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

from enum import Enum
from typing import Union

from ..fields import Field
from ..validators import Type, EnumValidator
from ..validators import IsType, EnumValidator
from ..util import UnsetValue


Expand All @@ -19,7 +20,7 @@ def __init__(self, enum, *args, **kwargs):
super().__init__(*args, **kwargs)
self.enum = enum
self.default_validators = [
Type(data_type=str),
IsType(data_type=str),
EnumValidator(enum=enum)
]

Expand Down
16 changes: 7 additions & 9 deletions src/wtfjson/fields/Field.py → src/wtfjson/fields/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@
from enum import Enum
from copy import deepcopy
from typing import List, Callable, Optional, Any

from ..abstract_input import AbstractInput
from ..util import unset_value
from ..exceptions import ValidationError, StopValidation, ClearValidation
from .UnboundField import UnboundField

from typing import TYPE_CHECKING
if TYPE_CHECKING:
import Form
from .unbound_field import UnboundField


class FieldState(Enum):
Expand All @@ -28,7 +26,7 @@ class FieldState(Enum):

class Field(ABC):
state: FieldState
_form: 'Form'
_form: AbstractInput
_field_name: str
data_raw: Any # raw input data
data_processed: Any # data after input filters
Expand All @@ -46,7 +44,7 @@ class Field(ABC):
required: bool

def __init__(self,
form: 'Form' = None,
form: AbstractInput = None,
field_name: str = None,
description: Optional[str] = None,
input_filters: Optional[list] = None,
Expand Down Expand Up @@ -100,7 +98,7 @@ def pre_validate(self):
except StopValidation as error:
self.append_error(error.message)
self.validation_stopped = True
except ClearValidation as no_error:
except ClearValidation:
self._errors = {}
self.validation_stopped = False

Expand All @@ -127,7 +125,7 @@ def validate(self) -> bool:
self.append_error(error.message)
except StopValidation as error:
self.append_error(error.message)
except ClearValidation as no_error:
except ClearValidation:
self._errors = {}
self.state = FieldState.validated
return not self.has_errors
Expand Down
Loading

0 comments on commit e079680

Please sign in to comment.