From 6ffc318fd0ec755caff7ee84e0205bcf3ca1896a Mon Sep 17 00:00:00 2001 From: xiechen Date: Thu, 5 Aug 2021 16:11:10 +0800 Subject: [PATCH 1/5] =?UTF-8?q?add=EF=BC=9ASmallInteger()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + ormar/fields/model_fields.py | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/README.md b/README.md index c38c41b..82f42d9 100644 --- a/README.md +++ b/README.md @@ -614,6 +614,7 @@ Available Model Fields (with required args - optional ones in docs): * `Time()` * `DateTime()` * `JSON()` +* `SmallInteger()` * `BigInteger()` * `Decimal(scale, precision)` * `UUID()` diff --git a/ormar/fields/model_fields.py b/ormar/fields/model_fields.py index 07e9ed0..1196048 100644 --- a/ormar/fields/model_fields.py +++ b/ormar/fields/model_fields.py @@ -538,6 +538,54 @@ else: ) +class SmallInteger(Integer, int): + """ + SmallInteger field factory that construct Field classes and populated their values. + """ + + _type = int + _sample = 0 + + def __new__( # type: ignore + cls, + *, + minimum: int = None, + maximum: int = None, + multiple_of: int = None, + **kwargs: Any + ) -> BaseField: + autoincrement = kwargs.pop("autoincrement", None) + autoincrement = ( + autoincrement + if autoincrement is not None + else kwargs.get("primary_key", False) + ) + kwargs = { + **kwargs, + **{ + k: v + for k, v in locals().items() + if k not in ["cls", "__class__", "kwargs"] + }, + } + kwargs["ge"] = kwargs["minimum"] + kwargs["le"] = kwargs["maximum"] + return super().__new__(cls, **kwargs) + + @classmethod + def get_column_type(cls, **kwargs: Any) -> Any: + """ + Return proper type of db column for given field type. + Accepts required and optional parameters that each column type accepts. + + :param kwargs: key, value pairs of sqlalchemy options + :type kwargs: Any + :return: initialized column with proper options + :rtype: sqlalchemy Column + """ + return sqlalchemy.SmallInteger() + + class BigInteger(Integer, int): """ BigInteger field factory that construct Field classes and populated their values. From d945a67f7a446df3563d68f4ae2b98ad99b0492a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E7=8C=BF=E8=BF=87=E5=AE=B6=E5=AE=B6?= <88415165+ProgrammerPlus1998@users.noreply.github.com> Date: Thu, 5 Aug 2021 16:38:34 +0800 Subject: [PATCH 2/5] Update model_fields.py add:SmallInteger() --- ormar/fields/model_fields.py | 48 ++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/ormar/fields/model_fields.py b/ormar/fields/model_fields.py index 07e9ed0..1196048 100644 --- a/ormar/fields/model_fields.py +++ b/ormar/fields/model_fields.py @@ -538,6 +538,54 @@ else: ) +class SmallInteger(Integer, int): + """ + SmallInteger field factory that construct Field classes and populated their values. + """ + + _type = int + _sample = 0 + + def __new__( # type: ignore + cls, + *, + minimum: int = None, + maximum: int = None, + multiple_of: int = None, + **kwargs: Any + ) -> BaseField: + autoincrement = kwargs.pop("autoincrement", None) + autoincrement = ( + autoincrement + if autoincrement is not None + else kwargs.get("primary_key", False) + ) + kwargs = { + **kwargs, + **{ + k: v + for k, v in locals().items() + if k not in ["cls", "__class__", "kwargs"] + }, + } + kwargs["ge"] = kwargs["minimum"] + kwargs["le"] = kwargs["maximum"] + return super().__new__(cls, **kwargs) + + @classmethod + def get_column_type(cls, **kwargs: Any) -> Any: + """ + Return proper type of db column for given field type. + Accepts required and optional parameters that each column type accepts. + + :param kwargs: key, value pairs of sqlalchemy options + :type kwargs: Any + :return: initialized column with proper options + :rtype: sqlalchemy Column + """ + return sqlalchemy.SmallInteger() + + class BigInteger(Integer, int): """ BigInteger field factory that construct Field classes and populated their values. From 7baaee63ce4753198956e9cbcc6f7019bbcf7b79 Mon Sep 17 00:00:00 2001 From: xiechen Date: Fri, 6 Aug 2021 11:43:51 +0800 Subject: [PATCH 3/5] =?UTF-8?q?add=EF=BC=9ASmallInteger()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/api/fields/model-fields.md | 28 ++++++ docs/fields/field-types.md | 13 +++ docs/index.md | 1 + ormar/__init__.py | 2 + ormar/fields/__init__.py | 2 + ormar/fields/model_fields.py | 96 +++++++++---------- .../test_encryption/test_encrypted_columns.py | 1 + tests/test_fastapi/test_choices_schema.py | 1 + .../test_model_definition.py | 1 + 10 files changed, 98 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 82f42d9..9b2523d 100644 --- a/README.md +++ b/README.md @@ -614,8 +614,8 @@ Available Model Fields (with required args - optional ones in docs): * `Time()` * `DateTime()` * `JSON()` -* `SmallInteger()` * `BigInteger()` +* `SmallInteger()` * `Decimal(scale, precision)` * `UUID()` * `LargeBinary(max_length)` diff --git a/docs/api/fields/model-fields.md b/docs/api/fields/model-fields.md index 3d4162b..adbf405 100644 --- a/docs/api/fields/model-fields.md +++ b/docs/api/fields/model-fields.md @@ -347,6 +347,34 @@ Accepts required and optional parameters that each column type accepts. `sqlalchemy Column`: initialized column with proper options + +## SmallInteger Objects + +```python +class SmallInteger(Integer, int) +``` + +SmallInteger field factory that construct Field classes and populated their values. + + +#### get\_column\_type + +```python + | @classmethod + | get_column_type(cls, **kwargs: Any) -> Any +``` + +Return proper type of db column for given field type. +Accepts required and optional parameters that each column type accepts. + +**Arguments**: + +- `kwargs` (`Any`): key, value pairs of sqlalchemy options + +**Returns**: + +`sqlalchemy Column`: initialized column with proper options + ## Decimal Objects diff --git a/docs/fields/field-types.md b/docs/fields/field-types.md index 12b703b..b76e288 100644 --- a/docs/fields/field-types.md +++ b/docs/fields/field-types.md @@ -69,6 +69,19 @@ Each of the `Fields` has assigned both `sqlalchemy` column class and python type !!!tip For explanation of other parameters check [pydantic][pydantic] documentation. +### SmallInteger + +`SmallInteger(minimum: int = None, + maximum: int = None, + multiple_of: int = None)` has no required parameters. + +* Sqlalchemy column: `sqlalchemy.SmallInteger` +* Type (used for pydantic): `int` + +!!!tip + For explanation of other parameters check [pydantic][pydantic] documentation. + + ### Float `Float(minimum: float = None, diff --git a/docs/index.md b/docs/index.md index c215fe5..20f8c86 100644 --- a/docs/index.md +++ b/docs/index.md @@ -636,6 +636,7 @@ Available Model Fields (with required args - optional ones in docs): * `DateTime()` * `JSON()` * `BigInteger()` +* `SmallInteger()` * `Decimal(scale, precision)` * `UUID()` * `LargeBinary(max_length)` diff --git a/ormar/__init__.py b/ormar/__init__.py index c9f8bc8..1c71fa9 100644 --- a/ormar/__init__.py +++ b/ormar/__init__.py @@ -41,6 +41,7 @@ from ormar.exceptions import ( # noqa: I100 from ormar.fields import ( BaseField, BigInteger, + SmallInteger, Boolean, DECODERS_MAP, Date, @@ -80,6 +81,7 @@ __version__ = "0.10.15" __all__ = [ "Integer", "BigInteger", + "SmallInteger", "Boolean", "Time", "Text", diff --git a/ormar/fields/__init__.py b/ormar/fields/__init__.py index bc679c4..9745b1b 100644 --- a/ormar/fields/__init__.py +++ b/ormar/fields/__init__.py @@ -9,6 +9,7 @@ from ormar.fields.foreign_key import ForeignKey, ForeignKeyField, UniqueColumns from ormar.fields.many_to_many import ManyToMany, ManyToManyField from ormar.fields.model_fields import ( BigInteger, + SmallInteger, Boolean, Date, DateTime, @@ -29,6 +30,7 @@ from ormar.fields.through_field import Through, ThroughField __all__ = [ "Decimal", "BigInteger", + "SmallInteger", "Boolean", "Date", "DateTime", diff --git a/ormar/fields/model_fields.py b/ormar/fields/model_fields.py index 1196048..a53ac0e 100644 --- a/ormar/fields/model_fields.py +++ b/ormar/fields/model_fields.py @@ -538,54 +538,6 @@ else: ) -class SmallInteger(Integer, int): - """ - SmallInteger field factory that construct Field classes and populated their values. - """ - - _type = int - _sample = 0 - - def __new__( # type: ignore - cls, - *, - minimum: int = None, - maximum: int = None, - multiple_of: int = None, - **kwargs: Any - ) -> BaseField: - autoincrement = kwargs.pop("autoincrement", None) - autoincrement = ( - autoincrement - if autoincrement is not None - else kwargs.get("primary_key", False) - ) - kwargs = { - **kwargs, - **{ - k: v - for k, v in locals().items() - if k not in ["cls", "__class__", "kwargs"] - }, - } - kwargs["ge"] = kwargs["minimum"] - kwargs["le"] = kwargs["maximum"] - return super().__new__(cls, **kwargs) - - @classmethod - def get_column_type(cls, **kwargs: Any) -> Any: - """ - Return proper type of db column for given field type. - Accepts required and optional parameters that each column type accepts. - - :param kwargs: key, value pairs of sqlalchemy options - :type kwargs: Any - :return: initialized column with proper options - :rtype: sqlalchemy Column - """ - return sqlalchemy.SmallInteger() - - class BigInteger(Integer, int): """ BigInteger field factory that construct Field classes and populated their values. @@ -634,6 +586,54 @@ class BigInteger(Integer, int): return sqlalchemy.BigInteger() +class SmallInteger(Integer, int): + """ + SmallInteger field factory that construct Field classes and populated their values. + """ + + _type = int + _sample = 0 + + def __new__( # type: ignore + cls, + *, + minimum: int = None, + maximum: int = None, + multiple_of: int = None, + **kwargs: Any + ) -> BaseField: + autoincrement = kwargs.pop("autoincrement", None) + autoincrement = ( + autoincrement + if autoincrement is not None + else kwargs.get("primary_key", False) + ) + kwargs = { + **kwargs, + **{ + k: v + for k, v in locals().items() + if k not in ["cls", "__class__", "kwargs"] + }, + } + kwargs["ge"] = kwargs["minimum"] + kwargs["le"] = kwargs["maximum"] + return super().__new__(cls, **kwargs) + + @classmethod + def get_column_type(cls, **kwargs: Any) -> Any: + """ + Return proper type of db column for given field type. + Accepts required and optional parameters that each column type accepts. + + :param kwargs: key, value pairs of sqlalchemy options + :type kwargs: Any + :return: initialized column with proper options + :rtype: sqlalchemy Column + """ + return sqlalchemy.SmallInteger() + + class Decimal(ModelFieldFactory, decimal.Decimal): """ Decimal field factory that construct Field classes and populated their values. diff --git a/tests/test_encryption/test_encrypted_columns.py b/tests/test_encryption/test_encrypted_columns.py index 2cfe0e8..504e2b2 100644 --- a/tests/test_encryption/test_encrypted_columns.py +++ b/tests/test_encryption/test_encrypted_columns.py @@ -67,6 +67,7 @@ class Author(ormar.Model): test_time = ormar.Time(default=datetime.time, **default_fernet) test_json = ormar.JSON(default={}, **default_fernet) test_bigint: int = ormar.BigInteger(default=0, **default_fernet) + test_smallint: int = ormar.SmallInteger(default=0, **default_fernet) test_decimal = ormar.Decimal(scale=2, precision=10, **default_fernet) test_decimal2 = ormar.Decimal(max_digits=10, decimal_places=2, **default_fernet) custom_backend: str = ormar.String( diff --git a/tests/test_fastapi/test_choices_schema.py b/tests/test_fastapi/test_choices_schema.py index 6d87fa4..cb93f62 100644 --- a/tests/test_fastapi/test_choices_schema.py +++ b/tests/test_fastapi/test_choices_schema.py @@ -42,6 +42,7 @@ class Organisation(ormar.Model): ident: str = ormar.String(max_length=100, choices=["ACME Ltd", "Other ltd"]) priority: int = ormar.Integer(choices=[1, 2, 3, 4, 5]) priority2: int = ormar.BigInteger(choices=[1, 2, 3, 4, 5]) + priority3: int = ormar.SmallInteger(choices=[1, 2, 3, 4, 5]) expire_date: datetime.date = ormar.Date( choices=[datetime.date(2021, 1, 1), datetime.date(2022, 5, 1)] ) diff --git a/tests/test_model_definition/test_model_definition.py b/tests/test_model_definition/test_model_definition.py index 399d8e8..9bacfce 100644 --- a/tests/test_model_definition/test_model_definition.py +++ b/tests/test_model_definition/test_model_definition.py @@ -35,6 +35,7 @@ class ExampleModel(Model): test_time = ormar.Time(default=datetime.time) test_json = ormar.JSON(default={}) test_bigint: int = ormar.BigInteger(default=0) + test_smallint: int = ormar.SmallInteger(default=0) test_decimal = ormar.Decimal(scale=2, precision=10) test_decimal2 = ormar.Decimal(max_digits=10, decimal_places=2) From 7e242f4fd34b3c3a8aefde40a97d1ffc383510f1 Mon Sep 17 00:00:00 2001 From: xiechen Date: Fri, 6 Aug 2021 15:57:07 +0800 Subject: [PATCH 4/5] =?UTF-8?q?add=EF=BC=9ASmallInteger()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_fastapi/test_choices_schema.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_fastapi/test_choices_schema.py b/tests/test_fastapi/test_choices_schema.py index cb93f62..7639ee5 100644 --- a/tests/test_fastapi/test_choices_schema.py +++ b/tests/test_fastapi/test_choices_schema.py @@ -110,6 +110,7 @@ def test_all_endpoints(): "ident": "ACME Ltd", "priority": 4, "priority2": 2, + "priority3": 1, "expire_date": "2022-05-01", "expire_time": "10:00:00", "expire_datetime": "2022-05-01T12:30:00", From 04555957b58f27ad7e6edcba566f3de2c62877c8 Mon Sep 17 00:00:00 2001 From: collerek Date: Fri, 6 Aug 2021 10:52:04 +0200 Subject: [PATCH 5/5] pin pip version to run github workflows --- .github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml index df50003..53fdcff 100644 --- a/.github/workflows/test-package.yml +++ b/.github/workflows/test-package.yml @@ -50,7 +50,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install --upgrade pip + python -m pip install pip==21.0.1 if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Run mysql env: