Esempio n. 1
0
def extend_entry(entry, dataset):
    entry['dataset'] = dataset.name
    entry['dataset.id'] = dataset.id
    entry = flatten(entry)
    entry['_id'] = dataset.name + '::' + unicode(entry['id'])
    for k, v in entry.items():
        # this is similar to json encoding, but not the same.
        if isinstance(v, datetime.datetime) and not v.tzinfo:
            entry[k] = datetime.datetime(v.year,
                                         v.month,
                                         v.day,
                                         v.hour,
                                         v.minute,
                                         v.second,
                                         tzinfo=tzutc())
        elif '.' in k and isinstance(v, (list, tuple)):
            entry[k] = " ".join([unicode(vi) for vi in v])
        else:
            entry[k] = safe_unicode(entry[k])
        if k.endswith(".name"):
            vk = k[:len(k) - len(".name")]
            entry[vk] = v
        if k.endswith(".label"):
            entry[k + "_str"] = entry[k]
            entry[k + "_facet"] = entry[k]
    for item in PluginImplementations(ISolrSearch):
        entry = item.update_index(entry)
    return entry
Esempio n. 2
0
def render(template_name,
           extra_vars=None,
           form_fill=None,
           form_errors={},
           cache_expire=3600,
           cache_private=False,
           method='xhtml'):

    _setup_cache(cache_expire, cache_private)

    # Pull in extra vars if needed
    globs = extra_vars or {}

    # Second, get the globals
    globs.update(pylons_globals())
    globs['g'] = app_globals
    globs['can'] = can
    globs['_form_errors'] = form_errors

    # Grab a template reference
    template = globs['app_globals'].genshi_loader.load(template_name)

    stream = template.generate(**globs)

    if form_fill is not None:
        filler = HTMLFormFiller(data=form_fill)
        stream = stream | filler

    for item in PluginImplementations(IGenshiStreamFilter):
        stream = item.filter(stream)

    return literal(stream.render(method=method, encoding=None))
Esempio n. 3
0
class HomeController(BaseController):

    extensions = PluginImplementations(IDatasetController)

    def index(self):
        # TODO decide if we want this.
        #featured_dataset = config.get("openspending.default_dataset")
        return render('home/index.html')

    def getinvolved(self):
        return render('home/getinvolved.html')

    def index_subdomain(self):
        if hasattr(c, 'dataset') and c.dataset:
            require.dataset.read(c.dataset)
            redirect(
                url(controller='dataset',
                    action='view',
                    name=c.dataset['name'],
                    sub_domain=None))
        else:
            redirect(url(controller='home', action='index', sub_domain=None))

    def locale(self):
        return_to = request.params.get('return_to', '/')
        locale = request.params.get('locale')
        if locale is not None:
            flash_success(_("Language has been set to: English"))
            set_session_locale(locale)
        else:
            flash_error(_("No language given!"))
        return_to += '&' if '?' in return_to else '?'
        # hack to prevent next page being cached
        return_to += '__cache=%s' % int(random.random() * 100000000)
        redirect(return_to.encode('utf-8'))

    def version(self):
        cwd = os.path.dirname(__file__)
        process = subprocess.Popen('git rev-parse --verify HEAD'.split(' '),
                                   cwd=cwd,
                                   stdout=subprocess.PIPE)
        output = process.communicate()[0]
        if process.returncode == 0:
            return output
        else:
            import openspending.version
            return openspending.version.__version__

    def ping(self):
        from openspending.tasks import ping
        ping.delay()
        flash_success(_("Sent ping!"))
        redirect('/')
Esempio n. 4
0
"""Routes configuration

The more specific and detailed routes should be defined first so they
may take precedent over the more generic routes. For more information
refer to the routes manual at http://routes.groovie.org/docs/
"""
from pylons import config
from routes import Mapper

from openspending.plugins.core import PluginImplementations
from openspending.plugins.interfaces import IRoutes

routing_plugins = PluginImplementations(IRoutes)


