Skip to content

Commit

Permalink
Merge pull request #82 from pstch/develop
Browse files Browse the repository at this point in the history
v0.9.5 : Generic URL arguments, better arguments and complete documentation
  • Loading branch information
Hugo Geoffroy committed Jul 29, 2014
2 parents 35ee55c + 0eed9b9 commit 7e599b3
Show file tree
Hide file tree
Showing 34 changed files with 1,298 additions and 216 deletions.
4 changes: 0 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ python:
- "3.4"
env:
- DJANGO=1.6 DJANGO_SETTINGS_MODULE=tests.settings
cache:
directories:
- /home/travis/build/cache/
- /home/travis/virtualenv/python3.4.0/lib/python3.4/site-packages
install:
- pip install coverage coveralls pep8
- pip install .
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
django-crucrudile [![Build Status](https://travis-ci.org/pstch/django-crucrudile.svg?branch=crucrudile)](https://travis-ci.org/pstch/django-crucrudile) [![Coverage Status](https://coveralls.io/repos/pstch/django-crucrudile/badge.png?branch=crucrudile)](https://coveralls.io/r/pstch/django-crucrudile?branch=crucrudile)
=================

Current release is `0.9.4`. `django-crucrudile` is available in PyPI : https://pypi.python.org/pypi/django-crucrudile/
Current release is `0.9.5`. `django-crucrudile` is available in PyPI : https://pypi.python.org/pypi/django-crucrudile/

`django-crucrudile` is currently only compatible with Python 3 (tested with 3.3 and 3.4). Backporting to Python 2 should be pretty easy (there are no Python 3 "exclusive" features used), and help is welcome for this simple, repetitive task.

Python 2 compatibility is expected for `1.1.0`.

**NOTE :** Development is done on the `develop` branch, and when releasing a new version, merged into the `master` branch

Expand Down
8 changes: 7 additions & 1 deletion django_crucrudile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@
The documentation can also be viewed online, at
https://django-crucrudile.readthedocs.org/en/master/.
Versionning
-----------
Starting from version ``0.9.5``, this package uses semantic version
(http://semver.org).
"""
__title__ = 'django-crucrudile'
__description__ = 'Django URL routing classes',

__version__ = '0.9.4'
__version__ = '0.9.5'

__author__ = 'Hugo Geoffroy'
__author_email__ = 'hugo@pstch.net'
Expand Down
12 changes: 8 additions & 4 deletions django_crucrudile/entities/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,21 @@ def get_str_tree(self, patterns_kwargs=None,
>>> router = Router(generic=True)
>>>
>>> router.register(TestModel)
>>> router.register(TestModel) is not None
True
>>> print(router.get_str_tree())
... # doctest: +NORMALIZE_WHITESPACE
- Router @ ^
- GenericModelRouter testmodel @ ^testmodel/
- testmodel-list-redirect @ ^$ RedirectView
- testmodel-delete @ ^delete$ DeleteView
- testmodel-update @ ^update$ UpdateView
- testmodel-delete @ ^delete/(?P<pk>\d+)$ DeleteView
- testmodel-delete @ ^delete/(?P<slug>[\w-]+)$ DeleteView
- testmodel-update @ ^update/(?P<pk>\d+)$ UpdateView
- testmodel-update @ ^update/(?P<slug>[\w-]+)$ UpdateView
- testmodel-create @ ^create$ CreateView
- testmodel-detail @ ^detail$ DetailView
- testmodel-detail @ ^detail/(?P<pk>\d+)$ DetailView
- testmodel-detail @ ^detail/(?P<slug>[\w-]+)$ DetailView
- testmodel-list @ ^list$ ListView
"""
Expand Down
142 changes: 113 additions & 29 deletions django_crucrudile/entities/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
mean.
"""
from collections import OrderedDict
from abc import ABCMeta

__all__ = ['provides', 'EntityStoreMetaclass', 'EntityStore']
Expand All @@ -43,7 +44,7 @@ def provides(provided, **kwargs):
:argument provided: Class (or object) to register in the base store. This
can be an object since it may be transformed
by :func:`EntityStore.register_apply_map`d
by :func:`EntityStore.register_apply_map`
:type provided: object
"""
Expand All @@ -58,20 +59,15 @@ def register_obj_in_store(router):
return register_obj_in_store


class EntityStoreMetaclass(ABCMeta):
"""EntityStoreMetaclass allows :class:`EntityStore` to use a different
:attr:`_base_store` store (list instance) for each class definitions
class BaseStoreMetaclassMixin(type):
"""Allows :class:`EntityStore` to use different
:attr:`_base_register_map` and :attr:`_base_register_map`
class-level mappings (list instance) for each class definitions.
(``cls`` instantiation)
.. note::
Subclasses :class:`abc.ABCMeta` because it will be used as the
metaclass for an entity, and entity are abstract classes, which
needs the :class:`âbc.ABCMeta` base class.
.. inheritance-diagram:: BaseStoreMetaclassMixin
.. inheritance-diagram:: EntityStoreMetaclass
>>> class Store(metaclass=EntityStoreMetaclass):
>>> class Store(metaclass=BaseStoreMetaclassMixin):
... pass
>>>
>>> class FailStore:
Expand All @@ -83,9 +79,6 @@ class EntityStoreMetaclass(ABCMeta):
>>> class FailNewStore(FailStore):
... pass
>>> (NewStore._base_store is
... Store._base_store)
False
>>> (NewStore._base_register_map is
... Store._base_register_map)
False
Expand All @@ -98,21 +91,26 @@ class EntityStoreMetaclass(ABCMeta):
True
"""
_base_store = []
_base_register_map = {}
_base_register_class_map = {}
_base_register_map = OrderedDict()
_base_register_class_map = OrderedDict()
"""
:attribute _base_store: Routed entity class store, instantiated
upon Router instantiation.
:type _base_store: list
:attribute _base_register_map: Base register map (see
:func:`get_register_map` and
:func:`register`)
:func:`EntityStore.get_register_map`
and
:func:`EntityStore.register`). Use
OrderedDict because mappings should
be used in the order they are added
(as multiple mappings may match).
:type _base_store: dict
:attribute _base_register_class_map: Base register class map (see
:func:`get_register_class_map`
and :func:`register_class`)
:type _base_store: dict
:func:`EntityStore.get_register_class_map`
and
:func:`EntityStore.register_class`).
Use OrderedDict because
mappings should be used in
the order they are added (as
multiple mappings may match).
:type _base_register_class_map: dict
"""
def __init__(cls, name, bases, attrs):
"""Replace :attr:`_base_store`, :attr:`_base_register_map` and
Expand All @@ -128,15 +126,89 @@ def __init__(cls, name, bases, attrs):
.. seealso::
For doctests that use this member, see
:class:`django_crucrudile.entities.store.EntityStoreMetaclass`
:class:`django_crucrudile.entities.store.BaseStoreMetaclassMixin`
"""
super().__init__(name, bases, attrs)
cls._base_register_map = cls._base_register_map.copy()
cls._base_register_class_map = cls._base_register_class_map.copy()


class EntityStoreMetaclassMixin(type):
"""Allows :class:`EntityStore` to use a different
:attr:`_base_store` store (list instance) for each class
definitions (``cls`` instantiation)
.. inheritance-diagram:: EntityStoreMetaclassMixin
>>> class Store(metaclass=EntityStoreMetaclassMixin):
... pass
>>>
>>> class FailStore:
... _fail_store = []
>>>
>>> class NewStore(Store):
... pass
>>>
>>> class FailNewStore(FailStore):
... pass
>>> (NewStore._base_store is
... Store._base_store)
False
>>> (FailNewStore._fail_store is
... FailStore._fail_store)
True
"""
_base_store = []
"""
:attribute _base_store: Routed entity class store, instantiated
upon Router instantiation.
:type _base_store: list
"""
def __init__(cls, name, bases, attrs):
"""Replace :attr:`_base_store`, :attr:`_base_register_map` and
:attr:`_base_register_class_map` by copies of themselves
:argument name: New class name
:type name: str
:argument bases: New class bases
:type bases: tuple
:argument attrs: New class attributes
:type attrs: dict
.. seealso::
For doctests that use this member, see
:class:`django_crucrudile.entities.store.EntityStoreMetaclassMixin`
"""
super().__init__(name, bases, attrs)
cls._base_store = cls._base_store.copy()


class EntityStoreMetaclass(EntityStoreMetaclassMixin,
BaseStoreMetaclassMixin,
ABCMeta):
"""Use the entity store and base store metaclass mixins, that handle
creating a new instance of the stores for each class definition.
See :class:`EntityStoreMetaclassMixin` and
:class:`BaseStoreMetaclassMixin` for more information.
.. note::
Also subclasses :class:`abc.ABCMeta` because it will be used as
the metaclass for an entity, and entity are abstract classes,
which needs the :class:`âbc.ABCMeta` base class.
.. inheritance-diagram:: EntityStoreMetaclass
"""


class EntityStore(metaclass=EntityStoreMetaclass):
"""Provides an entity store, and a :func:`register` method that
registers entities in the entity store.
Expand Down Expand Up @@ -373,13 +445,19 @@ def get_register_class_map(self):
The base implementation returns a copy of the stored mapping,
so overriding implementations may append to the return value.
.. warning::
The matching mapping will be used. This is why this method
must return an :class:`collections.OrderedDict`, so that
the adding order is used.
.. seealso::
For doctests that use this member, see
:func:`django_crucrudile.entities.store.EntityStore.register_class`
"""
return dict(self._base_register_class_map)
return OrderedDict(self._base_register_class_map)

@classmethod
def get_register_class_map_kwargs(cls):
Expand All @@ -406,13 +484,19 @@ def get_register_map(self):
The base implementation returns a copy of the stored mapping,
so overriding implementations may append to the return value.
.. warning::
The matching mapping will be used. This is why this method
must return an :class:`collections.OrderedDict`, so that
the adding order is used.
.. seealso::
For doctests that use this member, see
:func:`django_crucrudile.entities.store.EntityStore.register`
"""
return dict(self._base_register_map)
return OrderedDict(self._base_register_map)

def get_register_map_kwargs(self):
"""Arguments passed when applying register map, in :func:`register`
Expand Down
Loading

0 comments on commit 7e599b3

Please sign in to comment.