Skip to content

Commit

Permalink
Removed unnecessary dependencies (#20)
Browse files Browse the repository at this point in the history
1. Replaced `pytz.utc` with `timezone.utc` as it is more standard and doesn't require `pytz` install
2. Removed unnecessary dependencies
3. Changed github tested versions
  • Loading branch information
M1ha-Shvn committed Jan 1, 2024
1 parent 6160188 commit 1c533e6
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 77 deletions.
20 changes: 15 additions & 5 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,24 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
django-version: ["2.2", "3.0", "3.1", "3.2", "4.0"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
django-version: ["2.2", "3.0", "3.1", "3.2", "4.0", "4.1", "4.2", "5.0"]
exclude:
# Django 4.0+ doesn't support python 3.6, 3.7
- python-version: "3.6"
django-version: "4.0"
# Django 4.0+ doesn't support python 3.7
- python-version: "3.7"
django-version: "4.0"
- python-version: "3.7"
django-version: "4.1"
- python-version: "3.7"
django-version: "4.2"
- python-version: "3.7"
django-version: "5.0"

# Django 5.0+ doesn't support python 3.8, 3.9
- python-version: "3.8"
django-version: "5.0"
- python-version: "3.9"
django-version: "5.0"

steps:
- uses: actions/checkout@v2
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
Extended form fields to validate REST-request data via django.forms.

## Requirements
* Python 3.6+
* Python 3.7+
Other versions may also work but not tested automatically
* Django 2.2+
Other versions may also work but not tested automatically
* jsonschema
* pytz
* typing; python_version < '3.5'
* typing
* jsonschema
Optional. Required for validating json schema in `JsonField` and its child classes
* pytz
Optional. Required for `TimezoneField`

## Installation
Install via pip:
Expand Down
6 changes: 3 additions & 3 deletions requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
django>=1.7
jsonschema
psycopg2-binary
pytz
typing; python_version < '3.5'

jsonschema
pytz; python_version < '3.3'

# Linter
flake8
3 changes: 0 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
django>=1.7
jsonschema
psycopg2-binary
pytz
typing; python_version < '3.5'
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

setup(
name='django-rest-form-fields',
version='1.3.4',
version='1.3.5',
packages=['django_rest_form_fields'],
package_dir={'': 'src'},
url='https://github.com/M1hacka/django-rest-form-fields',
Expand Down
9 changes: 4 additions & 5 deletions src/django_rest_form_fields/compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
This file contains functions for different python and django version compatibility
"""
import datetime

import re
import sys
from datetime import timezone

import pytz
from django.utils.timezone import make_aware

if hasattr(re, 'Pattern'):
Expand All @@ -20,12 +19,12 @@

def to_timestamp(dt): # type: (datetime.datetime) -> float
if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) is None:
dt = make_aware(dt, pytz.utc)
dt = make_aware(dt, timezone.utc)
else:
dt = dt.astimezone(pytz.utc)
dt = dt.astimezone(timezone.utc)

# dt.timestamp() does not work before python 3.3
if hasattr(dt, 'timestamp'):
return dt.timestamp()
else:
return (dt - datetime.datetime(1970, 1, 1, 0, 0, 0, tzinfo=pytz.utc)).total_seconds()
return (dt - datetime.datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc)).total_seconds()
63 changes: 35 additions & 28 deletions src/django_rest_form_fields/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@
This file contains a number of custom fields to validate data with django forms
"""

import datetime
import json
from datetime import timezone, datetime, date
from typing import Any, Optional, Union

import jsonschema
import os
import pytz
import re
from django import forms
from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
from django.utils import timezone
from django.utils.timezone import make_aware
from django.utils.timezone import make_aware, now

from .compatibility import to_timestamp, PatternType, string_types
from .exceptions import FileSizeError, FileTypeError
Expand Down Expand Up @@ -190,7 +187,7 @@ def __init__(self, *args, **kwargs):

class TimestampField(RestFloatField):
"""
Form field, containing timestamp integer. Converts given value to datetime.datetime object
Form field, containing timestamp integer. Converts given value to datetime object
"""

def __init__(self, *args, **kwargs):
Expand All @@ -207,43 +204,43 @@ def __init__(self, *args, **kwargs):

# Converts initial to timestamp, if it is given as datetime
if 'initial' in kwargs:
assert isinstance(kwargs['initial'], (datetime.datetime, int, float)), \
"initial must be int, float or datetime.datetime instance"
assert isinstance(kwargs['initial'], (datetime, int, float)), \
"initial must be int, float or datetime instance"
dt = kwargs['initial']
if isinstance(dt, datetime.datetime):
if isinstance(dt, datetime):
kwargs['initial'] = to_timestamp(dt)

super(TimestampField, self).__init__(*args, min_value=0, max_value=2147483647, **kwargs)

def clean(self, value): # type: (Any) -> Optional[datetime.datetime]
def clean(self, value): # type: (Any) -> Optional[datetime]
value = super(TimestampField, self).clean(value)
if value == 0:
# Fix python 3.6 issue with Invalid argument value=0
return datetime.datetime(1970, 1, 1, tzinfo=pytz.utc)
return datetime(1970, 1, 1, tzinfo=timezone.utc)
elif value is not None:
dt = datetime.datetime.utcfromtimestamp(value)
return make_aware(dt, pytz.utc)
dt = datetime.utcfromtimestamp(value)
return make_aware(dt, timezone.utc)
else:
return value

def validate(self, value): # type: (Optional[int]) -> None
super(TimestampField, self).validate(value)
if value is not None:
if not self._in_future and value > to_timestamp(timezone.now()):
if not self._in_future and value > to_timestamp(now()):
raise ValidationError("You can't search time in future")


class DateTimeField(RestCharField):
"""
Parses given string as datetime by given mask with datetime.datetime.strptime() method
Parses given string as datetime by given mask with datetime.strptime() method
"""
base_type = datetime.datetime
base_type = datetime

def __init__(self, *args, **kwargs):
"""
Initializes field
:param args: Positional arguments
:param mask: Mask to parse datetime string with datetime.datetime.strptime() method
:param mask: Mask to parse datetime string with datetime.strptime() method
:param kwargs: Named arguments
"""
mask = kwargs.pop("mask", "%Y-%m-%dT%H:%M:%S")
Expand All @@ -253,60 +250,60 @@ def __init__(self, *args, **kwargs):

self.mask = mask

def clean(self, value): # type: (Any) -> datetime.datetime
def clean(self, value): # type: (Any) -> datetime
value = super(DateTimeField, self).clean(value)
if value is not None and not isinstance(value, self.base_type):
try:
dt = datetime.datetime.strptime(value, self.mask)
dt = datetime.strptime(value, self.mask)
except (ValueError, TypeError):
raise ValidationError("Invalid value format (%s)" % self.mask)

return make_aware(dt, pytz.utc)
return make_aware(dt, timezone.utc)
else:
return value


class DateField(DateTimeField):
"""
Parses month with datetime.datetime.strptime() method. Default format is %Y-%m.
Parses month with datetime.strptime() method. Default format is %Y-%m.
Returns datetime.date with first day of month.
"""
base_type = datetime.date
base_type = date

def __init__(self, *args, **kwargs):
"""
Initializes field
:param args: Positional arguments
:param mask: Mask to parse month string with datetime.datetime.strptime() method
:param mask: Mask to parse month string with datetime.strptime() method
:param kwargs: Named arguments
"""
mask = kwargs.pop("mask", "%Y-%m-%d")
super(DateField, self).__init__(*args, mask=mask, **kwargs)

def clean(self, value): # type (Any) -> datetime.date
value = super(DateField, self).clean(value)
return value.date() if isinstance(value, datetime.datetime) else value
return value.date() if isinstance(value, datetime) else value


class MonthField(DateTimeField):
"""
Parses month with datetime.datetime.strptime() method. Default format is %Y-%m.
Parses month with datetime.strptime() method. Default format is %Y-%m.
Returns datetime.date with first day of month.
"""

def __init__(self, *args, **kwargs):
"""
Initializes field
:param args: Positional arguments
:param mask: Mask to parse month string with datetime.datetime.strptime() method
:param mask: Mask to parse month string with datetime.strptime() method
:param kwargs: Named arguments
"""
mask = kwargs.pop("mask", "%Y-%m")
super(MonthField, self).__init__(*args, mask=mask, **kwargs)

def clean(self, value): # type (Any) -> datetime.date
def clean(self, value): # type (Any) -> date
value = super(MonthField, self).clean(value)
return value.date() if isinstance(value, datetime.datetime) else value
return value.date() if isinstance(value, datetime) else value


class TimezoneField(RestCharField):
Expand All @@ -316,6 +313,11 @@ class TimezoneField(RestCharField):

def validate(self, value): # type: (Optional[str]) -> None
super(TimezoneField, self).validate(value)
try:
import pytz
except ImportError as ex:
raise ImportError('pytz is required for TimezoneField') from ex

if value and value not in pytz.all_timezones:
raise ValidationError("Invalid timezone '{0}'".format(value))

Expand Down Expand Up @@ -438,6 +440,11 @@ def to_python(self, value): # type: (Any) -> Optional[Union[dict, list]]
def validate(self, value): # type: (Optional[Union[dict, list]]) -> None
super(JsonField, self).validate(value)
if self._json_schema and value is not None:
try:
import jsonschema
except ImportError as ex:
raise ImportError("jsonschema library is not required for this operation") from ex

try:
jsonschema.validate(value, self._json_schema)
except jsonschema.exceptions.ValidationError as ex:
Expand Down
3 changes: 1 addition & 2 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
"tests",
]

DATABASES = {
}
DATABASES = {}

USE_TZ = True
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

0 comments on commit 1c533e6

Please sign in to comment.