1
0
mirror of https://github.com/enpaul/kodak.git synced 2024-11-14 10:36:55 +00:00

Rename project to dehance

This commit is contained in:
Ethan Paul 2021-05-02 18:12:04 -04:00
parent 3b05fb2053
commit 6a7662ae0f
No known key found for this signature in database
GPG Key ID: D0E2CBF1245E92BF
32 changed files with 784 additions and 668 deletions

115
.gitignore vendored
View File

@ -1,112 +1,27 @@
# Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/ build/
develop-eggs/
dist/ dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/ *.egg-info/
.installed.cfg *.pyc
*.egg
requirements.txt
# PyInstaller *.swp
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage .coverage
.coverage.* *_cache/
.cache .tox/
nosetests.xml .cache/
coverage.xml .venv/
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
docs/imagemonk*.rst
docs/modules.rst
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/ .mypy_cache/
# Pycharm docs/_build/
.idea/ docs/modules.rst
.idea/vcs.xml docs/dehance*.rst
.vscode/
.idea/
# Project specific
*.db *.db
*.db-shm
*.db-wal

View File

@ -1,48 +1,59 @@
--- ---
# All of the pre-commit hooks here actually use the `pytyhon` pre-commit language
# setting. However, for the python language setting, pre-commit will create and manage
# a cached virtual environment for each hook ID and do a bare `pip install <repo>` into
# the venv to setup the hook. This can result in conflicting dependency versions between
# the version installed to the pre-commit venv and the version installed to the Poetry
# venv specified in the lockfile.
#
# The solution is to specify `language: system` for all hooks and then install the
# required dependencies to the Poetry venv. The `system` language skips the isolated
# venv creation and looks for the entrypoint specified by the hook in the global
# environment which, if running in the Poetry venv, will find the entrypoint provided
# by the Poetry-managed dependency.
#
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: local
rev: v3.3.0
hooks: hooks:
- id: end-of-file-fixer - id: end-of-file-fixer
name: end-of-file-fixer
entry: end-of-file-fixer
language: system language: system
types: [text]
- id: fix-encoding-pragma - id: fix-encoding-pragma
name: fix-encoding-pragma
entry: fix-encoding-pragma
args: args:
- "--remove" - "--remove"
language: system language: system
- id: trailing-whitespace types: [python]
- id: trailing-whitespace-fixer
name: trailing-whitespace-fixer
entry: trailing-whitespace-fixer
language: system language: system
types: [text]
- id: check-merge-conflict - id: check-merge-conflict
name: check-merge-conflict
entry: check-merge-conflict
language: system language: system
types: [text]
- repo: https://github.com/psf/black
rev: master
hooks:
- id: black
language: system
- repo: https://github.com/asottile/blacken-docs
rev: v1.8.0
hooks:
- id: blacken-docs
language: system
- repo: https://github.com/asottile/reorder_python_imports
rev: v2.3.6
hooks:
- id: reorder-python-imports - id: reorder-python-imports
name: reorder-python-imports
entry: reorder-python-imports
args: args:
- "--unclassifiable-application-module=imagemonk" - "--unclassifiable-application-module=dehance"
language: system language: system
types: [python]
- id: black
name: black
entry: black
language: system
types: [python]
- id: blacken-docs
name: blacken-docs
entry: blacken-docs
language: system
types: [text]
- id: mdformat
name: mdformat
entry: mdformat
language: system
args:
- "--number"
- "--wrap=90"
types:
- markdown

View File

@ -1,11 +1,12 @@
## Copyright 2020 Ethan Paul ## Copyright 2020 Ethan Paul
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated Permission is hereby granted, free of charge, to any person obtaining a copy of this
documentation files (the "Software"), to deal in the Software without restriction, including without limitation software and associated documentation files (the "Software"), to deal in the Software
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, without restriction, including without limitation the rights to use, copy, modify, merge,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions: publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of The above copyright notice and this permission notice shall be included in all copies or
the Software. substantial portions of the Software.
**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** **THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.**

