Statistics
| Branch: | Tag: | Revision:

root / snf-webproject / synnefo / webproject / management / utils.py @ b482fbcc

History | View | Annotate | Download (6 kB)

1 225cea18 Christos Stavrakakis
# Copyright 2012 - 2013 GRNET S.A. All rights reserved.
2 225cea18 Christos Stavrakakis
#
3 225cea18 Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 225cea18 Christos Stavrakakis
# without modification, are permitted provided that the following
5 225cea18 Christos Stavrakakis
# conditions are met:
6 225cea18 Christos Stavrakakis
#
7 225cea18 Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 225cea18 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 225cea18 Christos Stavrakakis
#      disclaimer.
10 225cea18 Christos Stavrakakis
#
11 225cea18 Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 225cea18 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 225cea18 Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 225cea18 Christos Stavrakakis
#      provided with the distribution.
15 225cea18 Christos Stavrakakis
#
16 225cea18 Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 225cea18 Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 225cea18 Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 225cea18 Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 225cea18 Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 225cea18 Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 225cea18 Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 225cea18 Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 225cea18 Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 225cea18 Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 225cea18 Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 225cea18 Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 225cea18 Christos Stavrakakis
#
29 225cea18 Christos Stavrakakis
# The views and conclusions contained in the software and
30 225cea18 Christos Stavrakakis
# documentation are those of the authors and should not be
31 225cea18 Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 225cea18 Christos Stavrakakis
# or implied, of GRNET S.A.
33 225cea18 Christos Stavrakakis
34 b0e7f310 Christos Stavrakakis
import json
35 f105d79d Christos Stavrakakis
import csv
36 f105d79d Christos Stavrakakis
import functools
37 225cea18 Christos Stavrakakis
from datetime import datetime
38 225cea18 Christos Stavrakakis
from django.utils.timesince import timesince, timeuntil
39 225cea18 Christos Stavrakakis
40 225cea18 Christos Stavrakakis
from synnefo.util.text import uenc, udec
41 225cea18 Christos Stavrakakis
42 225cea18 Christos Stavrakakis
43 225cea18 Christos Stavrakakis
def parse_bool(value, strict=True):
44 225cea18 Christos Stavrakakis
    """Convert a string to boolen value.
45 225cea18 Christos Stavrakakis

46 225cea18 Christos Stavrakakis
    If string is True, then ValueError will be raised, if the string can not be
47 225cea18 Christos Stavrakakis
    converted to boolean. Otherwise the string will be returned as is.
48 225cea18 Christos Stavrakakis

49 225cea18 Christos Stavrakakis
    """
50 225cea18 Christos Stavrakakis
    if value.lower() in ("yes", "true", "t", "1"):
51 225cea18 Christos Stavrakakis
        return True
52 225cea18 Christos Stavrakakis
    if value.lower() in ("no", "false", "f", "0"):
53 225cea18 Christos Stavrakakis
        return False
54 225cea18 Christos Stavrakakis
55 225cea18 Christos Stavrakakis
    if strict:
56 225cea18 Christos Stavrakakis
        raise ValueError("Can convert '%s' to boolean value")
57 225cea18 Christos Stavrakakis
    else:
58 225cea18 Christos Stavrakakis
        return value
59 225cea18 Christos Stavrakakis
60 225cea18 Christos Stavrakakis
61 225cea18 Christos Stavrakakis
def format_bool(b):
62 225cea18 Christos Stavrakakis
    """Convert a boolean value to YES or NO."""
63 225cea18 Christos Stavrakakis
    return "YES" if b else "NO"
64 225cea18 Christos Stavrakakis
65 225cea18 Christos Stavrakakis
66 225cea18 Christos Stavrakakis
def format_date(d):
67 225cea18 Christos Stavrakakis
    if not d:
68 225cea18 Christos Stavrakakis
        return ""
69 225cea18 Christos Stavrakakis
70 225cea18 Christos Stavrakakis
    if d < datetime.now():
71 225cea18 Christos Stavrakakis
        return timesince(d) + " ago"
72 225cea18 Christos Stavrakakis
    else:
73 225cea18 Christos Stavrakakis
        return "in " + timeuntil(d)
