Skip to content

Commit

Permalink
Merge branch 'release/0.42.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
tadams42 committed Aug 18, 2023
2 parents 75c6e15 + 3a07191 commit 118d9b4
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.41.0
current_version = 0.42.0
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.dev(?P<build>\d+))?
serialize =
{major}.{minor}.{patch}.dev{build}
Expand Down
24 changes: 23 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
# CHANGELOG

## 0.410.0 (2023-07-26)

## 0.42.0 (2023-08-18)

- fix: coerce filter values to Python objects
Combination of SQLAlchemy 2.x and psycopg 3.x no longer accepts query parameters as
strings for ie. integers and date-times. Query like following:

```py
User.query.filter(User.id == "42").first()
```

results with

```log
ProgrammingError: (psycopg.errors.UndefinedFunction) operator does not exist: bigint = character varying
```

Ideally, this would've been resolved in either of these libraries or in applications
themselves. And in most cases this the only solution. But in `flask-rest-jsonapi-next`
we can workaround most of these errors by trying to coerce filter values into correct
types.

## 0.41.0 (2023-07-26)

- fix: don't log stacktrace for common exceptions
- fix: defend from empty filters
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
project = "flask-rest-jsonapi-next"
copyright = "2016-2021 miLibris; 2021-... miLibris, tadams42"
author = "tadams42"
release = "0.41.0"
release = "0.42.0"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ requires = ["setuptools>=64", "wheel"]

[project]
name = "flask-rest-jsonapi-next"
version = "0.41.0"
version = "0.42.0"
description = "Flask extension to create REST web api according to JSONAPI 1.0 specification with Flask, Marshmallow and data provider of your choice (SQLAlchemy, MongoDB, ...)"
readme = "README.md"
classifiers = [
Expand All @@ -25,6 +25,7 @@ dependencies = [
"sqlalchemy",
"requests",
"packaging",
"python-dateutil",
]
keywords = [
"web",
Expand Down
2 changes: 1 addition & 1 deletion src/flask_rest_jsonapi_next/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.41.0"
__version__ = "0.42.0"

from .api import Api
from .data_layers.alchemy import SqlalchemyDataLayer
Expand Down
28 changes: 26 additions & 2 deletions src/flask_rest_jsonapi_next/data_layers/filtering/alchemy.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""Helper to create sqlalchemy filters according to filter querystring parameter"""

from decimal import Decimal

import dateutil
from sqlalchemy import and_, not_, or_

from ...exceptions import InvalidFilters
Expand Down Expand Up @@ -60,9 +63,11 @@ def resolve(self):
value = {self.filter_["name"].split("__")[1]: value}

if isinstance(value, dict):
return getattr(self.column, self.operator)(**value)
return getattr(self.column, self.operator)(
**{k: self._coerce(v) for k, v in value.items()}
)
else:
return getattr(self.column, self.operator)(value)
return getattr(self.column, self.operator)(self._coerce(value))

if "or" in self.filter_ and self.filter_["or"]:
return or_(
Expand All @@ -81,6 +86,25 @@ def resolve(self):
).resolve()
)

@classmethod
def _coerce(cls, value):
try:
return int(value)
except Exception:
pass

try:
return dateutil.parser.isoparse(value)
except Exception:
pass

try:
return Decimal(value)
except Exception:
pass

return value

@property
def name(self):
"""Return the name of the node or raise a BadRequest exception
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from typing import Callable, Optional, Type, Union

import flask
from werkzeug.exceptions import default_exceptions
from marshmallow import ValidationError
from werkzeug.exceptions import default_exceptions

from .error_formatters import error_response_from

Expand Down

0 comments on commit 118d9b4

Please sign in to comment.