View File

@ -1,7 +1,7 @@
# ImageMonk makefile # Dehance makefile
# You can set these variables from the command line # You can set these variables from the command line
PROJECT = imagemonk PROJECT = dehance
.PHONY: help .PHONY: help
# Put it first so that "make" without argument is like "make help" # Put it first so that "make" without argument is like "make help"
@ -28,7 +28,8 @@ clean-docs:
rm --force docs/$(PROJECT)*.rst rm --force docs/$(PROJECT)*.rst
rm --force docs/modules.rst rm --force docs/modules.rst
clean: clean-tox clean-py clean-docs; ## Clean temp build/cache files and directories clean: clean-tox clean-py clean-docs ## Clean temp build/cache files and directories
rm --force ./*db*
wheel: ## Build Python binary distribution wheel package wheel: ## Build Python binary distribution wheel package
poetry build --format wheel poetry build --format wheel
@ -37,10 +38,10 @@ source: ## Build Python source distribution package
poetry build --format sdist poetry build --format sdist
test: clean-tox ## Run the project testsuite(s) test: clean-tox ## Run the project testsuite(s)
tox poetry run tox --parallelize-locked-install=10
publish: clean test wheel source ## Build and upload to pypi (requires $PYPI_API_KEY be set) publish: clean test wheel source ## Build and upload to pypi (requires $PYPI_API_KEY be set)
@poetry publish --username __token__ --password $(PYPI_API_KEY) @poetry publish --username __token__ --password $(PYPI_API_KEY)
docs: clean-docs ## Build the documentation using Sphinx docs: clean-docs ## Build the documentation using Sphinx
tox -e docs poetry run tox -e docs

View File

@ -1,5 +1,42 @@
# imagemonk # dehance
HTTP server for handling image uploads and thumbnail generation. HTTP server for handling image uploads and thumbnail generation.
This project requires [Poetry 1.0+](https://python-poetry.org/) This project requires [Poetry 1.0+](https://python-poetry.org/)
## Implementation goals
Support token based authentication:
```
POST /auth/token
GET /img/abcdefg.jpg?token=XYZ
```
Support dynamic resolution generation:
```
GET /img/abcdefg/100x50.jpg
```
Support server-side aliasing of resolutions to names:
```
GET /img/abcdefg/foobar.jpg # translates to something like 120x90
```
Support parameter-based selection of scaling method:
```
# "absolute scale horizontal", "relative scale vertical"
GET /img/abcdefg/200x100.jpg?h=abs&v=rel
```
Support both sqlite and maria storage backend
Support redis caching to relieve file system strain
Support autocleaning of cached file system files to reduce directory size
Support

View File

@ -1,9 +1,9 @@
"""Programatically accessible project metadata""" """Programatically accessible project metadata"""
__title__ = "imagemonk" __title__ = "dehance"
__version__ = "0.1.0" __version__ = "0.1.0"
__authors__ = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"] __authors__ = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
__license__ = "MIT" __license__ = "MIT"
__summary__ = "HTTP server for uploading images and generating thumbnails" __summary__ = "HTTP server for uploading images and generating thumbnails"
__url__ = "https://github.com/mocproject/imagemonk/" __url__ = "https://github.com/mocproject/dehance/"

View File

@ -1,12 +1,12 @@
"""Development server stub entrypoint """Development server stub entrypoint
Flask comes with a built-in development server. This entrypoint allows ``imagemonk`` Flask comes with a built-in development server. This entrypoint allows ``dehance``
to be run directly to run the development server and expose some simple config options for ease of to be run directly to run the development server and expose some simple config options for ease of
access. Run the below command to start the server: access. Run the below command to start the server:
:: ::
python -m imagemonk python -m dehance
In addition to the helpful CLI flags, the Flask development server run by this module will also In addition to the helpful CLI flags, the Flask development server run by this module will also
load any ``.env`` files in the current working directory when running the application. load any ``.env`` files in the current working directory when running the application.
@ -17,7 +17,7 @@ load any ``.env`` files in the current working directory when running the applic
import argparse import argparse
import sys import sys
from imagemonk.application import APPLICATION from dehance.application import APPLICATION
# pylint: disable=invalid-name # pylint: disable=invalid-name

View File

@ -1,11 +1,11 @@
import flask import flask
from imagemonk import __about__ from dehance import __about__
from imagemonk import configuration from dehance import configuration
from imagemonk import constants from dehance import constants
from imagemonk import database from dehance import database
from imagemonk import exceptions from dehance import exceptions
from imagemonk.resources import ResponseHeaders from dehance.resources import ResponseHeaders
def make_the_tea() -> None: def make_the_tea() -> None:
@ -23,7 +23,7 @@ def initialize_database() -> None:
database.initialize(flask.current_app.appconfig) database.initialize(flask.current_app.appconfig)
class ImageMonkRequest(flask.Request): class DehanceRequest(flask.Request):
"""Extend the default Flask request object to add custom application state settings""" """Extend the default Flask request object to add custom application state settings"""
def make_response_headers(self) -> ResponseHeaders: def make_response_headers(self) -> ResponseHeaders:
@ -40,14 +40,14 @@ class ImageMonkRequest(flask.Request):
} }
class ImageMonkFlask(flask.Flask): class DehanceFlask(flask.Flask):
"""Extend the default Flask object to add the custom application config """Extend the default Flask object to add the custom application config
There's probably an easier/more kosher way to do this, but ¯\\_(ツ)_/¯ There's probably an easier/more kosher way to do this, but ¯\\_(ツ)_/¯
""" """
request_class = ImageMonkRequest request_class = DehanceRequest
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.appconfig: configuration.ImageMonkConfig = configuration.load() self.appconfig: configuration.DehanceConfig = configuration.load()

View File

@ -1,12 +1,12 @@
import flask_restful import flask_restful
from imagemonk import resources from dehance import resources
from imagemonk._server import ImageMonkFlask from dehance._server import DehanceFlask
from imagemonk._server import initialize_database from dehance._server import initialize_database
from imagemonk._server import make_the_tea from dehance._server import make_the_tea
APPLICATION = ImageMonkFlask(__name__) APPLICATION = DehanceFlask(__name__)
API = flask_restful.Api(APPLICATION, catch_all_404s=True) API = flask_restful.Api(APPLICATION, catch_all_404s=True)

View File

@ -8,7 +8,7 @@ from typing import Dict
from typing import Optional from typing import Optional
from typing import Tuple from typing import Tuple
from imagemonk import constants from dehance import constants
def _default_sqlite_pragmas() -> Dict[str, Any]: def _default_sqlite_pragmas() -> Dict[str, Any]:
@ -31,7 +31,7 @@ def _default_sqlite_pragmas() -> Dict[str, Any]:
@dataclass @dataclass
class _DBSqliteConfig: class _DBSqliteConfig:
path: Path = Path.cwd() / "imagemonk.db" path: Path = Path.cwd() / "dehance.db"
pragmas: Dict[str, Any] = field(default_factory=_default_sqlite_pragmas) pragmas: Dict[str, Any] = field(default_factory=_default_sqlite_pragmas)
@classmethod @classmethod
@ -51,7 +51,7 @@ class _DBMariaConfig:
username: str = "root" username: str = "root"
password: Optional[str] = None password: Optional[str] = None
port: int = 3306 port: int = 3306
schema: str = "imagemonk" schema: str = "dehance"
@classmethod @classmethod
def build(cls): def build(cls):
@ -106,7 +106,7 @@ class _UploadConfig:
@dataclass @dataclass
class ImageMonkConfig: class DehanceConfig:
database: _DBConfig = field(default_factory=_DBConfig.build) database: _DBConfig = field(default_factory=_DBConfig.build)
upload: _UploadConfig = field(default_factory=_UploadConfig.build) upload: _UploadConfig = field(default_factory=_UploadConfig.build)
storage_path: Path = Path.cwd() storage_path: Path = Path.cwd()
@ -120,6 +120,6 @@ class ImageMonkConfig:
) )
def load() -> ImageMonkConfig: def load() -> DehanceConfig:
return ImageMonkConfig.build() return DehanceConfig.build()

View File

@ -7,7 +7,7 @@ class SupportedDatabaseBackend(enum.Enum):
SQLITE = enum.auto() SQLITE = enum.auto()
HTTP_HEADER_RESPONSE_VERSION = "x-imagemonk-version" HTTP_HEADER_RESPONSE_VERSION = "x-dehance-version"
HTTP_HEADER_RESPONSE_DIGEST = "Digest" HTTP_HEADER_RESPONSE_DIGEST = "Digest"

View File

@ -3,18 +3,18 @@ from typing import Tuple
import peewee import peewee
from imagemonk import constants from dehance import constants
from imagemonk.configuration import ImageMonkConfig from dehance.configuration import DehanceConfig
from imagemonk.database._shared import ImageMonkModel from dehance.database._shared import DehanceModel
from imagemonk.database._shared import INTERFACE as interface from dehance.database._shared import INTERFACE as interface
from imagemonk.database.image import ImageRecord from dehance.database.image import ImageRecord
from imagemonk.database.thumbnail import ThumbnailRecord from dehance.database.thumbnail import ThumbnailRecord
MODELS: Tuple[ImageMonkModel, ...] = (ImageRecord, ThumbnailRecord) MODELS: Tuple[DehanceModel, ...] = (ImageRecord, ThumbnailRecord)
def initialize(config: ImageMonkConfig): def initialize(config: DehanceConfig):
"""Initialize the database interface """Initialize the database interface
Defining the database as an Defining the database as an

View File

@ -7,7 +7,7 @@ import peewee
INTERFACE = peewee.DatabaseProxy() INTERFACE = peewee.DatabaseProxy()
class ImageMonkModel(peewee.Model): class DehanceModel(peewee.Model):
class Meta: # pylint: disable=too-few-public-methods,missing-class-docstring class Meta: # pylint: disable=too-few-public-methods,missing-class-docstring
database = INTERFACE database = INTERFACE

View File

@ -4,10 +4,10 @@ from typing import List
import peewee import peewee
from imagemonk.database._shared import ImageMonkModel from dehance.database._shared import DehanceModel
class ImageRecord(ImageMonkModel): class ImageRecord(DehanceModel):
"""Database record for""" """Database record for"""
width = peewee.IntegerField(null=False) width = peewee.IntegerField(null=False)

View File

@ -1,10 +1,10 @@
import peewee import peewee
from imagemonk.database._shared import ImageMonkModel from dehance.database._shared import DehanceModel
from imagemonk.database.image import ImageRecord from dehance.database.image import ImageRecord
class ThumbnailRecord(ImageMonkModel): class ThumbnailRecord(DehanceModel):
parent = peewee.ForeignKeyField(ImageRecord) parent = peewee.ForeignKeyField(ImageRecord)
width = peewee.IntegerField(null=False) width = peewee.IntegerField(null=False)

View File

@ -2,13 +2,13 @@
:: ::
ImageMonkException DehanceException
+-- ClientError +-- ClientError
+-- ServerError +-- ServerError
""" """
class ImageMonkException(Exception): class DehanceException(Exception):
"""Whomp whomp, something went wrong """Whomp whomp, something went wrong
But seriously, don't ever raise this exception But seriously, don't ever raise this exception
@ -17,7 +17,7 @@ class ImageMonkException(Exception):
status: int status: int
class ClientError(ImageMonkException): class ClientError(DehanceException):
"""Error while processing client side input""" """Error while processing client side input"""
status = 400 status = 400
@ -29,7 +29,7 @@ class ImageResourceDeletedError(ClientError):
status = 410 status = 410
class ServerError(ImageMonkException): class ServerError(DehanceException):
"""Error while processing server side data""" """Error while processing server side data"""
status = 500 status = 500

View File

@ -0,0 +1,19 @@
from typing import Tuple
from dehance.resources._shared import DehanceResource
from dehance.resources._shared import ResponseBody
from dehance.resources._shared import ResponseHeaders
from dehance.resources.image import Image
from dehance.resources.image import ImageUpload
from dehance.resources.openapi import OpenAPI
from dehance.resources.thumbnail import ThumbnailResize
from dehance.resources.thumbnail import ThumbnailScale
RESOURCES: Tuple[DehanceResource, ...] = (
ImageUpload,
Image,
OpenAPI,
ThumbnailScale,
ThumbnailResize,
)

View File

@ -31,7 +31,7 @@ class ResponseTuple(NamedTuple):
headers: ResponseHeaders headers: ResponseHeaders
class ImageMonkResource(flask_restful.Resource): class DehanceResource(flask_restful.Resource):
"""Extension of the default :class:`flask_restful.Resource` class """Extension of the default :class:`flask_restful.Resource` class
Add a couple of useful things to the default resource class: Add a couple of useful things to the default resource class:

View File

@ -4,13 +4,13 @@ import uuid
import flask import flask
from imagemonk import constants from dehance import constants
from imagemonk import database from dehance import database
from imagemonk import exceptions from dehance import exceptions
from imagemonk.resources._shared import ImageMonkResource from dehance.resources._shared import DehanceResource
class ImageUpload(ImageMonkResource): class ImageUpload(DehanceResource):
routes = ("/image/",) routes = ("/image/",)
@ -20,8 +20,6 @@ class ImageUpload(ImageMonkResource):
uploaded = flask.request.files["image"] uploaded = flask.request.files["image"]
breakpoint()
if not uploaded.filename: if not uploaded.filename:
raise raise
@ -47,16 +45,14 @@ class ImageUpload(ImageMonkResource):
return None, 201 return None, 201
class Image(ImageMonkResource): class Image(DehanceResource):
routes = ("/image/<string:image_id>.jpeg",) routes = ("/image/<string:image_id>.jpeg",)
def get(self, image_id: str): def get(self, image_id: str):
image = database.ImageRecord.get( image = database.ImageRecord.get(
database.ImageRecord.uuid database.ImageRecord.uuid == uuid.UUID(image_id)
== uuid.UUID(image_id) & database.ImageRecord.format
== format
) )
if image.deleted: if image.deleted:

View File

@ -2,12 +2,12 @@ from pathlib import Path
from ruamel.yaml import YAML from ruamel.yaml import YAML
from imagemonk.resources._shared import ImageMonkResource from dehance.resources._shared import DehanceResource
yaml = YAML(typ="safe") yaml = YAML(typ="safe")
class OpenAPI(ImageMonkResource): class OpenAPI(DehanceResource):
routes = ("/openapi.json",) routes = ("/openapi.json",)

View File

@ -1,7 +1,7 @@
from imagemonk.resources._shared import ImageMonkResource from dehance.resources._shared import DehanceResource
class ThumbnailScale(ImageMonkResource): class ThumbnailScale(DehanceResource):
routes = ("/thumb/<string:image_id>/scale/<int:scale_width>.jpg",) routes = ("/thumb/<string:image_id>/scale/<int:scale_width>.jpg",)
@ -9,7 +9,7 @@ class ThumbnailScale(ImageMonkResource):
raise NotImplementedError raise NotImplementedError
class ThumbnailResize(ImageMonkResource): class ThumbnailResize(DehanceResource):
routes = ("/thumb/<string:image_id>/size/<int:width>x<int:height>.jpg",) routes = ("/thumb/<string:image_id>/size/<int:width>x<int:height>.jpg",)

View File

@ -7,18 +7,19 @@
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
import datetime
from pathlib import Path from pathlib import Path
BASE_DIR = Path(__file__).parent.resolve() BASE_DIR = Path(__file__).parent.resolve()
ABOUT = {} ABOUT = {}
with open(Path(BASE_DIR, "..", "imagemonk", "__about__.py")) as infile: with open(Path(BASE_DIR, "..", "dehance", "__about__.py")) as infile:
exec(infile.read(), ABOUT) exec(infile.read(), ABOUT)
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
project = ABOUT["__title__"] project = ABOUT["__title__"]
copyright = "2020" copyright = str(datetime.date.today().year)
author = ", ".join(ABOUT["__authors__"]) author = ", ".join(ABOUT["__authors__"])
# The full version, including alpha/beta/rc tags # The full version, including alpha/beta/rc tags

View File

@ -1,11 +1,11 @@
ImageMonk Dehance
========= =========
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Contents: :caption: Contents:
API Reference <imagemonk> API Reference <dehance>

View File

@ -1,19 +0,0 @@
from typing import Tuple
from imagemonk.resources._shared import ImageMonkResource
from imagemonk.resources._shared import ResponseBody
from imagemonk.resources._shared import ResponseHeaders
from imagemonk.resources.image import Image
from imagemonk.resources.image import ImageUpload
from imagemonk.resources.openapi import OpenAPI
from imagemonk.resources.thumbnail import ThumbnailResize
from imagemonk.resources.thumbnail import ThumbnailScale
RESOURCES: Tuple[ImageMonkResource, ...] = (
ImageUpload,
Image,
OpenAPI,
ThumbnailScale,
ThumbnailResize,
)

View File

@ -2,9 +2,9 @@
openapi: "3.0.2" openapi: "3.0.2"
info: info:
version: 0.1.0 version: 0.1.0
title: ImageMonk title: Dehance
description: >- description: >-
ImageMonk is a simple HTTP server that allows users to upload Dehance is a simple HTTP server that allows users to upload
images and retrieve them at a later time. In addition, it images and retrieve them at a later time. In addition, it
supports generating (and caching) scaled versions of the supports generating (and caching) scaled versions of the
uploaded images for use as thumbnails. uploaded images for use as thumbnails.
@ -13,7 +13,7 @@ info:
url: https://mit-license.org/ url: https://mit-license.org/
x-anchors: x-anchors:
DefaultHeaders: &headers-default DefaultHeaders: &headers-default
x-imagemonk-version: x-dehance-version:
$ref: "#/components/headers/Version" $ref: "#/components/headers/Version"
OptionsResponses: &responses-options OptionsResponses: &responses-options
'204': '204':

984
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,17 @@
[tool.poetry] [tool.poetry]
name = "imagemonk" name = "dehance"
version = "0.1.0" version = "0.1.0"
license = "MIT" license = "MIT"
authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"] authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
description = "HTTP server for uploading images and generating thumbnails" description = "HTTP server for uploading images and generating thumbnails"
repository = "https://github.com/mocproject/imagemonk/" repository = "https://github.com/mocproject/dehance/"
packages = [ packages = [
{include = "imagemonk"}, {include = "dehance"},
{include = "tests", format = "sdist"} {include = "tests", format = "sdist"}
] ]
include = [ include = [
"imagemonk/py.typed", "dehance/py.typed",
"imagemonk/resources/openapi.yaml" "dehance/resources/openapi.yaml"
] ]
keywords = ["flask", "image", "thumbnail", "hosting"] keywords = ["flask", "image", "thumbnail", "hosting"]
readme = "README.md" readme = "README.md"
@ -45,10 +45,10 @@ peewee = "^3.13.3"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
bandit = "^1.6.2" bandit = "^1.6.2"
black = { git = "https://github.com/psf/black.git" } black = "^21.4b2"
blacken-docs = "^1.9.1" blacken-docs = "^1.9.1"
ipython = "^7.10.2" ipython = "^7.10.2"
mypy = "^0.790" mypy = "^0.800"
pre-commit = "^2.1.1" pre-commit = "^2.1.1"
pre-commit-hooks = "^3.4.0" pre-commit-hooks = "^3.4.0"
pylint = "^2.6.0" pylint = "^2.6.0"
@ -60,7 +60,9 @@ sphinx = "^3.3.0"
sphinx-autodoc-typehints = "^1.11.1" sphinx-autodoc-typehints = "^1.11.1"
toml = "^0.10.1" toml = "^0.10.1"
tox = "^3.20.0" tox = "^3.20.0"
tox-poetry-installer = {extras = ["poetry"], version = "^0.6.1"} tox-poetry-installer = {extras = ["poetry"], version = "^0.7.0"}
mdformat = "^0.6"
mdformat-gfm = "^0.2"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.0.0"]

View File

@ -3,7 +3,7 @@ from pathlib import Path
import toml import toml
from imagemonk import __about__ from dehance import __about__
def test_about(): def test_about():

12
tox.ini
View File

@ -16,7 +16,7 @@ locked_deps =
pytest-cov pytest-cov
toml toml
commands = commands =
pytest --cov={envsitepackagesdir}/imagemonk --cov-config {toxinidir}/.coveragerc --cov-report term-missing {toxinidir}/tests/ pytest --cov={envsitepackagesdir}/dehance --cov-config {toxinidir}/.coveragerc --cov-report term-missing {toxinidir}/tests/
[testenv:static] [testenv:static]
description = Static formatting and quality enforcement description = Static formatting and quality enforcement
@ -26,6 +26,8 @@ skip_install = true
locked_deps = locked_deps =
black black
blacken-docs blacken-docs
mdformat
mdformat-gfm
mypy mypy
reorder-python-imports reorder-python-imports
pre-commit pre-commit
@ -33,8 +35,8 @@ locked_deps =
pylint pylint
commands = commands =
pre-commit run --all-files pre-commit run --all-files
pylint --rcfile {toxinidir}/.pylintrc {toxinidir}/imagemonk/ pylint --rcfile {toxinidir}/.pylintrc {toxinidir}/dehance/
mypy --ignore-missing-imports --no-strict-optional {toxinidir}/imagemonk/ mypy --ignore-missing-imports --no-strict-optional {toxinidir}/dehance/
[testenv:static-tests] [testenv:static-tests]
description = Static formatting and quality enforcement for the tests description = Static formatting and quality enforcement for the tests
@ -58,7 +60,7 @@ locked_deps =
safety safety
poetry poetry
commands = commands =
bandit --recursive --quiet {toxinidir}/imagemonk/ bandit --recursive --quiet {toxinidir}/dehance/
bandit --recursive --quiet --skip B101 {toxinidir}/tests/ bandit --recursive --quiet --skip B101 {toxinidir}/tests/
poetry export --format requirements.txt --output {envtmpdir}/requirements.txt --without-hashes --dev poetry export --format requirements.txt --output {envtmpdir}/requirements.txt --without-hashes --dev
safety check --bare --file {envtmpdir}/requirements.txt safety check --bare --file {envtmpdir}/requirements.txt
@ -70,5 +72,5 @@ locked_deps =
sphinx sphinx
sphinx-autodoc-typehints sphinx-autodoc-typehints
commands = commands =
sphinx-apidoc --no-toc --output-dir {toxinidir}/docs/ {toxinidir}/imagemonk/ sphinx-apidoc --no-toc --output-dir {toxinidir}/docs/ {toxinidir}/dehance/
sphinx-build -W -b html {toxinidir}/docs/ {toxinidir}/docs/_build sphinx-build -W -b html {toxinidir}/docs/ {toxinidir}/docs/_build