reporting_tools.py 6.14 KB
Newer Older
LE GAC Renaud's avatar
LE GAC Renaud committed
1
# -*- coding: utf-8 -*-
2
"""A collection of tools to build reports in controllers.
3 4

"""
5 6 7 8 9 10 11
import re


from list_postprocessing import (clean,
                                 highlight_my_authors,
                                 highlight_my_speaker,
                                 remove_undef)
12
from gluon.dal import smart_query
13
from gluon.storage import Storage
14

15

16
def format_publication(template, record, funcs=[]):
17
    """Build the bibliographic string for the *record*.
18

19 20 21 22 23 24 25 26
    Args:
        template (str): template to build the bibliographic string.
            The database fields are identified by the pattern
            ``{tablename.fieldname}``. They will be replace by the
            corresponding value found in the *record*.
        record (gluon.DAL.Row): entry of the publications table.
        funcs (list): list of reference to functions. They are used to polish
            the bibliographic string.
27

28 29
    Returns:
        str: the bibliographic reference
30 31 32 33 34 35 36 37 38 39 40 41 42

    """
    # format the record according to user requirement
    value = template.format(**record)

    # run post processing to polish/clean the value
    if funcs:
        for func in funcs:
            value = func(value, template, record)

    return value


43
def get_converter(row):
44
    """Get the converter dictionary for the axis label of the *list*.
45

46 47
    Args:
        row (gluon.dal.Row): one row of the database table *list*.
48

49 50
    Returns:
        dict: ``{value: "blabla, ....", value2: "foo", ....}``
51

52
    """
53
    di = {}
54
    if row.axis_label_converters:
55

56
        s = re.sub(r'" *, *', '"|', row.axis_label_converters)
57

58 59 60 61
        for el in s.split('|'):
            m = re.match(r' *(.+) *: *"(.+)"', el)
            if m:
                di[m.group(1)] = m.group(2)
62

63 64
    return di

65

66
def get_sections(db, selector, row):
67
    """Get the section rows for the *list*.
68

69 70 71 72
    Args:
        db (gluon.dal.DAL): database connection
        selector (plugin_dbui.Selector):
        row (gluon.dal.Row): one row of the database table *list*.
73

74 75 76 77 78 79 80
    Returns:
        list:
            * A list of rows of the *sections* table.
            * Each row also contains the *query* and *orderby*
              directives taking into account *selector* criteria.
            * Each row contains also the renderer format and post
              processing functions
81

82
    """
LE GAC Renaud's avatar
LE GAC Renaud committed
83
    publications = db.publications
84
    sections = []
LE GAC Renaud's avatar
LE GAC Renaud committed
85

86
    for el in row.sections.split(','):
87

88
        # retrieve the section record
89 90
        el = el.strip()
        rows = db(db.sections.section == el).select()
91

92 93
        if not rows:
            continue
94 95

        section = rows.first()
96
        sections.append(section)
97

98 99 100
        # query directive to extract publications for this section
        # It includes foreign key constraints and user requirements
        # related to team, project, authors and year
LE GAC Renaud's avatar
LE GAC Renaud committed
101
        query = selector.query(publications)
102

103
        if selector.year_start and not selector.year_end:
LE GAC Renaud's avatar
LE GAC Renaud committed
104
            query = (query) & (publications.year == selector.year_start)
105

106
        elif selector.year_start and selector.year_end:
LE GAC Renaud's avatar
LE GAC Renaud committed
107 108
            q_start = publications.year >= selector.year_start
            q_end = publications.year <= selector.year_end
109
            query = (query) & ((q_start) & (q_end))
110

111
        if selector.author:
LE GAC Renaud's avatar
LE GAC Renaud committed
112
            q_author = publications.authors_institute.contains(selector.author)
113
            query = (query) & (q_author)
114

115 116
        # add to the query the directive coming from the section itself
        # the publication category and dedicated conditions
117 118
        if section.category_codes:
            q_cat = None
119
            codes = section.category_codes.replace(' ', '').split(',')
120 121
            if codes:
                q_cat = db.categories.code.belongs(codes)
122

123
            query = (query) & (q_cat)
124 125

        if section.conditions:
LE GAC Renaud's avatar
LE GAC Renaud committed
126
            q_conditions = smart_query(publications, section.conditions)
127
            query = (query) & (q_conditions)
128

129
        section.query = query
130

131
        # order by directive to order publication for this section
132
        # taking into account directive from the row and from the section
133
        orderby = []
134

135 136
        for level in ('level_1', 'level_2', 'level_3', 'level_4'):
            axis = 'axis_%s' % level
137

138
            if not row[axis]:
139
                continue
140

141 142 143
            tablename = row[axis]
            fieldname = row['granularity_%s' % level]
            direction = row["direction_%s" % level]
144

145
            field = db[tablename][fieldname]
LE GAC Renaud's avatar
LE GAC Renaud committed
146
            if direction == "DESC":
147
                field = ~field
148 149 150

            orderby.append(field)

151
        section.orderby = tuple(orderby)
152 153 154 155 156 157 158 159 160 161 162 163 164

        # the renderer format and post processing functions
        renderer = db.renderers[section.id_renderers]

        section.renderer = Storage()
        section.renderer.template = renderer.template
        section.renderer.funcs = []

        funcs = renderer.postprocessing.replace(' ', '').split(',')
        for func in funcs:
            if func in globals():
                section.renderer.funcs.append(globals()[func])

165 166 167
    return sections


168
def ref_url(name='List'):
169
    """Get the URL string uses to build the current request.
170

171 172
    Note:
        This function is useful in view
173

174 175
    Args:
        name (str):
176

177 178
    Returns:
        str: ``"http://..."``
179

180
    """
181
    li = []
182 183
    for (k, v) in request.vars.iteritems():
        if k.startswith(name) and len(v):
184
            li.append("%s=%s" % (k, v))
185 186 187
        pass
    pass

188
    t = (request.env.http_host, request.env.path_info, '&'.join(li))
189
    url = "http://%s%s?%s" % t
190

191
    return url
192 193


194
def repr_team_project(db, selector):
195
    """Build the team/project string.
196

197 198 199
    Args:
        db (gluon.dal.DAL): database connection.
        selector (plugin_dbui.Selector):
200

201 202
    Returns:
        unicode: the pattern is "team" or "project" or "team/project".
203

204 205
    """
    s = ''
206

207 208
    if selector.id_teams and not selector.id_projects:
        s = db.teams[selector.id_teams].team
209

210 211
    elif not selector.id_teams and selector.id_projects:
        s = db.projects[selector.id_projects].project
212

213 214 215 216
    elif selector.id_teams and selector.id_projects:
        team = db.teams[selector.id_teams].team
        project = db.projects[selector.id_projects].project
        s = "%s/%s" % (team, project)
217

LE GAC Renaud's avatar
LE GAC Renaud committed
218
    return s