Skip to content

Commit

Permalink
Merge aa81b56 into da401ce
Browse files Browse the repository at this point in the history
  • Loading branch information
escaped committed Nov 24, 2019
2 parents da401ce + aa81b56 commit 89c3972
Show file tree
Hide file tree
Showing 18 changed files with 522 additions and 2,535 deletions.
33 changes: 33 additions & 0 deletions .pre-commit-config.yaml
@@ -0,0 +1,33 @@
---
repos:
- repo: local
hooks:
- id: black
name: black
language: system
entry: poetry run black
types: [python]

- repo: local
hooks:
- id: isort
name: isort
language: system
entry: poetry run isort
types: [python]

- repo: local
hooks:
- id: mypy
name: mypy
language: system
entry: poetry run mypy
types: [python]

- repo: local
hooks:
- id: flake8
name: flake8
language: system
entry: poetry run flake8
types: [python]
7 changes: 5 additions & 2 deletions .travis.yml
Expand Up @@ -5,17 +5,20 @@ language: python
python:
- 3.6
- 3.7
- 3.8
node_js: '8'

install:
- sudo apt-get update -qq
- sudo apt-get install -qq libimage-exiftool-perl
- pip install -U tox-travis
- pip install python-coveralls
- npm install
- pip install poetry
- poetry install
- poetry run pre-commit install

script:
- node_modules/.bin/commitlint-travis
- poetry run pre-commit run -a
- tox -r

after_success:
Expand Down
11 changes: 4 additions & 7 deletions README.rst
Expand Up @@ -146,20 +146,17 @@ Development
This project is using `poetry <https://poetry.eustace.io/>`_ to manage all dev dependencies.
Clone this repository and run ::

poetry develop
poetry install


to create a virtual enviroment with all dependencies.
You can now run the test suite using ::

poetry run pytest

To register the pre-commit hook, please run ::

This repository follows the `angular commit conventions <https://github.com/marionebl/commitlint/tree/master/@commitlint/config-angular>`_.
You can register a pre-commit hook to validate your commit messages by using
`husky <https://github.com/typicode/husky>`_. The configurations are already in place if
you have nodejs installed. Just run ::
poetry run pre-commit install

npm install

and the pre-commit hook will be registered.
This repository follows the `conventional commits <https://www.conventionalcommits.org/en/v1.0.0/>`_ convention.
1 change: 0 additions & 1 deletion commitlint.config.js

This file was deleted.

61 changes: 26 additions & 35 deletions exiffield/fields.py
Expand Up @@ -38,9 +38,8 @@ def get_exif(file_: FieldFile) -> str:
else:
# pass physical file to exiftool
file_path = file_.path
return subprocess.check_output(
[exiftool_path, '-j', '-l', file_path],
)
encoded_json = subprocess.check_output([exiftool_path, '-j', '-l', file_path],)
return encoded_json.decode('utf8')


class ExifField(JSONField):
Expand Down Expand Up @@ -72,8 +71,8 @@ def _check_for_exiftool(self) -> Generator[checks.CheckMessage, None, None]:
"""
if not shutil.which('exiftool'):
yield checks.Error(
"`exiftool` not found.",
hint="Please install `exiftool.`",
'`exiftool` not found.',
hint='Please install `exiftool.`',
obj=self,
id='exiffield.E001',
)
Expand All @@ -84,8 +83,8 @@ def _check_for_source(self) -> Generator[checks.CheckMessage, None, None]:
"""
if not self.source:
yield checks.Error(
f"`self.source` not set on {self.name}.",
hint="Set `self.source` to an existing FileField.",
f'`self.source` not set on {self.name}.',
hint='Set `self.source` to an existing FileField.',
obj=self,
id='exiffield.E002',
)
Expand All @@ -96,15 +95,15 @@ def _check_for_source(self) -> Generator[checks.CheckMessage, None, None]:
field = self.model._meta.get_field(self.source)
except exceptions.FieldDoesNotExist:
yield checks.Error(
f"`{self.source}` not found on {self.model}.",
hint="Check spelling or add field to model.",
f'`{self.source}` not found on {self.model}.',
hint='Check spelling or add field to model.',
obj=self,
id='exiffield.E003',
)
return
if not isinstance(field, models.FileField):
yield checks.Error(
f"`{self.source}` on {self.model} must be a FileField.",
f'`{self.source}` on {self.model} must be a FileField.',
obj=self,
id='exiffield.E004',
)
Expand All @@ -116,8 +115,8 @@ def _check_fields(self) -> Generator[checks.CheckMessage, None, None]:
"""
if not isinstance(self.denormalized_fields, dict):
yield checks.Error(
f"`denormalized_fields` on {self.model} should be a dictionary.",
hint="Check the kwargs of `ExifField`",
f'`denormalized_fields` on {self.model} should be a dictionary.',
hint='Check the kwargs of `ExifField`',
obj=self,
id='exiffield.E005',
)
Expand All @@ -128,35 +127,30 @@ def _check_fields(self) -> Generator[checks.CheckMessage, None, None]:
field = self.model._meta.get_field(fieldname)
except exceptions.FieldDoesNotExist:
yield checks.Error(
f"`{fieldname}` not found on {self.model}.",
hint="Check spelling or add field to model.",
f'`{fieldname}` not found on {self.model}.',
hint='Check spelling or add field to model.',
obj=self,
id='exiffield.E006',
)
continue

if field.editable:
yield checks.Error(
f"`{fieldname}` on {self.model} should not be editable.",
hint=f"Set `editable=False` on {fieldname}.",
f'`{fieldname}` on {self.model} should not be editable.',
hint=f'Set `editable=False` on {fieldname}.',
obj=self,
id='exiffield.E007',
)

if not callable(func):
yield checks.Error(
f"`Value for {fieldname}` on {self.model} should not be a callable.",
hint=f"Check your values for `denormalized_fields`",
f'`Value for {fieldname}` on {self.model} should not be a callable.',
hint=f'Check your values for `denormalized_fields`',
obj=self,
id='exiffield.E008',
)

def contribute_to_class(
self,
cls: models.Model,
name: str,
**kwargs,
) -> None:
def contribute_to_class(self, cls: models.Model, name: str, **kwargs,) -> None:
"""
Register signals for retrieving and writing of exif data.
"""
Expand All @@ -171,11 +165,7 @@ def contribute_to_class(
pre_save.connect(self.denormalize_exif, sender=cls)
post_init.connect(self.denormalize_exif, sender=cls)

def denormalize_exif(
self,
instance: models.Model,
**kwargs,
) -> None:
def denormalize_exif(self, instance: models.Model, **kwargs,) -> None:
"""
Update denormalized fields with new exif values.
"""
Expand All @@ -191,7 +181,8 @@ def denormalize_exif(
logger.warning(
'Could not execute `%s` to extract value for `%s.%s`',
extract_from_exif.__name__,
instance.__class__.__name__, model_field,
instance.__class__.__name__,
model_field,
exc_info=True,
)
if not value:
Expand All @@ -200,11 +191,11 @@ def denormalize_exif(
setattr(instance, model_field, value)

def update_exif(
self,
instance: models.Model,
force: bool = False,
commit: bool = False,
**kwargs,
self,
instance: models.Model,
force: bool = False,
commit: bool = False,
**kwargs,
) -> None:
"""
Load exif data from file.
Expand Down
9 changes: 4 additions & 5 deletions exiffield/getters.py
Expand Up @@ -25,9 +25,11 @@ def exifgetter(field: str) -> Callable[[ExifType], Any]:
"""
Return the unmodified value.
"""

def inner(exif: ExifType) -> Any:
return exif[field]['val']
inner.__name__ = f'exifgetter(\'{field}\')'

inner.__name__ = f'exifgetter("{field}")'
return inner


Expand All @@ -49,10 +51,7 @@ def get_datetaken(exif: ExifType) -> Optional[datetime.datetime]:
continue

try:
return datetime.datetime.strptime(
datetime_str,
'%Y:%m:%d %H:%M:%S',
)
return datetime.datetime.strptime(datetime_str, '%Y:%m:%d %H:%M:%S',)
except ValueError as e:
raise ExifError(f'Could not parse {datetime_str}') from e
raise ExifError(f'Could not find date')
Expand Down

0 comments on commit 89c3972

Please sign in to comment.