Browse Source

more work on documentation

I still don't like ReStructured Text
master
Holger Frey 7 years ago
parent
commit
b1870658a9
  1. 14
      README.rst
  2. 10
      ordr2/models/__init__.py
  3. 1
      ordr2/models/meta.py
  4. 59
      ordr2/resources/__init__.py
  5. 2
      ordr2/views/errors.py
  6. 1
      ordr2/views/public.py
  7. 24
      tests/resources/__init__.py

14
README.rst

@ -2,7 +2,17 @@
Ordr2 - CPI Ordering System Ordr2 - CPI Ordering System
=========================== ===========================
This is a complete rewrite of our current `ordering system`_. In our chair at the University of Freiburg there are about forty people working
in the lab but only four of them are accredited for the SAP ordering system
used by the university - the rest has to order through them. This leads to
a quite large amount of mails, post-its and calls per purchaser. To give this
some better structure, our small ordering system was developed. It is actually
a 'would-you-please-order-for-me-system' and disconnected from the upstream
system.
This is a complete rewrite of the CPI `ordering system`_ originally written in
PHP.
Goals Goals
----- -----
@ -30,7 +40,7 @@ style routing instead of the more widely spread url dispatch method. This
decision was made because: decision was made because:
* the starter of this project likes this kind of routing * the starter of this project likes this kind of routing
* it eliminates the need of defining routes * it eliminates the need of defining routes separately
* `row level security`_ is easy to implement since traversal works with * `row level security`_ is easy to implement since traversal works with
resources from the start. resources from the start.

10
ordr2/models/__init__.py

@ -1,3 +1,9 @@
''' models (sub)package for ordr2
prepare the sqlalchemy models for the database
'''
from sqlalchemy import engine_from_config from sqlalchemy import engine_from_config
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers from sqlalchemy.orm import configure_mappers
@ -45,7 +51,9 @@ def get_tm_session(session_factory, transaction_manager):
''' '''
dbsession = session_factory() dbsession = session_factory()
zope.sqlalchemy.register( zope.sqlalchemy.register(
dbsession, transaction_manager=transaction_manager) dbsession,
transaction_manager=transaction_manager
)
return dbsession return dbsession

1
ordr2/models/meta.py

@ -12,5 +12,6 @@ NAMING_CONVENTION = {
'pk': 'pk_%(table_name)s' 'pk': 'pk_%(table_name)s'
} }
# setup metadata conventions and base declarative class
metadata = MetaData(naming_convention=NAMING_CONVENTION) metadata = MetaData(naming_convention=NAMING_CONVENTION)
Base = declarative_base(metadata=metadata) Base = declarative_base(metadata=metadata)

59
ordr2/resources/__init__.py

@ -1,11 +1,30 @@
''' Resources (sub) package, used to connect URLs to views ''' ''' Resources (sub) package, used to connect URLs to views '''
from pyramid.security import Allow, Everyone, DENY_ALL
class BaseResource(object): class BaseResource(object):
''' '''
Base resouce class for location aware resources Base resouce class for location aware resources
establishes a simple dict like interface for returning child resources :param str name:
url path segment that identifies this resource in its lineage
:param parent:
parent resource
:type parent:
ordr2.resources.BaseResource
:param model:
(optional) a model instance represented by this resource,
e.g. a database entry
Provides a dict like interface for retrieving child resources used by
traversal style routing in the Pyramid web framework.
The ``nodes`` property is a dictionary to to match the next url path
segment in traversal to a child class.
For example: to return an AccountResouce when the next path segment is
'account' use ``nodes = {'account': AccountResource}``.
''' '''
# __name__ and __parent__ properties for location awareness # __name__ and __parent__ properties for location awareness
@ -17,22 +36,19 @@ class BaseResource(object):
# 'account' use nodes = {'account': AccountResource} # 'account' use nodes = {'account': AccountResource}
nodes = {} nodes = {}
def __init__(self, name, parent): def __init__(self, name, parent, model=None):
''' Create a base resource ''' Create a base resource '''
:param str name:
url path segment that identifies this resource in its lineage
:param parent:
parent resource in the lineage
:type parent:
ordr2.resources.BaseResource
'''
self.__name__ = name self.__name__ = name
self.__parent__ = parent self.__parent__ = parent
self.request = parent.request self.request = parent.request
self.model = model
def __acl__(self):
''' access controll list for the resource '''
return [DENY_ALL]
def __getitem__(self, key): def __getitem__(self, key):
''' provides a dict like interface to access child resources ''' provides the dict like interface to access child resources
:param str key: :param str key:
path segment for a child resource path segment for a child resource
@ -44,20 +60,23 @@ class BaseResource(object):
class RootResource(BaseResource): class RootResource(BaseResource):
''' The root resource for the application ''' ''' The root resource for the application
def __init__(self, request): :param request:
''' Create the root resource the current request object
:type request:
pyramid.request.Request
'''
:param request: def __init__(self, request):
the current request object ''' Create the root resource '''
:type request:
pyramid.request.Request
'''
self.__name__ = None self.__name__ = None
self.__parent__ = None self.__parent__ = None
self.request = request self.request = request
def __acl__(self):
''' access controll list for the resource '''
return [(Allow, Everyone, 'view')]
def includeme(config): def includeme(config):

2
ordr2/views/errors.py

@ -1,3 +1,5 @@
''' custom views for error messages '''
from pyramid.view import notfound_view_config from pyramid.view import notfound_view_config

1
ordr2/views/public.py

@ -13,4 +13,5 @@ from ..models import MyModel
renderer='ordr2:templates/mytemplate.jinja2' renderer='ordr2:templates/mytemplate.jinja2'
) )
def index(context, request): def index(context, request):
''' the start page '''
return {} return {}

24
tests/resources/__init__.py

@ -8,11 +8,23 @@ def test_base_resource_init():
from ordr2.resources import BaseResource, RootResource from ordr2.resources import BaseResource, RootResource
root = RootResource('request object') root = RootResource('request object')
resource = BaseResource('resource name', root) resource = BaseResource('resource name', root, 'model instance')
assert resource.__name__ == 'resource name' assert resource.__name__ == 'resource name'
assert resource.__parent__ == root assert resource.__parent__ == root
assert resource.request == 'request object' assert resource.request == 'request object'
assert resource.model == 'model instance'
def test_base_resource_acl():
''' test __acl__ function of base resource '''
from ordr2.resources import BaseResource, RootResource
from pyramid.security import DENY_ALL
root = RootResource('request object')
resource = BaseResource('resource name', root, 'model instance')
assert resource.__acl__() == [ DENY_ALL ]
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -43,3 +55,13 @@ def test_root_resource_init():
assert resource.__name__ is None assert resource.__name__ is None
assert resource.__parent__ is None assert resource.__parent__ is None
assert resource.request == 'request object' assert resource.request == 'request object'
def test_root_resource_acl():
''' test __acl__ function of root resource '''
from ordr2.resources import RootResource
from pyramid.security import Allow, Everyone
root = RootResource('request object')
assert root.__acl__() == [ (Allow, Everyone, 'view') ]