16 Commits
1.0.0 ... 1.2.0

Author SHA1 Message Date
5520faef88 Update changelog for version 1.2.0 2022-11-15 10:16:24 -05:00
60bdfbfb17 Remove support for python 3.6
Update transient dependencies
Update actions workflow to install poetry 1.2
Update makefile to use poetry 1.2 command structure
Add safety exclusions to account for outdated meta tools
Bump feature version to 1.2
2022-11-15 10:16:24 -05:00
d5d400e0a6 Update CI to run non-platform checks on python-3.10 2022-11-15 10:16:24 -05:00
e98aa73a8d Update changelog with version 1.1.1 2022-11-15 10:16:24 -05:00
4f5e007d7d Add badge for downloads per month 2022-11-15 10:16:24 -05:00
134c28fd92 Bump patch version 2022-11-15 10:16:24 -05:00
Evgeny Chernyavskiy
dac554e8d4 Ensure NULL-able Enums don't raise peewee.IntegrityError 2022-09-07 15:34:45 -04:00
44ad5da339 Update name of check CI workflow to improve clarity 2022-09-07 15:04:12 -04:00
ef8800059f Update black to stable release
Update transient dependencies to fix security errors
2022-09-07 15:04:12 -04:00
c6cab6ce2d Add build status badge to readme 2022-08-05 00:05:34 -04:00
6e9c3c2521 Update transient dependencies 2022-08-05 00:05:34 -04:00
02642312fb Add github actions CI 2022-08-05 00:05:34 -04:00
8076d8cd29 Update docs for new flat_transaction function 2022-01-20 01:05:25 -05:00
d2f66ce40e Update changelog with version 1.1 2022-01-20 01:03:12 -05:00
d33ffd3d8c Bump feature version 2022-01-20 01:01:48 -05:00
b8a684cec7 Add flat transaction decorator function 2022-01-20 00:59:02 -05:00
9 changed files with 1230 additions and 732 deletions

34
.github/scripts/setup-env.sh vendored Executable file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/env bash
#
# Environment setup script for the local project. Intended to be used with automation
# to create a repeatable local environment for tests to be run in. The python env
# this script creates can be accessed at the location defined by the CI_VENV variable
# below.
set -e;
CI_CACHE=$HOME/.cache;
POETRY_VERSION=1.2.2;
mkdir --parents "$CI_CACHE";
command -v python;
python --version;
curl --location https://install.python-poetry.org \
--output "$CI_CACHE/install-poetry.py" \
--silent \
--show-error;
python "$CI_CACHE/install-poetry.py" \
--version "$POETRY_VERSION" \
--yes;
poetry --version --no-ansi;
poetry run pip --version;
poetry install \
--quiet \
--remove-untracked \
--no-ansi;
poetry env info;
poetry run tox --version;

89
.github/workflows/ci.yaml vendored Normal file
View File

@@ -0,0 +1,89 @@
---
name: CI
on:
pull_request:
types: ["opened", "synchronize"]
push:
branches: ["devel"]
jobs:
Test:
name: Test with Python ${{ matrix.python.version }}
runs-on: ubuntu-latest
strategy:
matrix:
python:
- version: "3.7"
toxenv: py37
- version: "3.8"
toxenv: py38
- version: "3.9"
toxenv: py39
- version: "3.10"
toxenv: py310
fail-fast: true
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Python ${{ matrix.python.version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python.version }}
- name: Configure Job Cache
uses: actions/cache@v3
with:
path: |
~/.cache/pip
~/.cache/pypoetry/cache
~/.poetry
# Including the hashed poetry.lock in the cache slug ensures that the cache
# will be invalidated, and thus all packages will be redownloaded, if the
# lockfile is updated
key: ${{ runner.os }}-${{ matrix.python.toxenv }}-${{ hashFiles('**/poetry.lock') }}
- name: Configure Path
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Configure Environment
run: .github/scripts/setup-env.sh
- name: Run Toxenv ${{ matrix.python.toxenv }}
run: poetry run tox -e ${{ matrix.python.toxenv }}
Check:
name: Security, Linting, Formatting, Typing
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Python 3.10
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Configure Job Cache
uses: actions/cache@v3
with:
path: |
~/.cache/pip
~/.cache/pypoetry/cache
~/.poetry
# Hardcoded 'py310' slug here lets this cache piggyback on the 'py310' cache
# that is generated for the tests above
key: ${{ runner.os }}-py310-${{ hashFiles('**/poetry.lock') }}
- name: Configure Path
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Configure Environment
run: .github/scripts/setup-env.sh
- name: Run Static Analysis Checks
run: poetry run tox -e static
- name: Run Static Analysis Checks (Tests)
run: poetry run tox -e static-tests
- name: Run Security Checks
run: poetry run tox -e security

