Skip to content

Commit

Permalink
Merge pull request #5 from proteanhq/4-rename-repository-to-adapter-a…
Browse files Browse the repository at this point in the history
…nd-enrich-for-domain-model

4 Rename `Repository` to `Adapter` and enrich for domain model
  • Loading branch information
advishnuprasad authored Jan 16, 2019
2 parents 376c265 + c7106c8 commit 4a7fdde
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 74 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,7 @@ output/*/index.html
*.bak

# VS Code
.vscode
.vscode

# Redis file
dump.rdb
52 changes: 26 additions & 26 deletions src/protean_sqlalchemy/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from protean.core.exceptions import ConfigurationError
from protean.core.repository import BaseConnectionHandler
from protean.core.repository import BaseRepository
from protean.core.repository import BaseSchema
from protean.core.repository import BaseAdapter
from protean.core.repository import BaseModel
from protean.core.repository import Pagination
from sqlalchemy import create_engine
from sqlalchemy import orm
Expand Down Expand Up @@ -42,35 +42,35 @@ def close_connection(self, conn):


@as_declarative(metaclass=DeclarativeMeta)
class SqlalchemySchema(BaseSchema):
"""Schema representation for the Sqlalchemy Database """
class SqlalchemyModel(BaseModel):
"""Model representation for the Sqlalchemy Database """

@declared_attr
def __tablename__(cls):
return cls.opts_.schema_name
return cls.opts_.model_name

@classmethod
def from_entity(cls, entity):
""" Convert the entity to a schema object """
""" Convert the entity to a model object """
return cls(**entity.to_dict())

@classmethod
def to_entity(cls, schema_obj):
""" Convert the schema object to an entity """
def to_entity(cls, model_obj):
""" Convert the model object to an entity """
item_dict = {}
for field_name in cls.opts_.entity_cls.meta_.declared_fields:
item_dict[field_name] = getattr(schema_obj, field_name, None)
item_dict[field_name] = getattr(model_obj, field_name, None)
return cls.opts_.entity_cls(item_dict)


class Repository(BaseRepository):
"""Repository implementation for the Elasticsearch Database"""
class Adapter(BaseAdapter):
"""Adapter implementation for the Databases compliant with SQLAlchemy"""

def _filter_objects(self, page: int = 1, per_page: int = 10, # noqa: C901
order_by: list = (), excludes_: dict = None,
**filters) -> Pagination:
""" Filter objects from the sqlalchemy database """
qs = self.conn.query(self.schema_cls)
qs = self.conn.query(self.model_cls)

# check for sqlalchemy filters
filter_ = filters.pop('filter_', None)
Expand All @@ -79,14 +79,14 @@ def _filter_objects(self, page: int = 1, per_page: int = 10, # noqa: C901

# apply the rest of the filters and excludes
for fk, fv in filters.items():
col = getattr(self.schema_cls, fk)
col = getattr(self.model_cls, fk)
if type(fv) in (list, tuple):
qs = qs.filter(col.in_(fv))
else:
qs = qs.filter(col == fv)

for ek, ev in excludes_.items():
col = getattr(self.schema_cls, ek)
col = getattr(self.model_cls, ek)
if type(ev) in (list, tuple):
qs = qs.filter(~col.in_(ev))
else:
Expand All @@ -95,7 +95,7 @@ def _filter_objects(self, page: int = 1, per_page: int = 10, # noqa: C901
# apply the ordering
order_cols = []
for order_col in order_by:
col = getattr(self.schema_cls, order_col.lstrip('-'))
col = getattr(self.model_cls, order_col.lstrip('-'))
if order_col.startswith('-'):
order_cols.append(col.desc())
else:
Expand All @@ -121,48 +121,48 @@ def _filter_objects(self, page: int = 1, per_page: int = 10, # noqa: C901

return result

def _create_object(self, schema_obj):
def _create_object(self, model_obj):
""" Add a new record to the sqlalchemy database"""
self.conn.add(schema_obj)
self.conn.add(model_obj)

try:
# If the schema has Auto fields then flush to get them
# If the model has Auto fields then flush to get them
if self.entity_cls.meta_.has_auto_field:
self.conn.flush()
self.conn.commit()
except DatabaseError:
self.conn.rollback()
raise

return schema_obj
return model_obj

def _update_object(self, schema_obj):
def _update_object(self, model_obj):
""" Update a record in the sqlalchemy database"""
primary_key, data = {}, {}
for field_name, field_obj in \
self.entity_cls.meta_.declared_fields.items():
if field_obj.identifier:
primary_key = {
field_name: getattr(schema_obj, field_name)
field_name: getattr(model_obj, field_name)
}
else:
data[field_name] = getattr(schema_obj, field_name, None)
data[field_name] = getattr(model_obj, field_name, None)

# Run the update query and commit the results
try:
self.conn.query(self.schema_cls).filter_by(
self.conn.query(self.model_cls).filter_by(
**primary_key).update(data)
self.conn.commit()
except DatabaseError:
self.conn.rollback()
raise

return schema_obj
return model_obj

def _delete_objects(self, **filters):
""" Delete a record from the sqlalchemy database"""
# Delete the objects and commit the results
qs = self.conn.query(self.schema_cls)
qs = self.conn.query(self.model_cls)
try:
del_count = qs.filter_by(**filters).delete()
self.conn.commit()
Expand All @@ -172,5 +172,5 @@ def _delete_objects(self, **filters):
return del_count

def delete_all(self):
""" Delete all records in this schema """
""" Delete all records in this model """
self._delete_objects()
12 changes: 6 additions & 6 deletions src/protean_sqlalchemy/utils.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
""" Utility functions for the Protean Sqlalchemy Package """
from protean.core.repository import repo
from protean.core.repository import repo_factory
from sqlalchemy.orm.session import Session

from protean_sqlalchemy.repository import SqlalchemySchema
from protean_sqlalchemy.repository import SqlalchemyModel


def create_tables():
""" Create tables for all registered entities"""

for conn_name, conn in repo.connections.items():
for conn_name, conn in repo_factory.connections.items():
if isinstance(conn, Session):
SqlalchemySchema.metadata.create_all(conn.bind)
SqlalchemyModel.metadata.create_all(conn.bind)


def drop_tables():
""" Drop tables for all registered entities"""

# Delete all the tables
for conn_name, conn in repo.connections.items():
for conn_name, conn in repo_factory.connections.items():
if isinstance(conn, Session):
SqlalchemySchema.metadata.drop_all(conn.bind)
SqlalchemyModel.metadata.drop_all(conn.bind)
30 changes: 15 additions & 15 deletions tests/test_repo_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

from protean.core import field
from protean.core.entity import Entity
from protean.core.repository import repo
from protean.core.repository import repo_factory

from protean_sqlalchemy.repository import SqlalchemySchema
from protean_sqlalchemy.repository import SqlalchemyModel

from .test_repository import DogSchema
from .test_repository import DogModel


class Human(Entity):
Expand All @@ -26,13 +26,13 @@ def __repr__(self):
return f'<Human id={self.id}>'


class HumanSchema(SqlalchemySchema):
""" Schema for the Human Entity"""
class HumanModel(SqlalchemyModel):
"""Model for the Human Entity"""

class Meta:
""" Meta class for schema options"""
""" Meta class for model options"""
entity = Human
schema_name = 'humans'
model_name = 'humans'
bind = 'another_db'


Expand All @@ -42,18 +42,18 @@ class TestSqlalchemyRepositoryExt:
@classmethod
def setup_class(cls):
""" Setup actions for this test case"""
repo.register(HumanSchema)
repo.register(DogSchema)
repo_factory.register(HumanModel)
repo_factory.register(DogModel)

# Create all the tables
for conn in repo.connections.values():
SqlalchemySchema.metadata.create_all(conn.bind)
for conn in repo_factory.connections.values():
SqlalchemyModel.metadata.create_all(conn.bind)

def test_create(self):
""" Test creating an entity with all field types"""

# Create the entity and validate the results
human = repo.HumanSchema.create(
human = repo_factory.HumanModel.create(
name='John Doe', age='30', weight='13.45',
date_of_birth='01-01-2000',
hobbies=['swimming'],
Expand All @@ -76,14 +76,14 @@ def test_create(self):
assert human.to_dict() == expected

# Check if the object is in the repo
human = repo.HumanSchema.get(1)
human = repo_factory.HumanModel.get(1)
assert human is not None
assert human.to_dict() == expected

def test_multiple_dbs(self):
""" Test repository connections to multiple databases"""
humans = repo.HumanSchema.filter()
humans = repo_factory.HumanModel.filter()
assert humans is not None

dogs = repo.DogSchema.filter()
dogs = repo_factory.DogModel.filter()
assert dogs is not None
Loading

0 comments on commit 4a7fdde

Please sign in to comment.