mirror of
https://github.com/enpaul/peewee-plus.git
synced 2025-10-28 23:37:28 +00:00
Compare commits
14 Commits
0693d19f7a
...
enp/py312
| Author | SHA1 | Date | |
|---|---|---|---|
|
b11519194d
|
|||
|
f6e3870067
|
|||
|
e96999ed43
|
|||
|
42798178ae
|
|||
| d240306a70 | |||
| 7944d4de48 | |||
| d33dae2774 | |||
| 19b149c5c2 | |||
| 5f81f7cef7 | |||
| 480e3f3875 | |||
| 0d1c642871 | |||
| 68120fa65a | |||
| 992df5b478 | |||
| 027da380a5 |
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -24,6 +24,8 @@ jobs:
|
|||||||
toxenv: py310
|
toxenv: py310
|
||||||
- version: "3.11"
|
- version: "3.11"
|
||||||
toxenv: py311
|
toxenv: py311
|
||||||
|
- version: "3.12"
|
||||||
|
toxenv: py312
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -2,6 +2,16 @@
|
|||||||
|
|
||||||
See also: [Github Release Page](https://github.com/enpaul/peewee-plus/releases).
|
See also: [Github Release Page](https://github.com/enpaul/peewee-plus/releases).
|
||||||
|
|
||||||
|
## Version 1.3.0
|
||||||
|
|
||||||
|
View this release on: [Github](https://github.com/enpaul/peewee-plus/releases/tag/1.3.0),
|
||||||
|
[PyPI](https://pypi.org/project/peewee-plus/1.3.0/)
|
||||||
|
|
||||||
|
- Add field for storing Datetime Timedeltas
|
||||||
|
- **BREAKING CHANGE**: Update `JSONField` to raise `ValueError` instead of
|
||||||
|
`IntegrityError` on bad data write
|
||||||
|
- Update tests to account for more cases and test public API validity
|
||||||
|
|
||||||
## Version 1.2.1
|
## Version 1.2.1
|
||||||
|
|
||||||
View this release on: [Github](https://github.com/enpaul/peewee-plus/releases/tag/1.2.1),
|
View this release on: [Github](https://github.com/enpaul/peewee-plus/releases/tag/1.2.1),
|
||||||
|
|||||||
@@ -27,9 +27,10 @@ Examples of unacceptable behavior include:
|
|||||||
- The use of sexualized language or imagery, and sexual attention or advances of any kind
|
- The use of sexualized language or imagery, and sexual attention or advances of any kind
|
||||||
- Trolling, insulting or derogatory comments, and personal or political attacks
|
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
- Public or private harassment
|
- Public or private harassment
|
||||||
- Publishing others' private information, such as a physical or email address, without their
|
- Publishing others' private information, such as a physical or email address, without
|
||||||
explicit permission
|
their explicit permission
|
||||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
- Other conduct which could reasonably be considered inappropriate in a professional
|
||||||
|
setting
|
||||||
|
|
||||||
## Enforcement Responsibilities
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
@@ -52,8 +53,8 @@ offline event.
|
|||||||
## Enforcement
|
## Enforcement
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the
|
||||||
community leaders responsible for enforcement at \[INSERT CONTACT METHOD\]. All
|
community leaders responsible for enforcement at \[INSERT CONTACT METHOD\]. All complaints
|
||||||
complaints will be reviewed and investigated promptly and fairly.
|
will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
All community leaders are obligated to respect the privacy and security of the reporter of
|
All community leaders are obligated to respect the privacy and security of the reporter of
|
||||||
any incident.
|
any incident.
|
||||||
@@ -105,8 +106,8 @@ toward or disparagement of classes of individuals.
|
|||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
|
||||||
available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
Community Impact Guidelines were inspired by
|
||||||
enforcement ladder](https://github.com/mozilla/diversity).
|
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see the FAQ at
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
https://www.contributor-covenant.org/faq. Translations are available at
|
https://www.contributor-covenant.org/faq. Translations are available at
|
||||||
|
|||||||
29
README.md
29
README.md
@@ -14,7 +14,8 @@ release history.
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
*The documentation for this project is currently a work in progress. Please see the source code for complete docs*
|
*The documentation for this project is currently a work in progress. Please see the source
|
||||||
|
code for complete docs*
|
||||||
|
|
||||||
- [Installing](#installing)
|
- [Installing](#installing)
|
||||||
- [Features](#features)
|
- [Features](#features)
|
||||||
@@ -57,34 +58,36 @@ when using SQLite
|
|||||||
|
|
||||||
### Functions
|
### Functions
|
||||||
|
|
||||||
[`calc_batch_size`](blob/devel/peewee_plus.py#L93) - Helper function for writing
|
`calc_batch_size` - Helper function for writing backend-agnostic batch queries while
|
||||||
backend-agnostic batch queries while accounting for the
|
accounting for the
|
||||||
[SQLite max variable limit](https://www.sqlite.org/limits.html#max_variable_number).
|
[SQLite max variable limit](https://www.sqlite.org/limits.html#max_variable_number).
|
||||||
|
|
||||||
[`flat_transaction`](blob/devel/peewee_plus.py#L159) - Decorator function for wrapping
|
`flat_transaction` - Decorator function for wrapping callables in a database transaction
|
||||||
callables in a database transaction without creating nested transactions
|
without creating nested transactions
|
||||||
|
|
||||||
### Classes
|
### Classes
|
||||||
|
|
||||||
[`PathField`](blob/devel/peewee_plus.py#204) - A Peewee database field for storing
|
`PathField` - A Peewee database field for storing
|
||||||
[Pathlib](https://docs.python.org/3/library/pathlib.html) objects, optionally relative to
|
[Pathlib](https://docs.python.org/3/library/pathlib.html) objects, optionally relative to
|
||||||
a runtime value.
|
a runtime value.
|
||||||
|
|
||||||
[`PrecisionFloatField`](blob/devel/peewee_plus.py#L262) - A Peewee database field for
|
`PrecisionFloatField` - A Peewee database field for storing floats while specifying the
|
||||||
storing floats while specifying the
|
|
||||||
[MySQL precision parameters](https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html)
|
[MySQL precision parameters](https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html)
|
||||||
`M` and `D`
|
`M` and `D`
|
||||||
|
|
||||||
[`JSONField`](blob/devel/peewee_plus.py#L293) - A Peewee database field for storing
|
`JSONField` - A Peewee database field for storing arbitrary JSON-serializable data
|
||||||
arbitrary JSON-serializable data
|
|
||||||
|
|
||||||
[`EnumField`](blob/devel/peewee_plus.py#L348) - A Peewee database field for storing Enums
|
`EnumField` - A Peewee database field for storing Enums by name
|
||||||
by name
|
|
||||||
|
`TimedeltaField` A Peewee database field for natively storing
|
||||||
|
[`datetime.timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta)
|
||||||
|
objects
|
||||||
|
|
||||||
## For Developers
|
## For Developers
|
||||||
|
|
||||||
All project contributors and participants are expected to adhere to the
|
All project contributors and participants are expected to adhere to the
|
||||||
[Contributor Covenant Code of Conduct, v2](CODE_OF_CONDUCT.md) ([external link](https://www.contributor-covenant.org/version/2/0/code_of_conduct/)).
|
[Contributor Covenant Code of Conduct, v2](CODE_OF_CONDUCT.md)
|
||||||
|
([external link](https://www.contributor-covenant.org/version/2/0/code_of_conduct/)).
|
||||||
|
|
||||||
The `devel` branch has the latest (and potentially unstable) changes. The stable releases
|
The `devel` branch has the latest (and potentially unstable) changes. The stable releases
|
||||||
are tracked on [Github](https://github.com/enpaul/peewee-plus/releases),
|
are tracked on [Github](https://github.com/enpaul/peewee-plus/releases),
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ Various extensions, helpers, and utilities for `Peewee`_
|
|||||||
.. _`Peewee documentation`: https://docs.peewee-orm.com/en/latest/peewee/database.html#recommended-settings
|
.. _`Peewee documentation`: https://docs.peewee-orm.com/en/latest/peewee/database.html#recommended-settings
|
||||||
"""
|
"""
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import datetime
|
||||||
import enum
|
import enum
|
||||||
import functools
|
import functools
|
||||||
import json
|
import json
|
||||||
@@ -32,7 +33,7 @@ import peewee
|
|||||||
|
|
||||||
|
|
||||||
__title__ = "peewee-plus"
|
__title__ = "peewee-plus"
|
||||||
__version__ = "1.2.1"
|
__version__ = "1.3.1"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
__summary__ = "Various extensions, helpers, and utilities for Peewee"
|
__summary__ = "Various extensions, helpers, and utilities for Peewee"
|
||||||
__url__ = "https://github.com/enpaul/peewee-plus/"
|
__url__ = "https://github.com/enpaul/peewee-plus/"
|
||||||
@@ -54,6 +55,7 @@ __all__ = [
|
|||||||
"PrecisionFloatField",
|
"PrecisionFloatField",
|
||||||
"SQLITE_DEFAULT_PRAGMAS",
|
"SQLITE_DEFAULT_PRAGMAS",
|
||||||
"SQLITE_DEFAULT_VARIABLE_LIMIT",
|
"SQLITE_DEFAULT_VARIABLE_LIMIT",
|
||||||
|
"TimedeltaField",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -315,6 +317,8 @@ class JSONField(peewee.TextField): # pylint: disable=abstract-method
|
|||||||
|
|
||||||
:param dump_params: Additional keyword arguments to unpack into :func:`json.dump`
|
:param dump_params: Additional keyword arguments to unpack into :func:`json.dump`
|
||||||
:param load_params: Additional keyword arguments to unpack into :func:`json.load`
|
:param load_params: Additional keyword arguments to unpack into :func:`json.load`
|
||||||
|
:raises ValueError: When attempting to set a non-JSON serializable object to the field
|
||||||
|
:raises peewee.IntegrityError: When the underlying database value is not JSON serializable
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -332,7 +336,7 @@ class JSONField(peewee.TextField): # pylint: disable=abstract-method
|
|||||||
try:
|
try:
|
||||||
return super().db_value(json.dumps(value, **self.dump_params))
|
return super().db_value(json.dumps(value, **self.dump_params))
|
||||||
except TypeError as err:
|
except TypeError as err:
|
||||||
raise peewee.IntegrityError(
|
raise ValueError(
|
||||||
f"Failed to JSON encode object of type '{type(value)}'"
|
f"Failed to JSON encode object of type '{type(value)}'"
|
||||||
) from err
|
) from err
|
||||||
|
|
||||||
@@ -399,3 +403,22 @@ class EnumField(peewee.CharField): # pylint: disable=abstract-method
|
|||||||
raise peewee.IntegrityError(
|
raise peewee.IntegrityError(
|
||||||
f"Enum {self.enumeration.__name__} has no value with name '{value}'"
|
f"Enum {self.enumeration.__name__} has no value with name '{value}'"
|
||||||
) from None
|
) from None
|
||||||
|
|
||||||
|
|
||||||
|
class TimedeltaField(peewee.BigIntegerField):
|
||||||
|
"""Field class for storing python-native Timedelta objects
|
||||||
|
|
||||||
|
This is really just a helper wrapper around an integer field that performs the second conversions
|
||||||
|
automatically. It is a helpful helper though, so it's included.
|
||||||
|
|
||||||
|
.. note:: To avoid issues with float precision, this field stores the database value as an integer.
|
||||||
|
However, this necessitates the usage of the BigInt type to avoid overflowing the value.
|
||||||
|
Essentially, the value this field ends up storing is the number of microseconds in the
|
||||||
|
timedelta.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def db_value(self, value: datetime.timedelta) -> int:
|
||||||
|
return super().db_value(int(value.total_seconds() * 1000000))
|
||||||
|
|
||||||
|
def python_value(self, value: int) -> datetime.timedelta:
|
||||||
|
return datetime.timedelta(seconds=super().python_value(value) / 1000000)
|
||||||
|
|||||||
1551
poetry.lock
generated
1551
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "peewee-plus"
|
name = "peewee-plus"
|
||||||
version = "1.2.1"
|
version = "1.3.1"
|
||||||
description = "Various extensions, helpers, and utilities for Peewee"
|
description = "Various extensions, helpers, and utilities for Peewee"
|
||||||
authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
|
authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
|
||||||
repository = "https://github.com/enpaul/peewee-plus/"
|
repository = "https://github.com/enpaul/peewee-plus/"
|
||||||
@@ -22,6 +22,7 @@ classifiers = [
|
|||||||
"Programming Language :: Python :: 3.9",
|
"Programming Language :: Python :: 3.9",
|
||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
"Programming Language :: Python :: Implementation :: CPython",
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
"Topic :: Database",
|
"Topic :: Database",
|
||||||
"Typing :: Typed"
|
"Typing :: Typed"
|
||||||
@@ -41,6 +42,8 @@ ruamel-yaml = {version = "^0.17.21", python = "^3.10"}
|
|||||||
#
|
#
|
||||||
# https://github.com/python-poetry/poetry-plugin-export/issues/176
|
# https://github.com/python-poetry/poetry-plugin-export/issues/176
|
||||||
virtualenv = ">=20.15,<20.16"
|
virtualenv = ">=20.15,<20.16"
|
||||||
|
setuptools = {version = "^68.2.2", python = "^3.12"}
|
||||||
|
pip = {version = "^23.2.1", python = "^3.12"}
|
||||||
|
|
||||||
[tool.poetry.group.ci.dependencies]
|
[tool.poetry.group.ci.dependencies]
|
||||||
poetry = "^1.4.2"
|
poetry = "^1.4.2"
|
||||||
@@ -55,8 +58,8 @@ safety = {version = "^2.2.0", python = "^3.10"}
|
|||||||
[tool.poetry.group.static.dependencies]
|
[tool.poetry.group.static.dependencies]
|
||||||
black = {version = "^22.8.0", python = "^3.10"}
|
black = {version = "^22.8.0", python = "^3.10"}
|
||||||
blacken-docs = {version = "^1.12.0", python = "^3.10"}
|
blacken-docs = {version = "^1.12.0", python = "^3.10"}
|
||||||
mdformat = {version = "^0.6.4", python = "^3.10"}
|
mdformat = {version = "^0.7.16", python = "^3.10"}
|
||||||
mdformat-gfm = {version = "^0.2", python = "^3.10"}
|
mdformat-gfm = {version = "^0.3.5", python = "^3.10"}
|
||||||
mypy = {version = "^1.2.0", python = "^3.10"}
|
mypy = {version = "^1.2.0", python = "^3.10"}
|
||||||
pre-commit = {version = "^2.15.0", python = "^3.10"}
|
pre-commit = {version = "^2.15.0", python = "^3.10"}
|
||||||
pre-commit-hooks = {version = "^4.0.1", python = "^3.10"}
|
pre-commit-hooks = {version = "^4.0.1", python = "^3.10"}
|
||||||
|
|||||||
@@ -8,6 +8,15 @@ import peewee_plus
|
|||||||
from .fixtures import fakedb
|
from .fixtures import fakedb
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_api():
|
||||||
|
"""Test that the public API components are exposed via ``__all__``"""
|
||||||
|
|
||||||
|
assert peewee_plus.calc_batch_size.__name__ in peewee_plus.__all__
|
||||||
|
assert peewee_plus.flat_transaction.__name__ in peewee_plus.__all__
|
||||||
|
assert "SQLITE_DEFAULT_VARIABLE_LIMIT" in peewee_plus.__all__
|
||||||
|
assert "SQLITE_DEFAULT_PRAGMAS" in peewee_plus.__all__
|
||||||
|
|
||||||
|
|
||||||
def test_sqlite(fakedb):
|
def test_sqlite(fakedb):
|
||||||
"""Test the calculation of batch sizes on SQLite"""
|
"""Test the calculation of batch sizes on SQLite"""
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ import peewee_plus
|
|||||||
from .fixtures import fakedb
|
from .fixtures import fakedb
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_api():
|
||||||
|
"""Test that the public API components are exposed via ``__all__``"""
|
||||||
|
|
||||||
|
assert peewee_plus.EnumField.__name__ in peewee_plus.__all__
|
||||||
|
|
||||||
|
|
||||||
def test_enum(fakedb):
|
def test_enum(fakedb):
|
||||||
"""Test basic functionality of the enum field"""
|
"""Test basic functionality of the enum field"""
|
||||||
|
|
||||||
78
tests/test_json_field.py
Normal file
78
tests/test_json_field.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# pylint: disable=redefined-outer-name
|
||||||
|
# pylint: disable=missing-class-docstring
|
||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
# pylint: disable=unused-import
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import peewee
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import peewee_plus
|
||||||
|
from .fixtures import fakedb
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_api():
|
||||||
|
"""Test that the public API components are exposed via ``__all__``"""
|
||||||
|
|
||||||
|
assert peewee_plus.JSONField.__name__ in peewee_plus.__all__
|
||||||
|
|
||||||
|
|
||||||
|
def test_json(fakedb):
|
||||||
|
"""Test basic usage of JSONField class"""
|
||||||
|
|
||||||
|
class TestModel(peewee.Model):
|
||||||
|
class Meta:
|
||||||
|
database = fakedb
|
||||||
|
|
||||||
|
some_data = peewee_plus.JSONField()
|
||||||
|
|
||||||
|
fakedb.create_tables([TestModel])
|
||||||
|
|
||||||
|
data = {"foo": 10, "bar": ["hello", "world"], "baz": True}
|
||||||
|
|
||||||
|
model = TestModel(some_data=data)
|
||||||
|
model.save()
|
||||||
|
|
||||||
|
model = TestModel.get()
|
||||||
|
assert model.some_data == data
|
||||||
|
|
||||||
|
|
||||||
|
def test_errors(fakedb):
|
||||||
|
"""Test that errors are raised as expected"""
|
||||||
|
|
||||||
|
class GoodModel(peewee.Model):
|
||||||
|
class Meta:
|
||||||
|
database = fakedb
|
||||||
|
# Needs to match the table name below
|
||||||
|
table_name = "one_table"
|
||||||
|
|
||||||
|
id = peewee.AutoField()
|
||||||
|
some_data = peewee_plus.JSONField()
|
||||||
|
|
||||||
|
class BadModel(peewee.Model):
|
||||||
|
class Meta:
|
||||||
|
database = fakedb
|
||||||
|
# Needs to match the table name above
|
||||||
|
table_name = "one_table"
|
||||||
|
|
||||||
|
id = peewee.AutoField()
|
||||||
|
some_data = peewee.TextField()
|
||||||
|
|
||||||
|
fakedb.create_tables([GoodModel])
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
# The usage of path here is arbitrary, it just needs to be any
|
||||||
|
# non-JSON serializable type
|
||||||
|
bad = GoodModel(some_data=Path("."))
|
||||||
|
bad.save()
|
||||||
|
|
||||||
|
good = GoodModel(some_data={"foo": 123})
|
||||||
|
good.save()
|
||||||
|
|
||||||
|
# This is overwriting the ``some_data`` on the above object with garbage
|
||||||
|
bad = BadModel.get(good.id)
|
||||||
|
bad.some_data = "This{ string' is not, valid JSON;"
|
||||||
|
bad.save()
|
||||||
|
|
||||||
|
with pytest.raises(peewee.IntegrityError):
|
||||||
|
GoodModel.get(good.id)
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# pylint: disable=redefined-outer-name
|
|
||||||
# pylint: disable=missing-class-docstring
|
|
||||||
# pylint: disable=too-few-public-methods
|
|
||||||
# pylint: disable=unused-import
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import peewee
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
import peewee_plus
|
|
||||||
from .fixtures import fakedb
|
|
||||||
|
|
||||||
|
|
||||||
def test_json(fakedb):
|
|
||||||
"""Test basic usage of JSONField class"""
|
|
||||||
|
|
||||||
class TestModel(peewee.Model):
|
|
||||||
class Meta:
|
|
||||||
database = fakedb
|
|
||||||
|
|
||||||
some_data = peewee_plus.JSONField()
|
|
||||||
|
|
||||||
fakedb.create_tables([TestModel])
|
|
||||||
|
|
||||||
data = {"foo": 10, "bar": ["hello", "world"], "baz": True}
|
|
||||||
|
|
||||||
model = TestModel(some_data=data)
|
|
||||||
model.save()
|
|
||||||
|
|
||||||
model = TestModel.get()
|
|
||||||
assert model.some_data == data
|
|
||||||
|
|
||||||
with pytest.raises(peewee.IntegrityError):
|
|
||||||
bad = TestModel(some_data=Path("."))
|
|
||||||
bad.save()
|
|
||||||
@@ -31,3 +31,10 @@ def test_about():
|
|||||||
)
|
)
|
||||||
is True
|
is True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_all():
|
||||||
|
"""Test that the string entries in ``__all__`` are correct"""
|
||||||
|
|
||||||
|
for item in peewee_plus.__all__:
|
||||||
|
assert hasattr(peewee_plus, item)
|
||||||
@@ -10,6 +10,12 @@ import peewee_plus
|
|||||||
from .fixtures import fakedb
|
from .fixtures import fakedb
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_api():
|
||||||
|
"""Test that the public API components are exposed via ``__all__``"""
|
||||||
|
|
||||||
|
assert peewee_plus.PathField.__name__ in peewee_plus.__all__
|
||||||
|
|
||||||
|
|
||||||
def test_conversion(fakedb):
|
def test_conversion(fakedb):
|
||||||
"""Test basic usage of PathField for roundtrip compatibility"""
|
"""Test basic usage of PathField for roundtrip compatibility"""
|
||||||
|
|
||||||
@@ -8,6 +8,12 @@ import peewee_plus
|
|||||||
from .fixtures import fakedb
|
from .fixtures import fakedb
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_api():
|
||||||
|
"""Test that the public API components are exposed via ``__all__``"""
|
||||||
|
|
||||||
|
assert peewee_plus.PrecisionFloatField.__name__ in peewee_plus.__all__
|
||||||
|
|
||||||
|
|
||||||
# There isn't anything we can really test here since this field implements
|
# There isn't anything we can really test here since this field implements
|
||||||
# a MySQL-specific syntax and we test with SQLite. This test is here just
|
# a MySQL-specific syntax and we test with SQLite. This test is here just
|
||||||
# to ensure that the behavior is consistent with the normal FloatField when
|
# to ensure that the behavior is consistent with the normal FloatField when
|
||||||
|
|||||||
37
tests/test_timedelta_field.py
Normal file
37
tests/test_timedelta_field.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# pylint: disable=redefined-outer-name
|
||||||
|
# pylint: disable=missing-class-docstring
|
||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
# pylint: disable=unused-import
|
||||||
|
import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import peewee
|
||||||
|
|
||||||
|
import peewee_plus
|
||||||
|
from .fixtures import fakedb
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_api():
|
||||||
|
"""Test that the public API components are exposed via ``__all__``"""
|
||||||
|
|
||||||
|
assert peewee_plus.TimedeltaField.__name__ in peewee_plus.__all__
|
||||||
|
|
||||||
|
|
||||||
|
def test_conversion(fakedb):
|
||||||
|
"""Test basic usage of PathField for roundtrip compatibility"""
|
||||||
|
|
||||||
|
class TestModel(peewee.Model):
|
||||||
|
class Meta:
|
||||||
|
database = fakedb
|
||||||
|
|
||||||
|
name = peewee.CharField()
|
||||||
|
some_timedelta = peewee_plus.TimedeltaField()
|
||||||
|
|
||||||
|
fakedb.create_tables([TestModel])
|
||||||
|
|
||||||
|
delta = datetime.timedelta(seconds=300)
|
||||||
|
model = TestModel(name="one", some_timedelta=delta)
|
||||||
|
model.save()
|
||||||
|
|
||||||
|
new = TestModel.get(TestModel.name == "one")
|
||||||
|
assert new.some_timedelta == delta
|
||||||
5
tox.ini
5
tox.ini
@@ -1,6 +1,6 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist =
|
envlist =
|
||||||
py{37,38,39,310,311}
|
py{37,38,39,310,311,312}
|
||||||
static
|
static
|
||||||
static-tests
|
static-tests
|
||||||
security
|
security
|
||||||
@@ -19,6 +19,9 @@ commands =
|
|||||||
--cov-config {toxinidir}/.coveragerc \
|
--cov-config {toxinidir}/.coveragerc \
|
||||||
--cov-report term-missing
|
--cov-report term-missing
|
||||||
|
|
||||||
|
[testenv:.package]
|
||||||
|
basepython = python3.10
|
||||||
|
|
||||||
[testenv:static]
|
[testenv:static]
|
||||||
description = Static formatting and quality enforcement
|
description = Static formatting and quality enforcement
|
||||||
basepython = python3.10
|
basepython = python3.10
|
||||||
|
|||||||
Reference in New Issue
Block a user