74 225cea18 Christos Stavrakakis
75 225cea18 Christos Stavrakakis
76 225cea18 Christos Stavrakakis
def parse_filters(filter_by):
77 225cea18 Christos Stavrakakis
    """Parse a string into lookup parameters for QuerySet.filter(**kwargs).
78 225cea18 Christos Stavrakakis

79 225cea18 Christos Stavrakakis
    This functions converts a string of comma-separated key 'cond' val triples
80 225cea18 Christos Stavrakakis
    to two dictionaries, containing lookup parameters to be used for filter
81 225cea18 Christos Stavrakakis
    and exclude functions of QuerySet.
82 225cea18 Christos Stavrakakis

83 225cea18 Christos Stavrakakis
    e.g. filter_by="foo>=2, baz!=4" -> ({"foo__gte": "2"}, {"baz": "4"})
84 225cea18 Christos Stavrakakis

85 225cea18 Christos Stavrakakis
    """
86 225cea18 Christos Stavrakakis
87 225cea18 Christos Stavrakakis
    filter_dict = {}
88 225cea18 Christos Stavrakakis
    exclude_dict = {}
89 225cea18 Christos Stavrakakis
90 225cea18 Christos Stavrakakis
    filter_list = filter_by.split(",")
91 225cea18 Christos Stavrakakis
92 225cea18 Christos Stavrakakis
    def map_field_type(query):
93 225cea18 Christos Stavrakakis
        if "!=" in query:
94 225cea18 Christos Stavrakakis
            key, val = query.split("!=")
95 225cea18 Christos Stavrakakis
            exclude_dict[key] = parse_bool(val, strict=False)
96 225cea18 Christos Stavrakakis
            return
97 225cea18 Christos Stavrakakis
98 225cea18 Christos Stavrakakis
        OP_MAP = {
99 225cea18 Christos Stavrakakis
            ">=": "__gte",
100 225cea18 Christos Stavrakakis
            "=>": "__gte",
101 225cea18 Christos Stavrakakis
            ">":  "__gt",
102 225cea18 Christos Stavrakakis
            "<=": "__lte",
103 225cea18 Christos Stavrakakis
            "=<": "__lte",
104 225cea18 Christos Stavrakakis
            "<":  "__lt",
105 225cea18 Christos Stavrakakis
            "=":  "",
106 225cea18 Christos Stavrakakis
        }
107 225cea18 Christos Stavrakakis
108 225cea18 Christos Stavrakakis
        for op, new_op in OP_MAP.items():
109 225cea18 Christos Stavrakakis
            if op in query:
110 225cea18 Christos Stavrakakis
                key, val = query.split(op)
111 225cea18 Christos Stavrakakis
                filter_dict[key + new_op] = parse_bool(val, strict=False)
112 225cea18 Christos Stavrakakis
                return
113 225cea18 Christos Stavrakakis
114 225cea18 Christos Stavrakakis
    map(lambda x: map_field_type(x), filter_list)
115 225cea18 Christos Stavrakakis
116 225cea18 Christos Stavrakakis
    return (filter_dict, exclude_dict)
117 225cea18 Christos Stavrakakis
118 225cea18 Christos Stavrakakis
119 b0e7f310 Christos Stavrakakis
def pprint_table(out, table, headers=None, output_format='pretty',
120 b482fbcc Giorgos Korfiatis
                 separator=None, vertical=False, title=None):
121 225cea18 Christos Stavrakakis
    """Print a pretty, aligned string representation of table.
122 225cea18 Christos Stavrakakis

123 225cea18 Christos Stavrakakis
    Works by finding out the max width of each column and padding to data
124 225cea18 Christos Stavrakakis
    to this value.
125 225cea18 Christos Stavrakakis
    """
126 225cea18 Christos Stavrakakis
127 225cea18 Christos Stavrakakis
    assert(isinstance(table, (list, tuple))), "Invalid table type"
128 225cea18 Christos Stavrakakis
    if headers:
129 225cea18 Christos Stavrakakis
        assert(isinstance(headers, (list, tuple))), "Invalid headers type"
130 225cea18 Christos Stavrakakis
131 b0e7f310 Christos Stavrakakis
    sep = separator if separator else "  "
