reporting_tools.py 6.06 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.storage import Storage
13
from pydal.helpers.methods import smart_query
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

LE GAC Renaud's avatar
LE GAC Renaud committed
58
        for el in s.split("|"):
59 60 61
            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

LE GAC Renaud's avatar
LE GAC Renaud committed
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:
104
            query &= publications.year == selector.year_start
105

106
        elif selector.year_start and selector.year_end:
107 108
            query &= publications.year >= selector.year_start
            query &= publications.year <= selector.year_end
109

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

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

122
            query &= q_cat
123 124

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

128
        section.query = query
129

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

LE GAC Renaud's avatar
LE GAC Renaud committed
134 135
        for level in ("level_1", "level_2", "level_3", "level_4"):
            axis = "axis_%s" % level
136

137
            if not row[axis]:
138
                continue
139

140
            tablename = row[axis]
LE GAC Renaud's avatar
LE GAC Renaud committed
141
            fieldname = row["granularity_%s" % level]
142
            direction = row["direction_%s" % level]
143

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

            orderby.append(field)

150
        section.orderby = tuple(orderby)
151 152 153 154 155 156 157 158

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

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

LE GAC Renaud's avatar
LE GAC Renaud committed
159
        funcs = renderer.postprocessing.replace(" ", "").split(",")
160 161 162 163
        for func in funcs:
            if func in globals():
                section.renderer.funcs.append(globals()[func])

164 165 166
    return sections


LE GAC Renaud's avatar
LE GAC Renaud committed
167
def ref_url(name="List"):
168
    """Get the URL string uses to build the current request.
169

170 171
    Note:
        This function is useful in view
172

173 174
    Args:
        name (str):
175

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

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

LE GAC Renaud's avatar
LE GAC Renaud committed
187
    t = (request.env.http_host, request.env.path_info, "&".join(li))
188
    url = "http://%s%s?%s" % t
189

190
    return url
191 192


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

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

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

203
    """
LE GAC Renaud's avatar
LE GAC Renaud committed
204
    s = ""
205

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

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

212 213 214 215
    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)
216

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