Skip to content

Commit

Permalink
Merge branch 'main' into limit_return_fields
Browse files Browse the repository at this point in the history
  • Loading branch information
sav-norem authored Aug 2, 2024
2 parents 2df1beb + b20e887 commit 79e6140
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ sync: $(INSTALL_STAMP)
lint: $(INSTALL_STAMP) dist
$(POETRY) run isort --profile=black --lines-after-imports=2 ./tests/ $(NAME) $(SYNC_NAME)
$(POETRY) run black ./tests/ $(NAME)
$(POETRY) run flake8 --ignore=W503,E501,F401,E731,E712 ./tests/ $(NAME) $(SYNC_NAME)
$(POETRY) run flake8 --ignore=E231,E501,E712,E731,F401,W503 ./tests/ $(NAME) $(SYNC_NAME)
$(POETRY) run mypy ./tests/ $(NAME) $(SYNC_NAME) --ignore-missing-imports --exclude migrate.py --exclude _compat\.py$
$(POETRY) run bandit -r $(NAME) $(SYNC_NAME) -s B608

Expand Down
35 changes: 22 additions & 13 deletions aredis_om/model/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
AbstractSet,
Any,
Callable,
ClassVar,
Dict,
List,
Mapping,
Expand All @@ -32,7 +33,7 @@
from ulid import ULID

