1
0
mirror of https://github.com/enpaul/kodak.git synced 2024-11-14 02:27:24 +00:00

Rename project to fresnel-lens

This commit is contained in:
Ethan Paul 2021-10-28 19:03:09 -04:00
parent f9c38a5bcc
commit 888225bdf7
No known key found for this signature in database
GPG Key ID: D0E2CBF1245E92BF
31 changed files with 155 additions and 160 deletions

4
.gitignore vendored
View File

@ -16,9 +16,9 @@ dist/
docs/_build/ docs/_build/
docs/modules.rst docs/modules.rst
docs/imagemuck*.rst docs/fresnel_lens*.rst
imagemuck/openapi.yaml fresnel_lens/openapi.yaml
.vscode/ .vscode/
.idea/ .idea/

View File

@ -32,7 +32,7 @@ repos:
name: reorder-python-imports name: reorder-python-imports
entry: reorder-python-imports entry: reorder-python-imports
args: args:
- "--unclassifiable-application-module=imagemuck" - "--unclassifiable-application-module=fresnel_lens"
language: system language: system
types: [python] types: [python]

View File

@ -1,7 +1,7 @@
# ImageMuck makefile # fresnel-lens makefile
# You can set these variables from the command line # You can set these variables from the command line
PROJECT = imagemuck PROJECT = fresnel_lens
.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"

View File

@ -1,4 +1,4 @@
# imagemuck # fresnel-lens
HTTP server for handling image uploads and thumbnail generation. HTTP server for handling image uploads and thumbnail generation.

View File

@ -12,7 +12,7 @@ from pathlib import Path
BASE_DIR = Path(__file__).parent.resolve() BASE_DIR = Path(__file__).parent.resolve()
ABOUT = {} ABOUT = {}
with open(Path(BASE_DIR, "..", "imagemuck", "__about__.py")) as infile: with open(Path(BASE_DIR, "..", "fresnel_lens", "__about__.py")) as infile:
exec(infile.read(), ABOUT) exec(infile.read(), ABOUT)

View File

@ -1,11 +1,11 @@
ImageMuck Fresnel Lens
========= ============
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Contents: :caption: Contents:
API Reference <imagemuck> API Reference <fresnel_lens>

View File

@ -1,9 +1,9 @@
"""Programatically accessible project metadata""" """Programatically accessible project metadata"""
__title__ = "imagemuck" __title__ = "fresnel-lens"
__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/imagemuck/" __url__ = "https://github.com/enpaul/fresnel-lens/"

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 ``imagemuck`` Flask comes with a built-in development server. This entrypoint allows ``fresnel_lens``
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 imagemuck python -m fresnel_lens
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 imagemuck.application import APPLICATION from fresnel_lens.application import APPLICATION
# pylint: disable=invalid-name # pylint: disable=invalid-name

View File

@ -1,15 +1,16 @@
import flask import flask
from imagemuck import __about__ from fresnel_lens import __about__
from imagemuck import configuration from fresnel_lens import configuration
from imagemuck import constants from fresnel_lens import constants
from imagemuck import database from fresnel_lens import database
from imagemuck import exceptions from fresnel_lens import exceptions
from imagemuck.resources import ResponseHeaders from fresnel_lens.resources import ResponseHeaders
def make_the_tea() -> None: def make_the_tea() -> None:
"""Just for fun """Just for fun
https://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol https://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol
""" """
if flask.request.content_type == "message/coffeepot": if flask.request.content_type == "message/coffeepot":
@ -23,7 +24,7 @@ def initialize_database() -> None:
database.initialize(flask.current_app.appconfig) database.initialize(flask.current_app.appconfig)
class ImageMuckRequest(flask.Request): class FresnelRequest(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:
@ -46,8 +47,8 @@ class ImageMuckFlask(flask.Flask):
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 = ImageMuckRequest request_class = FresnelRequest
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.appconfig: configuration.ImageMuckConfig = configuration.load() self.appconfig: configuration.FresnelConfig = configuration.load()

View File

@ -1,9 +1,9 @@
import flask_restful import flask_restful
from imagemuck import resources from fresnel_lens import resources
from imagemuck._server import ImageMuckFlask from fresnel_lens._server import ImageMuckFlask
from imagemuck._server import initialize_database from fresnel_lens._server import initialize_database
from imagemuck._server import make_the_tea from fresnel_lens._server import make_the_tea
APPLICATION = ImageMuckFlask(__name__) APPLICATION = ImageMuckFlask(__name__)

View File

@ -1,3 +1,5 @@
import datetime
import enum
import json import json
import os import os
from dataclasses import dataclass from dataclasses import dataclass
@ -5,10 +7,20 @@ from dataclasses import field
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
from typing import Dict from typing import Dict
from typing import NamedTuple
from typing import Optional from typing import Optional
from typing import Sequence
from typing import Tuple from typing import Tuple
from imagemuck import constants import peewee
from fresnel_lens import constants
class DimensionConfig(NamedTuple):
strategy: constants.DimensionStrategy
anchor: constants.Anchor
value: int
def _default_sqlite_pragmas() -> Dict[str, Any]: def _default_sqlite_pragmas() -> Dict[str, Any]:
@ -31,7 +43,7 @@ def _default_sqlite_pragmas() -> Dict[str, Any]:
@dataclass @dataclass
class _DBSqliteConfig: class _DBSqliteConfig:
path: Path = Path.cwd() / "imagemuck.db" path: Path = Path.cwd() / "fresnel_lens.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 +63,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 = "imagemuck" schema: str = "fresnel_lens"
@classmethod @classmethod
def build(cls): def build(cls):
@ -67,52 +79,40 @@ class _DBMariaConfig:
@dataclass @dataclass
class _DBConfig: class _DBConfig:
backend: constants.SupportedDatabaseBackend = ( backend: constants.DatabaseBackend = constants.DatabaseBackend.SQLITE
constants.SupportedDatabaseBackend.SQLITE
)
sqlite: _DBSqliteConfig = field(default_factory=_DBSqliteConfig.build) sqlite: _DBSqliteConfig = field(default_factory=_DBSqliteConfig.build)
mariadb: _DBMariaConfig = field(default_factory=_DBMariaConfig.build) mariadb: _DBMariaConfig = field(default_factory=_DBMariaConfig.build)
@classmethod @classmethod
def build(cls): def build(cls):
return cls( return cls(
backend=constants.SupportedDatabaseBackend[ backend=constants.DatabaseBackend[os.environ[constants.ENV_CONF_DB_BACKEND]]
os.environ[constants.ENV_CONF_DB_BACKEND]
]
if constants.ENV_CONF_DB_BACKEND in os.environ if constants.ENV_CONF_DB_BACKEND in os.environ
else cls.backend else cls.backend
) )
@dataclass @dataclass
class _UploadConfig: class ManipConfig:
alias: str
size_limit: int = 1 * 1024 * 1024 formats: Sequence[constants.ImageFormat] = (
formats: Tuple[str] = ("jpg", "jpeg") constants.ImageFormat.JPEG,
constants.ImageFormat.PNG,
@classmethod )
def build(cls): horizontal: None
return cls( vertical: None
size_limit=(int(os.environ[constants.ENV_CONF_FS_UPLOAD_MAX_SIZE]) * 1024)
if constants.ENV_CONF_FS_UPLOAD_MAX_SIZE in os.environ
else cls.size_limit,
formats=(
item.strip().lower()
for item in os.environ[constants.ENV_CONF_FS_UPLOAD_FORMATS].split(",")
)
if constants.ENV_CONF_FS_UPLOAD_MAX_SIZE in os.environ
else cls.formats,
)
@dataclass @dataclass
class ImageMuckConfig: class ImageMuckConfig:
database: _DBConfig = field(default_factory=_DBConfig.build) database: _DBConfig = field(default_factory=_DBConfig.build)
upload: _UploadConfig = field(default_factory=_UploadConfig.build) images: Path = Path.cwd() / "images"
storage_path: Path = Path.cwd() cache_dir: Path = Path.cwd() / "cache"
expose_source: bool = False
manips: Sequence[ManipConfig] = ()
@classmethod @classmethod
def build(cls): def from_env(cls):
return cls( return cls(
storage_path=Path( storage_path=Path(
os.getenv(constants.ENV_CONF_FS_STORAGE_PATH, cls.storage_path) os.getenv(constants.ENV_CONF_FS_STORAGE_PATH, cls.storage_path)
@ -121,5 +121,4 @@ class ImageMuckConfig:
def load() -> ImageMuckConfig: def load() -> ImageMuckConfig:
return ImageMuckConfig.from_env()
return ImageMuckConfig.build()

29
fresnel_lens/constants.py Normal file
View File

@ -0,0 +1,29 @@
import enum
import peewee
class DatabaseBackend(enum.Enum):
MARIADB = peewee.MySQLDatabase
SQLITE = peewee.SqliteDatabase
class DimensionStrategy(enum.Enum):
CROP = enum.auto()
SCALE = enum.auto()
RELATIVE = enum.auto()
class ImageFormat(enum.Enum):
JPEG = ("jpg", "jpeg")
PNG = ("png",)
GIF = ("gif",)
class Anchor(enum.Enum):
C = "center"
HTTP_HEADER_RESPONSE_VERSION = "x-fresnel_lens-version"
HTTP_HEADER_RESPONSE_DIGEST = "Digest"

View File

@ -3,18 +3,18 @@ from typing import Tuple
import peewee import peewee
from imagemuck import constants from fresnel_lens import constants
from imagemuck.configuration import ImageMuckConfig from fresnel_lens.configuration import FresnelConfig
from imagemuck.database._shared import ImageMuckModel from fresnel_lens.database._shared import FresnelModel
from imagemuck.database._shared import INTERFACE as interface from fresnel_lens.database._shared import INTERFACE as interface
from imagemuck.database.image import ImageRecord from fresnel_lens.database.image import ImageRecord
from imagemuck.database.thumbnail import ThumbnailRecord from fresnel_lens.database.thumbnail import ThumbnailRecord
MODELS: Tuple[ImageMuckModel, ...] = (ImageRecord, ThumbnailRecord) MODELS: Tuple[FresnelModel, ...] = (ImageRecord, ThumbnailRecord)
def initialize(config: ImageMuckConfig): def initialize(config: FresnelConfig):
"""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 ImageMuckModel(peewee.Model): class FresnelModel(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 imagemuck.database._shared import ImageMuckModel from fresnel_lens.database._shared import FresnelModel
class ImageRecord(ImageMuckModel): class ImageRecord(FresnelModel):
"""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 imagemuck.database._shared import ImageMuckModel from fresnel_lens.database._shared import FresnelModel
from imagemuck.database.image import ImageRecord from fresnel_lens.database.image import ImageRecord
class ThumbnailRecord(ImageMuckModel): class ThumbnailRecord(FresnelModel):
parent = peewee.ForeignKeyField(ImageRecord) parent = peewee.ForeignKeyField(ImageRecord)
width = peewee.IntegerField(null=False) width = peewee.IntegerField(null=False)

View File

@ -2,13 +2,13 @@
:: ::
ImageMuckException FresnelException
+-- ClientError +-- ClientError
+-- ServerError +-- ServerError
""" """
class ImageMuckException(Exception): class FresnelException(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 ImageMuckException(Exception):
status: int status: int
class ClientError(ImageMuckException): class ClientError(FresnelException):
"""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(ImageMuckException): class ServerError(FresnelException):
"""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 fresnel_lens.resources._shared import FresnelResource
from fresnel_lens.resources._shared import ResponseBody
from fresnel_lens.resources._shared import ResponseHeaders
from fresnel_lens.resources.image import Image
from fresnel_lens.resources.image import ImageUpload
from fresnel_lens.resources.openapi import OpenAPI
from fresnel_lens.resources.thumbnail import ThumbnailResize
from fresnel_lens.resources.thumbnail import ThumbnailScale
RESOURCES: Tuple[FresnelResource, ...] = (
ImageUpload,
Image,
OpenAPI,
ThumbnailScale,
ThumbnailResize,
)

View File

@ -31,7 +31,7 @@ class ResponseTuple(NamedTuple):
headers: ResponseHeaders headers: ResponseHeaders
class ImageMuckResource(flask_restful.Resource): class FresnelResource(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 imagemuck import constants from fresnel_lens import constants
from imagemuck import database from fresnel_lens import database
from imagemuck import exceptions from fresnel_lens import exceptions
from imagemuck.resources._shared import ImageMuckResource from fresnel_lens.resources._shared import FresnelResource
class ImageUpload(ImageMuckResource): class ImageUpload(FresnelResource):
routes = ("/image/",) routes = ("/image/",)
@ -45,7 +45,7 @@ class ImageUpload(ImageMuckResource):
return None, 201 return None, 201
class Image(ImageMuckResource): class Image(FresnelResource):
routes = ("/image/<string:image_id>.jpeg",) routes = ("/image/<string:image_id>.jpeg",)

View File

@ -2,12 +2,12 @@ from pathlib import Path
from ruamel.yaml import YAML from ruamel.yaml import YAML
from imagemuck.resources._shared import ImageMuckResource from fresnel_lens.resources._shared import FresnelResource
yaml = YAML(typ="safe") yaml = YAML(typ="safe")
class OpenAPI(ImageMuckResource): class OpenAPI(FresnelResource):
routes = ("/openapi.json",) routes = ("/openapi.json",)

View File

@ -1,7 +1,7 @@
from imagemuck.resources._shared import ImageMuckResource from fresnel_lens.resources._shared import FresnelResource
class ThumbnailScale(ImageMuckResource): class ThumbnailScale(FresnelResource):
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(ImageMuckResource):
raise NotImplementedError raise NotImplementedError
class ThumbnailResize(ImageMuckResource): class ThumbnailResize(FresnelResource):
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

@ -1,34 +0,0 @@
import enum
class SupportedDatabaseBackend(enum.Enum):
MARIADB = enum.auto()
SQLITE = enum.auto()
HTTP_HEADER_RESPONSE_VERSION = "x-imagemuck-version"
HTTP_HEADER_RESPONSE_DIGEST = "Digest"
ENV_CONF_DB_BACKEND = "IMGMONK_DATABASE_BACKEND"
ENV_CONF_DB_SQLITE_PATH = "IMGMONK_SQLITE_PATH"
ENV_CONF_DB_SQLITE_PRAGMAS = "IMGMONK_SQLITE_PRAGMAS"
ENV_CONF_DB_MARIA_HOSTNAME = "IMGMONK_MARIA_HOSTNAME"
ENV_CONF_DB_MARIA_USERNAME = "IMGMONK_MARIA_USERNAME"
ENV_CONF_DB_MARIA_PASSWORD = "IMGMONK_MARIA_PASSWORD"
ENV_CONF_DB_MARIA_PORT = "IMGMONK_MARIA_PORT"
ENV_CONF_DB_MARIA_SCHEMA = "IMGMONK_MARIA_SCHEMA"
ENV_CONF_FS_STORAGE_PATH = "IMGMONK_STORAGE_PATH"
ENV_CONF_FS_UPLOAD_MAX_SIZE = "IMGMONK_UPLOAD_LIMIT"
ENV_CONF_FS_UPLOAD_FORMATS = "IMGMONK_UPLOAD_FORMATS"

View File

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

View File

@ -2,7 +2,7 @@
openapi: "3.0.2" openapi: "3.0.2"
info: info:
version: 0.1.0 version: 0.1.0
title: ImageMuck title: Fresnel Lens
description: >- description: >-
A simple HTTP service for mucking about with images. This is a super basic HTTP A simple HTTP service for mucking about with images. This is a super basic HTTP
service for autogenerating website-ready banner and preview images from full-size service for autogenerating website-ready banner and preview images from full-size
@ -198,10 +198,10 @@ components:
data: {} data: {}
headers: headers:
Version: Version:
description: ImageMuck server application version description: Application name and version
schema: schema:
type: string type: string
example: imagemuck-1.0.0 example: fresnel-lens-1.0.0
Allowed: Allowed:
description: Comma delimited list of valid HTTP verbs description: Comma delimited list of valid HTTP verbs
schema: schema:

View File

@ -1,17 +1,17 @@
[tool.poetry] [tool.poetry]
name = "imagemuck" name = "fresnel-lens"
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/imagemuck/" repository = "https://github.com/enpaul/fresnel-lens/"
packages = [ packages = [
{include = "imagemuck"}, {include = "fresnel_lens"},
{include = "tests", format = "sdist"} {include = "tests", format = "sdist"}
] ]
include = [ include = [
"imagemuck/py.typed", "fresnel_lens/py.typed",
"imagemuck/openapi.yaml" "fresnel_lens/openapi.yaml"
] ]
keywords = ["flask", "image", "thumbnail", "hosting"] keywords = ["flask", "image", "thumbnail", "hosting"]
readme = "README.md" readme = "README.md"

View File

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

View File

@ -3,7 +3,7 @@ import importlib.resources
import openapi_spec_validator import openapi_spec_validator
import ruamel.yaml import ruamel.yaml
from imagemuck import __about__ from fresnel_lens import __about__
yaml = ruamel.yaml.YAML(typ="safe") # pylint: disable=invalid-name yaml = ruamel.yaml.YAML(typ="safe") # pylint: disable=invalid-name
@ -11,10 +11,10 @@ yaml = ruamel.yaml.YAML(typ="safe") # pylint: disable=invalid-name
def test_openapi(): def test_openapi():
openapi_spec_validator.validate_spec( openapi_spec_validator.validate_spec(
yaml.load(importlib.resources.read_text("imagemuck", "openapi.yaml")) yaml.load(importlib.resources.read_text("fresnel_lens", "openapi.yaml"))
) )
def test_openapi_version(): def test_openapi_version():
spec = yaml.load(importlib.resources.read_text("imagemuck", "openapi.yaml")) spec = yaml.load(importlib.resources.read_text("fresnel_lens", "openapi.yaml"))
assert spec["info"]["version"] == __about__.__version__ assert spec["info"]["version"] == __about__.__version__

10
tox.ini
View File

@ -19,7 +19,7 @@ locked_deps =
ruamel.yaml ruamel.yaml
toml toml
commands = commands =
pytest --cov={envsitepackagesdir}/imagemuck --cov-config {toxinidir}/.coveragerc --cov-report term-missing {toxinidir}/tests/ pytest --cov={envsitepackagesdir}/fresnel_lens --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
@ -38,8 +38,8 @@ locked_deps =
pylint pylint
commands = commands =
pre-commit run --all-files pre-commit run --all-files
pylint --rcfile {toxinidir}/.pylintrc {toxinidir}/imagemuck/ pylint --rcfile {toxinidir}/.pylintrc {toxinidir}/fresnel_lens/
mypy --ignore-missing-imports --no-strict-optional {toxinidir}/imagemuck/ mypy --ignore-missing-imports --no-strict-optional {toxinidir}/fresnel_lens/
[testenv:static-tests] [testenv:static-tests]
description = Static formatting and quality enforcement for the tests description = Static formatting and quality enforcement for the tests
@ -63,7 +63,7 @@ locked_deps =
safety safety
poetry poetry
commands = commands =
bandit --recursive --quiet {toxinidir}/imagemuck/ bandit --recursive --quiet {toxinidir}/fresnel_lens/
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
@ -75,5 +75,5 @@ locked_deps =
sphinx sphinx
sphinx-autodoc-typehints sphinx-autodoc-typehints
commands = commands =
sphinx-apidoc --no-toc --output-dir {toxinidir}/docs/ {toxinidir}/imagemuck/ sphinx-apidoc --no-toc --output-dir {toxinidir}/docs/ {toxinidir}/fresnel_lens/
sphinx-build -W -b html {toxinidir}/docs/ {toxinidir}/docs/_build sphinx-build -W -b html {toxinidir}/docs/ {toxinidir}/docs/_build