132 b0e7f310 Christos Stavrakakis
133 b0e7f310 Christos Stavrakakis
    def stringnify(obj):
134 225cea18 Christos Stavrakakis
        if isinstance(obj, (unicode, str)):
135 225cea18 Christos Stavrakakis
            return udec(obj)
136 225cea18 Christos Stavrakakis
        else:
137 225cea18 Christos Stavrakakis
            return str(obj)
138 225cea18 Christos Stavrakakis
139 f105d79d Christos Stavrakakis
    if headers:
140 f105d79d Christos Stavrakakis
        headers = map(stringnify, headers)
141 b0e7f310 Christos Stavrakakis
    table = [map(stringnify, row) for row in table]
142 b0e7f310 Christos Stavrakakis
143 b0e7f310 Christos Stavrakakis
    if output_format == "json":
144 f105d79d Christos Stavrakakis
        assert(headers is not None), "json output format requires headers"
145 b0e7f310 Christos Stavrakakis
        table = [dict(zip(headers, row)) for row in table]
146 b0e7f310 Christos Stavrakakis
        out.write(json.dumps(table, indent=4))
147 b0e7f310 Christos Stavrakakis
        out.write("\n")
148 b0e7f310 Christos Stavrakakis
    elif output_format == "csv":
149 f105d79d Christos Stavrakakis
        cw = csv.writer(out)
150 b0e7f310 Christos Stavrakakis
        if headers:
151 f105d79d Christos Stavrakakis
            table.insert(0, headers)
152 f105d79d Christos Stavrakakis
        table = map(functools.partial(map, uenc), table)
153 f105d79d Christos Stavrakakis
        cw.writerows(table)
154 b0e7f310 Christos Stavrakakis
    elif output_format == "pretty":
155 28578e52 Christos Stavrakakis
        if vertical:
156 28578e52 Christos Stavrakakis
            assert(len(table) == 1)
157 28578e52 Christos Stavrakakis
            row = table[0]
158 28578e52 Christos Stavrakakis
            max_key = max(map(len, headers))
159 28578e52 Christos Stavrakakis
            for row in table:
160 28578e52 Christos Stavrakakis
                for (k, v) in zip(headers, row):
161 28578e52 Christos Stavrakakis
                    k = uenc(k.ljust(max_key))
162 4571b863 Giorgos Korfiatis
                    v = uenc(v)
163 28578e52 Christos Stavrakakis
                    out.write("%s: %s\n" % (k, v))
164 28578e52 Christos Stavrakakis
        else:
165 28578e52 Christos Stavrakakis
            # Find out the max width of each column
166 28578e52 Christos Stavrakakis
            columns = [headers] + table if headers else table
167 28578e52 Christos Stavrakakis
            widths = [max(map(len, col)) for col in zip(*(columns))]
168 28578e52 Christos Stavrakakis
169 28578e52 Christos Stavrakakis
            t_length = sum(widths) + len(sep) * (len(widths) - 1)
170 b482fbcc Giorgos Korfiatis
            if title is not None:
171 b482fbcc Giorgos Korfiatis
                out.write(title.center(t_length) + "\n")
172 28578e52 Christos Stavrakakis
            if headers:
173 28578e52 Christos Stavrakakis
                # pretty print the headers
174 28578e52 Christos Stavrakakis
                line = sep.join(uenc(v.rjust(w))\
175 28578e52 Christos Stavrakakis
                                for v, w in zip(headers, widths))
176 28578e52 Christos Stavrakakis
                out.write(line + "\n")
177 28578e52 Christos Stavrakakis
                out.write("-" * t_length + "\n")
178 28578e52 Christos Stavrakakis
179 28578e52 Christos Stavrakakis
            # print the rest table
180 28578e52 Christos Stavrakakis
            for row in table:
181 28578e52 Christos Stavrakakis
                line = sep.join(uenc(v.rjust(w)) for v, w in zip(row, widths))
182 28578e52 Christos Stavrakakis
                out.write(line + "\n")
183 b0e7f310 Christos Stavrakakis
    else:
184 b0e7f310 Christos Stavrakakis
        raise ValueError("Unknown output format '%s'" % output_format)