def make_map():
    """Create, configure and return the routes Mapper"""
    map = Mapper(directory=config['pylons.paths']['controllers'],
                 always_scan=config['debug'],
                 explicit=True)
    map.minimization = False

    # The ErrorController route (handles 404/500 error pages); it should
    # likely stay at the top, ensuring it can always be resolved
    map.connect('/error/{action}', controller='error')
    map.connect('/error/{action}/{id}', controller='error')
    # The ErrorTestController is used to test our custom error pages.
    map.connect('/_error_test/{action}', controller='error_test')

    # CUSTOM ROUTES HERE
    for plugin in routing_plugins:
Esempio n. 5
0
class DimensionController(BaseController):

    extensions = PluginImplementations(IDimensionController)


    def _get_member(self, dataset, dimension_name, name):
        self._get_dataset(dataset)
        c.dimension = dimension_name
        for dimension in c.dataset.compounds:
            if dimension.name == dimension_name:
                cond = dimension.alias.c.name==name
                members = list(dimension.members(cond, limit=1))
                if not len(members):
                    abort(404, _('Sorry, there is no member named %r')
                            % name)
                c.member = members.pop()
                c.num_entries = dimension.num_entries(cond)
                return
        abort(404, _('Sorry, there is no dimension named %r') % dimension_name)


    def index(self, dataset, format='html'):
        self._get_dataset(dataset)
        if format == 'json':
            return to_jsonp([d.as_dict() for d in c.dataset.dimensions])
        else:
            return render('dimension/index.html')


    def view(self, dataset, dimension, format='html'):
        self._get_dataset(dataset)
        try:
            c.dimension = c.dataset[dimension]
        except KeyError:
            abort(404, _('This is not a dimension'))
        if not isinstance(c.dimension, model.Dimension):
            abort(404, _('This is not a dimension'))

        page = self._get_page('page')
        cache = AggregationCache(c.dataset)
        result = cache.aggregate(drilldowns=[dimension], page=page, 
                                 pagesize=PAGE_SIZE)
        items = result.get('drilldown', [])
        c.values = [(d.get(dimension), d.get('amount')) for d in items]

        if format == 'json':
            return to_jsonp({
                "values": c.values,
                "meta": c.dimension.as_dict()})

        c.page = Page(c.values, page=page,
                      item_count=result['summary']['num_drilldowns'],
                      items_per_page=PAGE_SIZE,
                      presliced_list=True)
        return render('dimension/view.html')


    def member(self, dataset, dimension, name, format="html"):
        self._get_member(dataset, dimension, name)

        handle_request(request, c, c.member, c.dimension)
        if c.view is None:
            self._make_browser()

        for item in self.extensions:
            item.read(c, request, response, c.member)

        if format == 'json':
            return to_jsonp(c.member)
        elif format == 'csv':
            return write_csv([c.member], response)
        else:
            return render('dimension/member.html')


    def entries(self, dataset, dimension, name, format='html'):
        self._get_member(dataset, dimension, name)

        handle_request(request, c, c.member, c.dimension)

        self._make_browser()
        if format == 'json':
            return c.browser.to_jsonp()
        elif format == 'csv':
            return c.browser.to_csv()
        else:
            return render('dimension/entries.html')


    def _make_browser(self):
        url = url_for(controller='dimension', action='entries',
                dataset=c.dataset.name,
                dimension=c.dimension,
                name=c.member['name'])
        c.browser = Browser(c.dataset, request.params, url=url)
        c.browser.filter_by("+%s:\"%s\"" % (c.dimension, c.member['name']))
        c.browser.facet_by_dimensions()
