Skip to content

Commit

Permalink
Renamed services to repositories to better reflect their purpose
Browse files Browse the repository at this point in the history
  • Loading branch information
simoncoulton committed Apr 9, 2015
1 parent 30d3487 commit bd3115d
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 216 deletions.
2 changes: 1 addition & 1 deletion MANIFEST.in
Expand Up @@ -3,4 +3,4 @@ include AUTHORS
include LICENSE
include requirements.txt
include requirements-test.txt
include watson/db/alembic/*
include watson/db/alembic/templates/watson/*
4 changes: 2 additions & 2 deletions tests/watson/db/support.py
Expand Up @@ -5,7 +5,7 @@
from sqlalchemy.ext.declarative import declarative_base
from watson.framework import applications, events
from watson.db.models import _DeclarativeMeta
from watson.db.services import Base
from watson.db.repositories import Base


def start_response(status_line, headers):
Expand Down Expand Up @@ -72,5 +72,5 @@ def create_session_add_dummy_data():
session = create_session_add_dummy_data()


class TestService(Base):
class TestRepository(Base):
__model__ = Test
6 changes: 3 additions & 3 deletions tests/watson/db/test_fixtures.py
Expand Up @@ -16,7 +16,7 @@ def test_populate():

def test_populate_to_session():
fixtures.populate(support.session, 'tests/watson/db/fixtures/dummy.json')
service = support.TestService(support.session)
fixture = service.first(value='Fixture')
repo = support.TestRepository(support.session)
fixture = repo.first(value='Fixture')
assert fixture
service.delete(fixture)
repo.delete(fixture)
55 changes: 55 additions & 0 deletions tests/watson/db/test_repositories.py
@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
from pytest import raises
from tests.watson.db import support


class TestBaseRepository(object):

def setup(self):
self.session = support.session

def test_create(self):
with raises(Exception):
support.TestRepository()
assert support.TestRepository(self.session)

def test_new_obj(self):
repo = support.TestRepository(self.session)
obj = repo.new(value=2)
assert obj.value == 2

def test_query_all(self):
repo = support.TestRepository(self.session)
assert len(repo.all()) == 6

def test_get(self):
repo = support.TestRepository(self.session)
repo.get(1).value == 1
with raises(Exception):
repo.get(10, error_on_not_found=True)

def test_first(self):
repo = support.TestRepository(self.session)
assert repo.first(id=1).value == '1'

def test_save_delete(self):
repo = support.TestRepository(self.session)
obj = repo.new(value='test')
repo.save(obj)
assert repo.count() == 7
repo.delete(obj)
assert repo.count() == 6
assert not repo.first(value='test')

def test_save_delete_all(self):
repo = support.TestRepository(self.session)
obj = repo.new(value='test')
obj2 = repo.new(value='test2')
repo.save_all(obj, obj2)
assert repo.first(value='test2')
repo.delete_all(obj, obj2)
assert not repo.first(value='test2')

def test_update(self):
with raises(NotImplementedError):
support.TestRepository(self.session).update()
55 changes: 0 additions & 55 deletions tests/watson/db/test_services.py

This file was deleted.

2 changes: 1 addition & 1 deletion watson/db/__init__.py
@@ -1,2 +1,2 @@
# -*- coding: utf-8 -*-
__version__ = '2.0.3'
__version__ = '2.1.0'
156 changes: 156 additions & 0 deletions watson/db/repositories.py
@@ -0,0 +1,156 @@
# -*- coding: utf-8 -*-
import abc
from watson.db.contextmanagers import transaction_scope


class Base(metaclass=abc.ABCMeta):
"""Provides common interactions with the SQLAlchemy session.
Example:
.. code-block:: python
class MyRepository(Base):
__model__ = models.MyModel
# sqlalchemy_session is a reference to a Session object
repo = MyRepository(sqlalchemy_session)
mymodel = repo.new(attr='Value')
print(mymodel.attr) # 'Value'
repo.save(mymodel)
Attributes:
session (Session): The SqlAlchemy session
__model__ (mixed): The model object the server interacts with
"""
session = None
__model__ = None

def __init__(self, session):
"""
Args:
session (Session): The SqlAlchemy session
"""
self.session = session

@property
def query(self):
return self.session.query(self.__model__)

def all(self):
"""
Returns:
list: A list of all model objects
"""
return self.query.all()

def get(self, id, error_on_not_found=False):
"""Retrieve a single object based on it's ID.
Args:
id (int): The primary key of the record
error_on_not_found (bool): Raise an exception if not found
Returns:
mixed: The matching model object
Raises:
Exception when no matching results are found.
"""
obj = self.query.get(id)
if not obj and error_on_not_found:
raise Exception('No matching result found.')
return obj

# Convenience methods

def find(self, **kwargs):
"""Shorthand for the filter_by method.
Should be used when performing query specific operations (such as
bulk deletion)
Args:
kwargs: The fields to search for
"""
return self.query.filter_by(**kwargs)

def first(self, **kwargs):
"""Return the first matching result for the query.
Args:
kwargs: The fields to search for
Returns:
mixed: The object found, or None if nothing was returned
"""
return self.find(**kwargs).first()

def delete(self, model):
"""Deletes a model from the database.
Args:
model (mixed): The model to delete
"""
with transaction_scope(self.session) as session:
session.delete(model)

def delete_all(self, *models):
"""Delete a list of models.
If deleting more than a single model of the same type, then
a Repository.find(**kwargs).delete() should be called (and wrapped in a
transaction_scope) instead.
Args:
models (list): The models to delete
"""
with transaction_scope(self.session) as session:
for model in models:
session.delete(model)

def new(self, **kwargs):
"""Creates a new instance of the model object
Args:
kwargs (mixed): The initial values for the model
Returns:
mixed: The newly created model
"""
return self.__model__(**kwargs)

def save(self, model):
"""Add the model to the session and save it to the database.
Args:
model (mixed): The object to save
Returns:
mixed: The saved model
"""
with transaction_scope(self.session) as session:
session.add(model)
return model

def save_all(self, *models):
"""Save a list of models.
Args:
models (list, tuple): The models to save
"""
with transaction_scope(self.session) as session:
for model in models:
session.add(model)
return True

def count(self):
"""Returns the total number of model objects
Return:
int
"""
return self.query.count()

def update(self, **kwargs):
raise NotImplementedError()

0 comments on commit bd3115d

Please sign in to comment.