Skip to content

Commit 2649ede

Browse files
authored
add Decimal field (#104)
1 parent ea9153a commit 2649ede

File tree

9 files changed

+45
-11
lines changed

9 files changed

+45
-11
lines changed

.github/workflows/test-suite.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,17 @@ jobs:
1616
matrix:
1717
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10.0-rc.1"]
1818

19+
services:
20+
postgres:
21+
image: postgres:10.8
22+
env:
23+
POSTGRES_USER: username
24+
POSTGRES_PASSWORD: password
25+
POSTGRES_DB: testsuite
26+
ports:
27+
- 5432:5432
28+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
29+
1930
steps:
2031
- uses: "actions/checkout@v2"
2132
- uses: "actions/setup-python@v2"
@@ -28,6 +39,8 @@ jobs:
2839
- name: "Build package & docs"
2940
run: "scripts/build"
3041
- name: "Run tests"
42+
env:
43+
TEST_DATABASE_URL: "postgresql://username:password@localhost:5432/testsuite"
3144
run: "scripts/test"
3245
- name: "Enforce coverage"
3346
run: "scripts/coverage"

docs/declaring_models.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ See `TypeSystem` for [type-specific validation keyword arguments][typesystem-fie
6262
* `orm.Boolean()`
6363
* `orm.Date()`
6464
* `orm.DateTime()`
65+
* `orm.Decimal()`
6566
* `orm.Enum()`
6667
* `orm.Float()`
6768
* `orm.Integer()`

orm/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Boolean,
66
Date,
77
DateTime,
8+
Decimal,
89
Enum,
910
Float,
1011
ForeignKey,
@@ -15,14 +16,15 @@
1516
)
1617
from orm.models import Model
1718

18-
__version__ = "0.1.7"
19+
__version__ = "0.1.8"
1920
__all__ = [
2021
"NoMatch",
2122
"MultipleMatches",
2223
"BigInteger",
2324
"Boolean",
2425
"Date",
2526
"DateTime",
27+
"Decimal",
2628
"Enum",
2729
"Float",
2830
"Integer",

orm/fields.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,15 @@ def __init__(self, enum, **kwargs):
126126

127127
def get_column_type(self):
128128
return sqlalchemy.Enum(self.enum)
129+
130+
131+
class Decimal(ModelField, typesystem.Decimal):
132+
def __init__(self, max_digits: int, decimal_places: int, **kwargs):
133+
assert max_digits, "max_digits is required"
134+
assert decimal_places, "decimal_places is required"
135+
self.max_digits = max_digits
136+
self.decimal_places = decimal_places
137+
super().__init__(**kwargs)
138+
139+
def get_column_type(self):
140+
return sqlalchemy.Numeric(precision=self.max_digits, scale=self.decimal_places)

orm/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ async def load(self):
365365
row = await self.__database__.fetch_one(expr)
366366

367367
# Update the instance.
368-
for key, value in dict(row).items():
368+
for key, value in dict(row._mapping).items():
369369
setattr(self, key, value)
370370

371371
@classmethod

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
databases[sqlite]
1+
databases[postgresql]
2+
psycopg2
23
typesystem
34

45
# Packaging

tests/settings.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
import os
22

3-
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///test.db")
3+
assert "TEST_DATABASE_URL" in os.environ, "TEST_DATABASE_URL is not set."
4+
5+
DATABASE_URL = os.environ["TEST_DATABASE_URL"]

tests/test_columns.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime
2+
import decimal
23
from enum import Enum
34

45
import databases
@@ -35,6 +36,7 @@ class Example(orm.Model):
3536
created_time = orm.Time(default=time)
3637
description = orm.Text(allow_blank=True)
3738
value = orm.Float(allow_null=True)
39+
price = orm.Decimal(max_digits=5, decimal_places=2, allow_null=True)
3840
data = orm.JSON(default={})
3941
status = orm.Enum(StatusEnum, default=StatusEnum.DRAFT)
4042

@@ -57,13 +59,18 @@ async def test_model_crud():
5759
assert example.created_day == datetime.date.today()
5860
assert example.description == ""
5961
assert example.value is None
62+
assert example.price is None
6063
assert example.data == {}
6164
assert example.status == StatusEnum.DRAFT
6265

6366
await example.update(
64-
data={"foo": 123}, value=123.456, status=StatusEnum.RELEASED
67+
data={"foo": 123},
68+
value=123.456,
69+
status=StatusEnum.RELEASED,
70+
price=decimal.Decimal("999.99"),
6571
)
6672
example = await Example.objects.get()
6773
assert example.value == 123.456
6874
assert example.data == {"foo": 123}
6975
assert example.status == StatusEnum.RELEASED
76+
assert example.price == decimal.Decimal("999.99")

tests/test_models.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,23 +172,19 @@ async def test_model_order_by():
172172

173173
users = await User.objects.order_by("name", "-id").all()
174174
assert users[0].name == "Allen"
175-
assert users[0].id == 2
176175
assert users[1].name == "Bob"
177-
assert users[1].id == 3
176+
assert users[0].id < users[1].id
178177

179178
users = await User.objects.filter(name="Bob").order_by("-id").all()
180179
assert users[0].name == "Bob"
181-
assert users[0].id == 3
182180
assert users[1].name == "Bob"
183-
assert users[1].id == 1
181+
assert users[0].id > users[1].id
184182

185183
users = await User.objects.order_by("id").limit(1).all()
186184
assert users[0].name == "Bob"
187-
assert users[0].id == 1
188185

189186
users = await User.objects.order_by("id").limit(1).offset(1).all()
190187
assert users[0].name == "Allen"
191-
assert users[0].id == 2
192188

193189

194190
async def test_model_exists():

0 commit comments

Comments
 (0)