Esempio n. 6
0
class BaseController(WSGIController):

    items = PluginImplementations(IRequest)

    def __call__(self, environ, start_response):
        """Invoke the Controller"""
        # WSGIController.__call__ dispatches to the Controller method
        # the request is routed to. This routing information is
        # available in environ['pylons.routes_dict']
        begin = time()
        try:
            return WSGIController.__call__(self, environ, start_response)
        finally:
            db.session.remove()
            db.session.close()
            log.debug("Request to %s took %sms" %
                      (request.path, int((time() - begin) * 1000)))

    def __before__(self, action, **params):
        account_name = request.environ.get('REMOTE_USER', None)
        if account_name:
            c.account = model.Account.by_name(account_name)
        else:
            c.account = None

        i18n.handle_request(request, c)
        c.state = session.get('state', {})

        c.q = ''
        c.items_per_page = int(request.params.get('items_per_page', 20))
        c.datasets = model.Dataset.all_by_account(c.account)
        c.dataset = None
        self._detect_dataset_subdomain()

        for item in self.items:
            item.before(request, c)

    def __after__(self):
        if session.get('state', {}) != c.state:
            session['state'] = c.state
            session.save()

        for item in self.items:
            item.after(request, c)

        db.session.close()

    def _detect_dataset_subdomain(self):
        http_host = request.environ.get('HTTP_HOST').lower()
        if http_host.startswith('www.'):
            http_host = http_host[len('www.'):]
        if not '.' in http_host:
            return
        dataset_name, domain = http_host.split('.', 1)
        for dataset in c.datasets:
            if dataset.name.lower() == dataset_name:
                c.dataset = dataset

    def _detect_format(self, format):
        for mimetype, mimeformat in self.accept_mimetypes.items():
            if format == mimeformat or \
                    mimetype in request.headers.get("Accept", ""):
                return mimeformat
        return "html"

    def _get_dataset(self, dataset):
        c.dataset = model.Dataset.by_name(dataset)
        if c.dataset is None:
            abort(404, _('Sorry, there is no dataset named %r') % dataset)
        require.dataset.read(c.dataset)

    def _get_page(self, param='page'):
        try:
            return int(request.params.get(param))
        except:
            return 1
Esempio n. 7
0
class DatasetController(BaseController):

    extensions = PluginImplementations(IDatasetController)

    def index(self, format='html'):
        for item in self.extensions:
            item.index(c, request, response, c.results)

        if format == 'json':
            return to_jsonp(map(lambda d: d.as_dict(), c.datasets))
        elif format == 'csv':
            results = map(lambda d: d.as_dict(), c.datasets)
            return write_csv(results, response)
        else:
            c.query = request.params.items()
            c.add_filter = lambda f, v: '?' + urlencode(c.query + [(f, v)] if (
                f, v) not in c.query else c.query)
            c.del_filter = lambda f, v: '?' + urlencode([(k, x)
                                                         for k, x in c.query
                                                         if (k, x) != (f, v)])
            c.results = c.datasets
            for language in request.params.getall('languages'):
                l = db.aliased(DatasetLanguage)
                c.results = c.results.join(l, Dataset._languages)
                c.results = c.results.filter(l.code == language)
            for territory in request.params.getall('territories'):
                t = db.aliased(DatasetTerritory)
                c.results = c.results.join(t, Dataset._territories)
                c.results = c.results.filter(t.code == territory)
            c.results = list(c.results)
            c.territory_options = DatasetTerritory.dataset_counts(c.results)
            c.language_options = DatasetLanguage.dataset_counts(c.results)
            return render('dataset/index.html')

    def cta(self):
        return render('dataset/new_cta.html')

    def new(self, errors={}):
        c.currencies = sorted(CURRENCIES.items(), key=lambda (k, v): v)
        require.account.create()
        errors = [(k[len('dataset.'):], v) for k, v in errors.items()]
        c.have_error = bool(errors)
        c.dataset_info_style = '' if errors else 'display: none;'
        return render(
            'dataset/new.html',
            form_errors=dict(errors),
            form_fill=request.params if errors else {'currency': 'USD'})

    def create(self):
        require.account.create()
        try:
            model = {'dataset': request.params}
            schema = dataset_schema(ValidationState(model))
            data = schema.deserialize(request.params)
            if Dataset.by_name(data['name']):
                raise Invalid(
                    SchemaNode(String(), name='dataset.name'),
                    _("A dataset with this identifer already exists!"))
            dataset = Dataset({'dataset': data})
            dataset.private = True
            dataset.managers.append(c.account)
            db.session.add(dataset)
            db.session.commit()
            redirect(
                h.url_for(controller='editor',
                          action='index',
                          dataset=dataset.name))
        except Invalid, i:
            errors = i.asdict()
            return self.new(errors)