initial commit
initial commit

file:b/.idea/other.xml (new)
--- /dev/null
+++ b/.idea/other.xml
@@ -1,1 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PyDocumentationSettings">
+    <option name="myDocStringFormat" value="Plain" />
+  </component>
+</project>
 
+

--- /dev/null
+++ b/.idea/testrunner.xml
@@ -1,1 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="TestRunnerService">
+    <option name="projectConfiguration" value="Unittests" />
+    <option name="PROJECT_TEST_RUNNER" value="Unittests" />
+  </component>
+</project>
 
+

file:a/README.rst -> file:b/README.rst
--- a/README.rst
+++ b/README.rst
@@ -1,80 +1,21 @@
-This CKAN Extension demonstrates some common patterns for customising a CKAN instance.
+This CKAN Extension customises a CKAN instance for the hosting of data.gov.au.
 
 It comprises:
 
-* A CKAN Extension "plugin" at ``ckanext/example/plugin.py`` which, when
+* A CKAN Extension "plugin" at ``ckanext/datagovau/plugin.py`` which, when
   loaded, overrides various settings in the core ``ini``-file to provide:
-
-  * A path to local customisations of the core templates and stylesheets
-  * A "stream filter" that replaces arbitrary strings in rendered templates
-  * A "route" to override and extend the default behaviour of a core CKAN page
-
-* A custom Pylons controller for overriding some core CKAN behaviour
-
-* A custom Package edit form
-
-* A custom Group edit form
-
-* A plugin that allows for custom forms to be used for datasets based on 
-  their "type".
-
-* A custom User registration and edition form
-
-* Some simple template customisations
+  * A path to local customisations of the core templates and available licenses database
+  * A custom Package edit form
+  * A custom n3/rdf output format
 
 Installation
 ============
 
 To install this package, from your CKAN virtualenv, run the following from your CKAN base folder (e.g. ``pyenv/``)::
 
-  pip install -e git+https://github.com/okfn/ckanext-example#egg=ckanext-example
+  pip install -e git+https://github.com/okfn/ckanext-datagovau#egg=ckanext-datagovau
 