from .. import redis
from .._compat import BaseModel
from .._compat import PYDANTIC_V2, BaseModel
from .._compat import FieldInfo as PydanticFieldInfo
from .._compat import (
ModelField,
Expand Down Expand Up @@ -1441,13 +1442,22 @@ def outer_type_or_annotation(field):

class RedisModel(BaseModel, abc.ABC, metaclass=ModelMeta):
pk: Optional[str] = Field(default=None, primary_key=True)
ConfigDict: ClassVar

Meta = DefaultMeta

class Config:
orm_mode = True
arbitrary_types_allowed = True
extra = "allow"
if PYDANTIC_V2:
from pydantic import ConfigDict

model_config = ConfigDict(
from_attributes=True, arbitrary_types_allowed=True, extra="allow"
)
else:

class Config:
orm_mode = True
arbitrary_types_allowed = True
extra = "allow"

def __init__(__pydantic_self__, **data: Any) -> None:
__pydantic_self__.validate_primary_key()
Expand Down Expand Up @@ -1657,9 +1667,6 @@ def redisearch_schema(cls):

def check(self):
"""Run all validations."""
from pydantic.version import VERSION as PYDANTIC_VERSION

PYDANTIC_V2 = PYDANTIC_VERSION.startswith("2.")
if not PYDANTIC_V2:
*_, validation_error = validate_model(self.__class__, self.__dict__)
if validation_error:
Expand All @@ -1681,8 +1688,8 @@ def __init_subclass__(cls, **kwargs):
for typ in (Set, Mapping, List):
if isinstance(origin, type) and issubclass(origin, typ):
raise RedisModelError(
f"HashModels cannot index set, list,"
f" or mapping fields. Field: {name}"
f"HashModels cannot index set, list, "
f"or mapping fields. Field: {name}"
)
if isinstance(field_type, type) and issubclass(field_type, RedisModel):
raise RedisModelError(
Expand All @@ -1702,8 +1709,8 @@ def __init_subclass__(cls, **kwargs):
for typ in (Set, Mapping, List):
if issubclass(origin, typ):
raise RedisModelError(
f"HashModels cannot index set, list,"
f" or mapping fields. Field: {name}"
f"HashModels cannot index set, list, "
f"or mapping fields. Field: {name}"
)

if issubclass(outer_type, RedisModel):
Expand Down Expand Up @@ -2008,7 +2015,9 @@ def schema_for_fields(cls):
if issubclass(_type, str):
redisearch_field = f"$.{name} AS {name} TAG SEPARATOR {SINGLE_VALUE_TAG_FIELD_SEPARATOR}"
else:
redisearch_field = cls.schema_for_type(name, _type, field_info)
redisearch_field = cls.schema_for_type(
json_path, name, "", _type, field_info
)
schema_parts.append(redisearch_field)
continue
schema_parts.append(
Expand Down
3 changes: 1 addition & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
version: "3.8"

---
services:
redis:
image: "redis/redis-stack:latest"
Expand Down
9 changes: 5 additions & 4 deletions docs/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,11 @@ from redis_om import HashModel
class Customer(HashModel):
# ... Fields ...

class Config:
orm_mode = True
arbitrary_types_allowed = True
extra = "allow"
model_config = ConfigDict(
from_attributes=True,
arbitrary_types_allowed=True,
extra="allow",
)
```

Some features may not work correctly if you change these settings.
Expand Down
1 change: 1 addition & 0 deletions tests/test_hash_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,7 @@ class ModelWithStringDefault(HashModel):
assert res.test == "None"


@py_test_mark_asyncio
async def test_update_validation():
class TestUpdate(HashModel):
name: str
Expand Down
35 changes: 31 additions & 4 deletions tests/test_json_model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# type: ignore

import abc
import asyncio
import dataclasses
import datetime
import decimal
Expand Down Expand Up @@ -882,9 +883,23 @@ async def test_schema(m, key_prefix):
# We need to build the key prefix because it will differ based on whether
# these tests were copied into the tests_sync folder and unasynce'd.
key_prefix = m.Member.make_key(m.Member._meta.primary_key_pattern.format(pk=""))
assert (
m.Member.redisearch_schema()
== f"ON JSON PREFIX 1 {key_prefix} SCHEMA $.pk AS pk TAG SEPARATOR | $.first_name AS first_name TAG SEPARATOR | CASESENSITIVE $.last_name AS last_name TAG SEPARATOR | $.email AS email TAG SEPARATOR | $.age AS age NUMERIC $.bio AS bio TAG SEPARATOR | $.bio AS bio_fts TEXT $.address.pk AS address_pk TAG SEPARATOR | $.address.city AS address_city TAG SEPARATOR | $.address.postal_code AS address_postal_code TAG SEPARATOR | $.address.note.pk AS address_note_pk TAG SEPARATOR | $.address.note.description AS address_note_description TAG SEPARATOR | $.orders[*].pk AS orders_pk TAG SEPARATOR | $.orders[*].items[*].pk AS orders_items_pk TAG SEPARATOR | $.orders[*].items[*].name AS orders_items_name TAG SEPARATOR |"
assert m.Member.redisearch_schema() == (
f"ON JSON PREFIX 1 {key_prefix} SCHEMA "
"$.pk AS pk TAG SEPARATOR | "
"$.first_name AS first_name TAG SEPARATOR | CASESENSITIVE "
"$.last_name AS last_name TAG SEPARATOR | "
"$.email AS email TAG SEPARATOR | "
"$.age AS age NUMERIC "
"$.bio AS bio TAG SEPARATOR | "
"$.bio AS bio_fts TEXT "
"$.address.pk AS address_pk TAG SEPARATOR | "
"$.address.city AS address_city TAG SEPARATOR | "
"$.address.postal_code AS address_postal_code TAG SEPARATOR | "
"$.address.note.pk AS address_note_pk TAG SEPARATOR | "
"$.address.note.description AS address_note_description TAG SEPARATOR | "
"$.orders[*].pk AS orders_pk TAG SEPARATOR | "
"$.orders[*].items[*].pk AS orders_items_pk TAG SEPARATOR | "
"$.orders[*].items[*].name AS orders_items_name TAG SEPARATOR |"
)


Expand Down Expand Up @@ -1006,8 +1021,8 @@ class ModelWithStringDefault(JsonModel):
assert res.test == "None"


@py_test_mark_asyncio
async def test_update_validation():

class Embedded(EmbeddedJsonModel):
price: float
name: str = Field(index=True)
Expand Down Expand Up @@ -1037,6 +1052,7 @@ class TestUpdatesClass(JsonModel):
assert rematerialized.age == 42


@py_test_mark_asyncio
async def test_model_with_dict():
class EmbeddedJsonModelWithDict(EmbeddedJsonModel):
dict: Dict
Expand Down Expand Up @@ -1083,6 +1099,17 @@ class Example(JsonModel):
assert res.name == ex.name


@py_test_mark_asyncio
async def test_int_pk():
class ModelWithIntPk(JsonModel):
my_id: int = Field(index=True, primary_key=True)

await Migrator().run()
await ModelWithIntPk(my_id=42).save()

m = await ModelWithIntPk.find(ModelWithIntPk.my_id == 42).first()
assert m.my_id == 42

@py_test_mark_asyncio
async def test_pagination():
class Test(JsonModel):
Expand Down

0 comments on commit 79e6140

Please sign in to comment.