View File

@@ -2,6 +2,22 @@
See also: [Github Release Page](https://github.com/enpaul/peewee-plus/releases).
## Version 1.2.0
View this release on: [Github](https://github.com/enpaul/peewee-plus/releases/tag/1.2.0),
[PyPI](https://pypi.org/project/peewee-plus/1.2.0/)
- Remove support for Python 3.6
- Update development workflows to use Poetry 1.2
- Fix nullable enums raising an `IntegrityError` when value is `None` (#1)
## Version 1.1.0
View this release on: [Github](https://github.com/enpaul/peewee-plus/releases/tag/1.1.0),
[PyPI](https://pypi.org/project/peewee-plus/1.1.0/)
- Add decorator function for wrapping callables in a flat database transaction
## Version 1.0.0
View this release on: [Github](https://github.com/enpaul/peewee-plus/releases/tag/1.0.0),

View File

@@ -33,11 +33,11 @@ source: ## Build Python source distribution package
build: clean wheel source; ## Build all distribution packages
test: clean-tox ## Run the project testsuite(s)
poetry run tox
poetry run tox --parallel
publish: clean test build ## Build and upload to pypi (requires $PYPI_API_KEY be set)
@poetry publish --username __token__ --password $(PYPI_API_KEY)
dev: ## Create local dev environment
poetry install --remove-untracked
poetry install --sync
poetry run pre-commit install

View File

@@ -2,7 +2,9 @@
Various extensions, helpers, and utilities for [Peewee](http://peewee-orm.com)
[![CI Status](https://github.com/enpaul/peewee-plus/workflows/CI/badge.svg?event=push)](https://github.com/enpaul/peewee-plus/actions)
[![PyPI Version](https://img.shields.io/pypi/v/peewee-plus)](https://pypi.org/project/peewee-plus/)
[![PyPI Downloads](https://img.shields.io/pypi/dm/peewee-plus)](https://libraries.io/pypi/peewee-plus)
[![License](https://img.shields.io/pypi/l/peewee-plus)](https://opensource.org/licenses/MIT)
[![Python Supported Versions](https://img.shields.io/pypi/pyversions/peewee-plus)](https://www.python.org)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
@@ -55,25 +57,29 @@ when using SQLite
### Functions
[`calc_batch_size`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#L68) -
[`calc_batch_size`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#L71) -
Helper function for determining how to batch a create/update query with SQLite
[`flat_transaction`](https://github.com/enpaul/peewee-plus/blob/devel/peewee_plus.py#L137)
\- Decorator function for wrapping callables in a database transaction without creating
nested transactions
### Classes
[`PathField`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#134) - A
[`PathField`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#179) - A
Peewee database field for storing
[Pathlib](https://docs.python.org/3/library/pathlib.html) objects, optionally relative to
a runtime value.
[`PrecisionFloatField`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#L192)
[`PrecisionFloatField`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#L237)
\- A Peewee database field for storing floats while specifying the
[MySQL precision parameters](https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html)
`M` and `D`
[`JSONField`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#L222) - A
[`JSONField`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#L267) - A
Peewee database field for storing arbitrary JSON-serializable data
[`EnumField`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#L277) - A
[`EnumField`](https://github.com/enpaul/peewee-plus/blob/1.0.0/peewee_plus.py#L322) - A
Peewee database field for storing Enums by name
## For Developers

View File

@@ -12,7 +12,9 @@
.. _`Peewee documentation`: http://docs.peewee-orm.com/en/latest/peewee/database.html#recommended-settings
"""
import contextlib
import enum
import functools
import json
from pathlib import Path
from typing import Any
@@ -26,7 +28,7 @@ import peewee
__title__ = "peewee-plus"
__version__ = "1.0.0"
__version__ = "1.2.0"
__license__ = "MIT"
__summary__ = "Various extensions, helpers, and utilities for Peewee"
__url__ = "https://github.com/enpaul/peewee-plus/"
@@ -42,6 +44,7 @@ __all__ = [
"__authors__",
"calc_batch_size",
"EnumField",
"flat_transaction",
"JSONField",
"PathField",
"PrecisionFloatField",
@@ -131,7 +134,52 @@ def calc_batch_size(
return len(models)
class PathField(peewee.CharField):
def flat_transaction(interface: peewee.Database):
"""Database transaction wrapper that avoids nested transactions
A decorator that can be used to decorate functions or methods so that the entire callable
is executed in a single transaction context. If a transaction is already open then it will
be reused rather than opening a nested transaction.
Example usage:
.. code-block:: python
db = peewee.SqliteDatabase("test.db")
@flat_transaction(db)
def subquery():
...
@flat_transaction(db)
def my_query():
...
subquery()
# This call opens only a single transaction
my_query()
:param interface: Peewee database interface that should be used to open the transaction
"""
def outer(func):
@functools.wraps(func)
def inner(*args, **kwargs):
with interface.atomic() if not interface.in_transaction() else contextlib.nullcontext():
return func(*args, **kwargs)
return inner
return outer
# TODO: The disable=abstract-method pragmas below are to get around new linting warnings
# in pylint>2.12, but they haven't been addressed properly. They should be revisited
# and fixed properly in the future.
class PathField(peewee.CharField): # pylint: disable=abstract-method
"""Field class for storing file paths
This field can be used to simply store pathlib paths in the database without needing to
@@ -189,7 +237,7 @@ class PathField(peewee.CharField):
)
class PrecisionFloatField(peewee.FloatField):
class PrecisionFloatField(peewee.FloatField): # pylint: disable=abstract-method
"""Field class for storing floats with custom precision parameters
This field adds support for specifying the ``M`` and ``D`` precision parameters of a
@@ -219,7 +267,7 @@ class PrecisionFloatField(peewee.FloatField):
return [self.max_digits, self.decimal_places]
class JSONField(peewee.TextField):
class JSONField(peewee.TextField): # pylint: disable=abstract-method
"""Field class for storing JSON-serializable data
This field can be used to store a dictionary of data directly in the database without needing
@@ -274,7 +322,7 @@ class JSONField(peewee.TextField):
) from err
class EnumField(peewee.CharField):
class EnumField(peewee.CharField): # pylint: disable=abstract-method
"""Field class for storing Enums
This field can be used for storing members of an :class:`enum.Enum` in the database,
@@ -319,7 +367,11 @@ class EnumField(peewee.CharField):
def python_value(self, value: str) -> enum.Enum:
try:
return self.enumeration[super().python_value(value)]
return (
None
if value is None and self.null
else self.enumeration[super().python_value(value)]
)
except KeyError:
raise peewee.IntegrityError(
f"Enum {self.enumeration.__name__} has no value with name '{value}'"

1712
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "peewee-plus"
version = "1.0.0"
version = "1.2.0"
description = "Various extensions, helpers, and utilities for Peewee"
authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
repository = "https://github.com/enpaul/peewee-plus/"
@@ -17,7 +17,6 @@ classifiers = [
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
@@ -28,29 +27,29 @@ classifiers = [
]
[tool.poetry.dependencies]
python = "^3.6.1"
python = "^3.7.1"
peewee = "^3.14.8"
[tool.poetry.dev-dependencies]
bandit = "^1.7.1"
black = {version = "^21.11b1", python = "^3.7"}
blacken-docs = {version = "^1.12.0", python = "^3.7"}
ipython = {version = "^7.29.0", python = "^3.7"}
black = "^22.8.0"
blacken-docs = "^1.12.0"
ipython = "^7.29.0"
mdformat = "^0.6.4"
mdformat-gfm = "^0.2"
mypy = "^0.910"
pre-commit = "^2.15.0"
pre-commit-hooks = "^4.0.1"
pylint = "^2.11.1"
pylint = "^2.13.0"
pytest = "^6.2.5"
pytest-cov = "^3.0.0"
reorder-python-imports = "^2.6.0"
safety = "^1.10.3"
safety = "^2.2.0"
toml = "^0.10.2"
tox = "^3.24.4"
tox-poetry-installer = {extras = ["poetry"], version = "^0.8.2"}
tox-poetry-installer = {extras = ["poetry"], version = "^0.10.0"}
types-toml = "^0.10.1"
[build-system]
requires = ["poetry-core>=1.0.0"]
requires = ["poetry-core>=1.1.0"]
build-backend = "poetry.core.masonry.api"

View File

@@ -1,6 +1,6 @@
[tox]
envlist =
py{36,37,38,39,310}
py{37,38,39,310}
static
static-tests
security
@@ -24,7 +24,7 @@ commands =
[testenv:static]
description = Static formatting and quality enforcement
basepython = python3.8
basepython = python3.10
ignore_errors = true
locked_deps =
black
@@ -47,7 +47,7 @@ commands =
[testenv:static-tests]
description = Static formatting and quality enforcement for the tests
basepython = python3.8
basepython = python3.10
ignore_errors = true
locked_deps =
mypy
@@ -63,7 +63,7 @@ commands =
[testenv:security]
description = Security checks
basepython = python3.8
basepython = python3.10
skip_install = true
ignore_errors = true
locked_deps =