reporting_tools.py 6.04 KB
Newer Older
1
"""A collection of tools to build reports in controllers.
2 3

"""
4 5 6
import re


7 8 9 10
from .list_postprocessing import (clean,
                                  highlight_my_authors,
                                  highlight_my_speaker,
                                  remove_undef)
11
from gluon.storage import Storage
12
from pydal.helpers.methods import smart_query
13

14

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

18 19 20 21 22 23 24 25
    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.
26

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

    """
    # 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


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

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

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

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

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

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

62 63
    return di

64

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

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

73 74 75 76 77 78 79
    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
80

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

LE GAC Renaud's avatar
LE GAC Renaud committed
85
    for el in row.sections.split(","):
86

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

91 92
        if not rows:
            continue
93 94

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

97 98 99
        # 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
100
        query = selector.query(publications)
101

102
        if selector.year_start and not selector.year_end:
103
            query &= publications.year == selector.year_start
104

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

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

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

121
            query &= q_cat
122 123

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

127
        section.query = query
128

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

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

136
            if not row[axis]:
137
                continue
138

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

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

            orderby.append(field)

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

        # 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
158
        funcs = renderer.postprocessing.replace(" ", "").split(",")
159 160 161 162
        for func in funcs:
            if func in globals():
                section.renderer.funcs.append(globals()[func])

163 164 165
    return sections


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

169 170
    Note:
        This function is useful in view
171

172 173
    Args:
        name (str):
174

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

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

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

189
    return url
190 191


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

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

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

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

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

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

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

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