-Then activate it by setting ``ckan.plugins = example`` in your main ``ini``-file.
-
-Orientation
-===========
-
-* Examine the source code, starting with ``ckanext/example/plugin.py``
-
-* To understand the nuts and bolts of this file, which is a CKAN
-  *Extension*, read in conjunction with the "Extension
-  documentation": http://docs.ckan.org/en/latest/extensions.html
-
-* One thing the extension does is set the values of
-  ``extra_public_paths`` and ``extra_template_paths`` in the CKAN
-  config, which are "documented
-  here": http://docs.ckan.org/en/latest/configuration.html#extra-template-paths
-
-* These are set to point at directories within
-  ``ckanext/example/theme/`` (in this package).  Here we:
-   * override the home page HTML ``ckanext/example/theme/templates/home/index.html``
-   * provide some extra style by serving ``extra.css`` (which is loaded using the ``ckan.template_head_end`` option
-   * customise the navigation and header of the main template in the file ``layout.html``.
-
-  The latter file is a great place to make global theme alterations.
-  It uses the _layout template_ pattern "described in the Genshi
-  documentation":http://genshi.edgewall.org/wiki/GenshiTutorial#AddingaLayoutTemplate.
-  This allows you to use Xpath selectors to override snippets of HTML
-  globally.
-
-* The custom package edit form at ``package_form.py`` follows a deprecated
-  way to make a form (using FormAlchemy). This part of the Example Theme needs
-  updating. In the meantime, follow the instructions at: 
-  http://docs.ckan.org/en/latest/forms.html
-
-Example Tags With Vocabularies
-==============================
-
-To add example tag vocabulary data to the database, from the ckanext-example directory run:
-
-::
-
-    paster example create-example-vocabs -c <path to your ckan config file>
-
-This data can be removed with
-
-::
-
-    paster example clean -c <path to your ckan config file>
+Then activate it by setting ``ckan.plugins = datagovau`` in your main ``ini``-file.
 
 
+

--- /dev/null
+++ b/ckanext-datagovau.iml
@@ -1,1 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
 
+

--- /dev/null
+++ b/ckanext/datagovau/templates/package/read_base.html
@@ -1,1 +1,15 @@
+{% ckan_extends %}
 
+{% block subtitle %}{{ pkg.title or pkg.name }}{% endblock %}
+
+{% block links -%}
+{{ super() }}
+<link rel="lol" type="test"/>
+{% endblock -%}
+
+{% block head_extras -%}
+{{ super() }}
+<meta property="og:gon" content="lol">
+{% endblock -%}
+
+

--- a/ckanext/example/__init__.py
+++ /dev/null
@@ -1,2 +1,1 @@
-# package
 

--- a/ckanext/example/commands.py
+++ /dev/null
@@ -1,83 +1,1 @@
-from ckan import model
-from ckan.lib.cli import CkanCommand
-from ckan.logic import get_action, NotFound
-import forms
 
-import logging
-log = logging.getLogger()
-
-
-class ExampleCommand(CkanCommand):
-    '''
-    CKAN Example Extension
-
-    Usage::
-
-        paster example create-example-vocabs -c <path to config file>
-
-        paster example clean -c <path to config file>
-            - Remove all data created by ckanext-example
-
-    The commands should be run from the ckanext-example directory.
-    '''
-    summary = __doc__.split('\n')[0]
-    usage = __doc__
-
-    def command(self):
-        '''
-        Parse command line arguments and call appropriate method.
-        '''
-        if not self.args or self.args[0] in ['--help', '-h', 'help']:
-            print ExampleCommand.__doc__
-            return
-
-        cmd = self.args[0]
-        self._load_config()
-
-        if cmd == 'create-example-vocabs':
-            self.create_example_vocabs()
-        if cmd == 'clean':
-            self.clean()
-        else:
-            log.error('Command "%s" not recognized' % (cmd,))
-
-    def create_example_vocabs(self):
-        '''
-        Adds example vocabularies to the database if they don't already exist.
-        '''
-        user = get_action('get_site_user')({'model': model, 'ignore_auth': True}, {})
-        context = {'model': model, 'session': model.Session, 'user': user['name']}
-
-        try:
-            data = {'id': forms.GENRE_VOCAB}
-            get_action('vocabulary_show')(context, data)
-            log.info("Example genre vocabulary already exists, skipping.")
-        except NotFound:
-            log.info("Creating vocab %s" % forms.GENRE_VOCAB)
-            data = {'name': forms.GENRE_VOCAB}
-            vocab = get_action('vocabulary_create')(context, data)
-            log.info("Adding tag %s to vocab %s" % ('jazz', forms.GENRE_VOCAB))
-            data = {'name': 'jazz', 'vocabulary_id': vocab['id']}
-            get_action('tag_create')(context, data)
-            log.info("Adding tag %s to vocab %s" % ('soul', forms.GENRE_VOCAB))
-            data = {'name': 'soul', 'vocabulary_id': vocab['id']}
-            get_action('tag_create')(context, data)
-
-        try:
-            data = {'id': forms.COMPOSER_VOCAB}
-            get_action('vocabulary_show')(context, data)
-            log.info("Example composer vocabulary already exists, skipping.")
-        except NotFound:
-            log.info("Creating vocab %s" % forms.COMPOSER_VOCAB)
-            data = {'name': forms.COMPOSER_VOCAB}
-            vocab = get_action('vocabulary_create')(context, data)
-            log.info("Adding tag %s to vocab %s" % ('Bob Mintzer', forms.COMPOSER_VOCAB))
-            data = {'name': 'Bob Mintzer', 'vocabulary_id': vocab['id']}
-            get_action('tag_create')(context, data)
-            log.info("Adding tag %s to vocab %s" % ('Steve Lewis', forms.COMPOSER_VOCAB))
-            data = {'name': 'Steve Lewis', 'vocabulary_id': vocab['id']}
-            get_action('tag_create')(context, data)
-
-    def clean(self):
-        log.error("Clean command not yet implemented")
-

--- a/ckanext/example/controller.py
+++ /dev/null
@@ -1,53 +1,1 @@
-import sys
-from ckan.lib.base import request
-from ckan.lib.base import c, g, h
-from ckan.lib.base import model
-from ckan.lib.base import render
-from ckan.lib.base import _
 
-from ckan.lib.navl.validators import not_empty
-
-from ckan.controllers.user import UserController
-
-
-class CustomUserController(UserController):
-    """This controller is an example to show how you might extend or
-    override core CKAN behaviour from an extension package.
-
-    It overrides 2 method hooks which the base class uses to create the
-    validation schema for the creation and editing of a user; to require
-    that a fullname is given.
-    """
-
-    new_user_form = 'user/register.html'
-
-    def _add_requires_full_name_to_schema(self, schema):
-        """
-        Helper function that modifies the fullname validation on an existing schema
-        """
-        schema['fullname'] = [not_empty, unicode]
-
-    def _new_form_to_db_schema(self):
-        """
-        Defines a custom schema that requires a full name to be supplied
-
-        This method is a hook that the base class calls for the validation
-        schema to use when creating a new user.
-        """
-        schema = super(CustomUserController, self)._new_form_to_db_schema()
-        self._add_requires_full_name_to_schema(schema)
-        return schema
-
-    def _edit_form_to_db_schema(self):
-        """
-        Defines a custom schema that requires a full name cannot be removed
-        when editing the user.
-
-        This method is a hook that the base class calls for the validation
-        schema to use when editing an exiting user.
-        """
-        schema = super(CustomUserController, self)._edit_form_to_db_schema()
-        self._add_requires_full_name_to_schema(schema)
-        return schema
-
-

--- a/ckanext/example/forms.py
+++ /dev/null
@@ -1,268 +1,1 @@
-import os
-import logging
-from ckan.authz import Authorizer
-from ckan.logic.converters import convert_to_extras,\
-    convert_from_extras, convert_to_tags, convert_from_tags, free_tags_only
-from ckan.logic import get_action, NotFound
-from ckan.logic.schema import package_form_schema, group_form_schema
-from ckan.lib.base import c, model
-from ckan.plugins import IDatasetForm, IGroupForm, IConfigurer
-from ckan.plugins import IGenshiStreamFilter
-from ckan.plugins import implements, SingletonPlugin
-from ckan.lib.navl.validators import ignore_missing, keep_extras, not_empty
-import ckan.lib.plugins
 
-log = logging.getLogger(__name__)
-
-GENRE_VOCAB = u'genre_vocab'
-COMPOSER_VOCAB = u'composer_vocab'
-
-
-class ExampleGroupForm(SingletonPlugin):
-    """This plugin demonstrates how a class packaged as a CKAN
-    extension might extend CKAN behaviour by providing custom forms
-    based on the type of a Group.
-
-    In this case, we implement two extension interfaces to provide custom
-    forms for specific types of group.
-
-      - ``IConfigurer`` allows us to override configuration normally
-        found in the ``ini``-file.  Here we use it to specify where the
-        form templates can be found.
-
-      - ``IGroupForm`` allows us to provide a custom form for a dataset
-        based on the 'type' that may be set for a group.  Where the
-        'type' matches one of the values in group_types then this
-        class will be used.
-    """
-    implements(IGroupForm, inherit=True)
-    implements(IConfigurer, inherit=True)
-
-    def update_config(self, config):
-        """
-        This IConfigurer implementation causes CKAN to look in the
-        ```templates``` directory when looking for the group_form()
-        """
-        here = os.path.dirname(__file__)
-        rootdir = os.path.dirname(os.path.dirname(here))
-        template_dir = os.path.join(rootdir, 'ckanext',
-                                    'example', 'theme', 'templates')
-        config['extra_template_paths'] = ','.join([template_dir,
-                config.get('extra_template_paths', '')])
-
-    def group_form(self):
-        """
-        Returns a string representing the location of the template to be
-        rendered.  e.g. "forms/group_form.html".
-        """
-        return 'forms/group_form.html'
-
-    def group_types(self):
-        """
-        Returns an iterable of group type strings.
-
-        If a request involving a group of one of those types is made, then
-        this plugin instance will be delegated to.
-
-        There must only be one plugin registered to each group type.  Any
-        attempts to register more than one plugin instance to a given group
-        type will raise an exception at startup.
-        """
-        return ["testgroup"]
-
-    def is_fallback(self):
-        """
-        Returns true iff this provides the fallback behaviour, when no other
-        plugin instance matches a group's type.
-
-        As this is not the fallback controller we should return False.  If
-        we were wanting to act as the fallback, we'd return True
-        """
-        return False
-
-    def form_to_db_schema(self):
-        """
-        Returns the schema for mapping group data from a form to a format
-        suitable for the database.
-        """
-        return group_form_schema()
-
-    def db_to_form_schema(self):
-        """
-        Returns the schema for mapping group data from the database into a
-        format suitable for the form (optional)
-        """
-        return {}
-
-    def check_data_dict(self, data_dict):
-        """
-        Check if the return data is correct.
-
-        raise a DataError if not.
-        """
-
-    def setup_template_variables(self, context, data_dict):
-        """
-        Add variables to c just prior to the template being rendered.
-        """
-
-
-class ExampleDatasetForm(SingletonPlugin, ckan.lib.plugins.DefaultDatasetForm):
-    """This plugin demonstrates how a theme packaged as a CKAN
-    extension might extend CKAN behaviour.
-
-    In this case, we implement three extension interfaces:
-
-      - ``IConfigurer`` allows us to override configuration normally
-        found in the ``ini``-file.  Here we use it to specify where the
-        form templates can be found.
-      - ``IDatasetForm`` allows us to provide a custom form for a dataset
-        based on the type_name that may be set for a package.  Where the
-        type_name matches one of the values in package_types then this
-        class will be used.
-    """
-    implements(IDatasetForm, inherit=True)
-    implements(IConfigurer, inherit=True)
-    implements(IGenshiStreamFilter, inherit=True)
-
-    def update_config(self, config):
-        """
-        This IConfigurer implementation causes CKAN to look in the
-        ```templates``` directory when looking for the package_form()
-        """
-        here = os.path.dirname(__file__)
-        rootdir = os.path.dirname(os.path.dirname(here))
-        template_dir = os.path.join(rootdir, 'ckanext',
-                                    'example', 'theme', 'templates')
-        config['extra_template_paths'] = ','.join([template_dir,
-                config.get('extra_template_paths', '')])
-
-    def package_form(self):
-        """
-        Returns a string representing the location of the template to be
-        rendered.  e.g. "package/new_package_form.html".
-        """
-        return 'forms/dataset_form.html'
-
-    def is_fallback(self):
-        """
-        Returns true iff this provides the fallback behaviour, when no other
-        plugin instance matches a package's type.
-
-        As this is not the fallback controller we should return False.  If
-        we were wanting to act as the fallback, we'd return True
-        """
-        return True
-
-    def package_types(self):
-        """
-        Returns an iterable of package type strings.
-
-        If a request involving a package of one of those types is made, then
-        this plugin instance will be delegated to.
-
-        There must only be one plugin registered to each package type.  Any
-        attempts to register more than one plugin instance to a given package
-        type will raise an exception at startup.
-        """
-        return ["example_dataset_form"]
-
-    def setup_template_variables(self, context, data_dict=None):
-        """
-        Adds variables to c just prior to the template being rendered that can
-        then be used within the form
-        """
-        c.licences = [('', '')] + model.Package.get_license_options()
-        c.publishers = [('Example publisher', 'Example publisher 2')]
-        c.is_sysadmin = Authorizer().is_sysadmin(c.user)
-        c.resource_columns = model.Resource.get_columns()
-        try:
-            c.genre_tags = get_action('tag_list')(context, {'vocabulary_id': GENRE_VOCAB})
-            c.composer_tags = get_action('tag_list')(context, {'vocabulary_id': COMPOSER_VOCAB})
-        except NotFound:
-            c.vocab_tags = None
-            c.composer_tags = None
-
-        ## This is messy as auths take domain object not data_dict
-        pkg = context.get('package') or c.pkg
-        if pkg:
-            c.auth_for_change_state = Authorizer().am_authorized(
-                c, model.Action.CHANGE_STATE, pkg)
-
-    def form_to_db_schema(self):
-        """
-        Returns the schema for mapping package data from a form to a format
-        suitable for the database.
-        """
-        schema = package_form_schema()
-        schema.update({
-            'published_by': [ignore_missing, unicode, convert_to_extras],
-            'genre_tags': [ignore_missing, convert_to_tags(GENRE_VOCAB)],
-            'composer_tags': [ignore_missing, convert_to_tags(COMPOSER_VOCAB)]
-        })
-        return schema
-
-    def db_to_form_schema(self):
-        """
-        Returns the schema for mapping package data from the database into a
-        format suitable for the form (optional)
-        """
-        schema = package_form_schema()
-        schema.update({
-            'tags': {
-                '__extras': [keep_extras, free_tags_only]
-            },
-            'genre_tags_selected': [
-                convert_from_tags(GENRE_VOCAB), ignore_missing
-            ],
-            'composer_tags_selected': [
-                convert_from_tags(COMPOSER_VOCAB), ignore_missing
-            ],
-            'published_by': [convert_from_extras, ignore_missing],
-        })
-        schema['groups'].update({
-            'name': [not_empty, unicode],
-            'title': [ignore_missing]
-        })
-        return schema
-
-    def check_data_dict(self, data_dict):
-        """
-        Check if the return data is correct and raises a DataError if not.
-        """
-        return
-
-    def filter(self, stream):
-        # Add vocab tags to the bottom of the sidebar.
-        from pylons import request
-        from genshi.filters import Transformer
-        from genshi.input import HTML
-        routes = request.environ.get('pylons.routes_dict')
-        context = {'model': model}
-        if routes.get('controller') == 'package' \
-            and routes.get('action') == 'read':
-                for vocab in (GENRE_VOCAB, COMPOSER_VOCAB):
-                    try:
-                        vocab = get_action('vocabulary_show')(context, {'id': vocab})
-                        vocab_tags = [t for t in c.pkg_dict.get('tags', [])
-                                      if t.get('vocabulary_id') == vocab['id']]
-                    except NotFound:
-                        vocab_tags = None
-
-                    if not vocab_tags:
-                        continue
-
-                    html = '<li class="sidebar-section">'
-                    if vocab['name'] == GENRE_VOCAB:
-                        html = html + '<h3>Musical Genre</h3>'
-                    elif vocab['name'] == COMPOSER_VOCAB:
-                        html = html + '<h3>Composer</h3>'
-                    html = html + '<ul class="tags clearfix">'
-                    for tag in vocab_tags:
-                        html = html + '<li>%s</li>' % tag['name']
-                    html = html + "</ul></li>"
-                    stream = stream | Transformer(
-                        "//div[@id='sidebar']//ul[@class='widget-list']"
-                    ).append(HTML(html))
-        return stream
-

--- a/ckanext/example/package_form.py
+++ /dev/null
@@ -1,40 +1,1 @@
-from sqlalchemy.util import OrderedDict
-from pylons.i18n import _
 
-from ckan.forms import common
-from ckan.forms import package
-
-
-# Setup the fieldset
-def build_example_form(is_admin=False,
-                       user_editable_groups=None,
-                       **kwargs):
-    """Customise the core CKAN dataset editing form by adding a new
-    field "temporal coverage", and changing the layout of the core
-    fields.
-    """
-    # Restrict fields
-    builder = package.build_package_form(
-        user_editable_groups=user_editable_groups)
-
-    # Extra fields
-    builder.add_field(common.DateRangeExtraField('temporal_coverage'))
-
-    # Layout
-    field_groups = OrderedDict([
-        (_('Customised Basic information'), ['title', 'name', 'url',
-                                  'notes', 'tags']),
-        (_('Details'), ['author', 'author_email', 'groups',
-                        'maintainer', 'maintainer_email',
-                        'license_id', 'temporal_coverage' ]),
-        (_('Resources'), ['resources']),
-        ])
-    builder.set_displayed_fields(field_groups)
-    return builder
-
-
-def get_example_fieldset(is_admin=False, user_editable_groups=None, **kwargs):
-    return build_example_form(is_admin=is_admin,
-                              user_editable_groups=user_editable_groups,
-                              **kwargs).get_fieldset()
-

--- a/ckanext/example/plugin.py
+++ /dev/null
@@ -1,120 +1,1 @@
-import os
-from logging import getLogger
 
-from pylons import request
-from genshi.input import HTML
-from genshi.filters.transform import Transformer
-
-from ckan.plugins import implements, SingletonPlugin
-from ckan.plugins import IConfigurer
-from ckan.plugins import IGenshiStreamFilter
-from ckan.plugins import IRoutes
-
-log = getLogger(__name__)
-
-
-class ExamplePlugin(SingletonPlugin):
-    """This plugin demonstrates how a theme packaged as a CKAN
-    extension might extend CKAN behaviour.
-
-    In this case, we implement three extension interfaces:
-
-      - ``IConfigurer`` allows us to override configuration normally
-        found in the ``ini``-file.  Here we use it to specify the site
-        title, and to tell CKAN to look in this package for templates
-        and resources that customise the core look and feel.
-        
-      - ``IGenshiStreamFilter`` allows us to filter and transform the
-        HTML stream just before it is rendered.  In this case we use
-        it to rename "frob" to "foobar"
-        
-      - ``IRoutes`` allows us to add new URLs, or override existing
-        URLs.  In this example we use it to override the default
-        ``/register`` behaviour with a custom controller
-    """
-    implements(IConfigurer, inherit=True)
-    implements(IGenshiStreamFilter, inherit=True)
-    implements(IRoutes, inherit=True)
-
-    def update_config(self, config):
-        """This IConfigurer implementation causes CKAN to look in the
-        ```public``` and ```templates``` directories present in this
-        package for any customisations.
-
-        It also shows how to set the site title here (rather than in
-        the main site .ini file), and causes CKAN to use the
-        customised package form defined in ``package_form.py`` in this
-        directory.
-        """
-        here = os.path.dirname(__file__)
-        rootdir = os.path.dirname(os.path.dirname(here))
-        our_public_dir = os.path.join(rootdir, 'ckanext',
-                                      'example', 'theme', 'public')
-        template_dir = os.path.join(rootdir, 'ckanext',
-                                    'example', 'theme', 'templates')
-        # set our local template and resource overrides
-        config['extra_public_paths'] = ','.join([our_public_dir,
-                config.get('extra_public_paths', '')])
-        config['extra_template_paths'] = ','.join([template_dir,
-                config.get('extra_template_paths', '')])
-        # add in the extra.css
-        config['ckan.template_head_end'] = config.get('ckan.template_head_end', '') +\
-                                           '<link rel="stylesheet" href="/css/extra.css" type="text/css"> '
-        # set the title
-        config['ckan.site_title'] = "Example CKAN theme"
-        # set the customised package form (see ``setup.py`` for entry point)
-        config['package_form'] = "example_form"
-
-    def filter(self, stream):
-        """Conform to IGenshiStreamFilter interface.
-
-        This example filter renames 'frob' to 'foobar' (this string is
-        found in the custom ``home/index.html`` template provided as
-        part of the package).
-
-        It also adds the chosen JQuery plugin to the page if viewing the
-        dataset edit page (provides a better UX for working with tags with vocabularies)
-        """
-        stream = stream | Transformer('//p[@id="examplething"]/text()')\
-                 .substitute(r'frob', r'foobar')
-
-        routes = request.environ.get('pylons.routes_dict')
-        if routes.get('controller') == 'package' \
-            and routes.get('action') == 'edit':
-                stream = stream | Transformer('head').append(HTML(
-                    '<link rel="stylesheet" href="/css/chosen.css" />'
-                ))
-                stream = stream | Transformer('body').append(HTML(
-                    '''
-                    <script src="/scripts/chosen.jquery.min.js" type="text/javascript"></script>'
-                    <script type="text/javascript">$(".chzn-select").chosen();</script>
-                    '''
-                ))
-
-        return stream
-
-    def before_map(self, map):
-        """This IRoutes implementation overrides the standard
-        ``/user/register`` behaviour with a custom controller.  You
-        might instead use it to provide a completely new page, for
-        example.
-
-        Note that we have also provided a custom register form
-        template at ``theme/templates/user/register.html``.
-        """
-        # Hook in our custom user controller at the points of creation
-        # and edition.
-        map.connect('/user/register',
-                    controller='ckanext.example.controller:CustomUserController',
-                    action='register')
-        map.connect('/user/edit',
-                    controller='ckanext.example.controller:CustomUserController',
-                    action='edit')
-        map.connect('/user/edit/{id:.*}',
-                    controller='ckanext.example.controller:CustomUserController',
-                    action='edit')
-
-        map.connect('/package/new', controller='package_formalchemy', action='new')
-        map.connect('/package/edit/{id}', controller='package_formalchemy', action='edit')
-        return map
-

 Binary files a/ckanext/example/theme/public/css/chosen-sprite.png and /dev/null differ
file:a