root / snf-webproject / synnefo / webproject / management / util.py @ b0e7f310
History | View | Annotate | Download (5.3 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 | 225cea18 | Christos Stavrakakis | from datetime import datetime |
36 | 225cea18 | Christos Stavrakakis | from django.utils.timesince import timesince, timeuntil |
37 | 225cea18 | Christos Stavrakakis | |
38 | 225cea18 | Christos Stavrakakis | from synnefo.util.text import uenc, udec |
39 | 225cea18 | Christos Stavrakakis | |
40 | 225cea18 | Christos Stavrakakis | |
41 | 225cea18 | Christos Stavrakakis | def parse_bool(value, strict=True): |
42 | 225cea18 | Christos Stavrakakis | """Convert a string to boolen value.
|
43 | 225cea18 | Christos Stavrakakis |
|
44 | 225cea18 | Christos Stavrakakis | If string is True, then ValueError will be raised, if the string can not be
|
45 | 225cea18 | Christos Stavrakakis | converted to boolean. Otherwise the string will be returned as is.
|
46 | 225cea18 | Christos Stavrakakis |
|
47 | 225cea18 | Christos Stavrakakis | """
|
48 | 225cea18 | Christos Stavrakakis | if value.lower() in ("yes", "true", "t", "1"): |
49 | 225cea18 | Christos Stavrakakis | return True |
50 | 225cea18 | Christos Stavrakakis | if value.lower() in ("no", "false", "f", "0"): |
51 | 225cea18 | Christos Stavrakakis | return False |
52 | 225cea18 | Christos Stavrakakis | |
53 | 225cea18 | Christos Stavrakakis | if strict:
|
54 | 225cea18 | Christos Stavrakakis | raise ValueError("Can convert '%s' to boolean value") |
55 | 225cea18 | Christos Stavrakakis | else:
|
56 | 225cea18 | Christos Stavrakakis | return value
|
57 | 225cea18 | Christos Stavrakakis | |
58 | 225cea18 | Christos Stavrakakis | |
59 | 225cea18 | Christos Stavrakakis | def format_bool(b): |
60 | 225cea18 | Christos Stavrakakis | """Convert a boolean value to YES or NO."""
|
61 | 225cea18 | Christos Stavrakakis | return "YES" if b else "NO" |
62 | 225cea18 | Christos Stavrakakis | |
63 | 225cea18 | Christos Stavrakakis | |
64 | 225cea18 | Christos Stavrakakis | def format_date(d): |
65 | 225cea18 | Christos Stavrakakis | if not d: |
66 | 225cea18 | Christos Stavrakakis | return "" |
67 | 225cea18 | Christos Stavrakakis | |
68 | 225cea18 | Christos Stavrakakis | if d < datetime.now():
|
69 | 225cea18 | Christos Stavrakakis | return timesince(d) + " ago" |
70 | 225cea18 | Christos Stavrakakis | else:
|
71 | 225cea18 | Christos Stavrakakis | return "in " + timeuntil(d) |
72 | 225cea18 | Christos Stavrakakis | |
73 | 225cea18 | Christos Stavrakakis | |
74 | 225cea18 | Christos Stavrakakis | def parse_filters(filter_by): |
75 | 225cea18 | Christos Stavrakakis | """Parse a string into lookup parameters for QuerySet.filter(**kwargs).
|
76 | 225cea18 | Christos Stavrakakis |
|
77 | 225cea18 | Christos Stavrakakis | This functions converts a string of comma-separated key 'cond' val triples
|
78 | 225cea18 | Christos Stavrakakis | to two dictionaries, containing lookup parameters to be used for filter
|
79 | 225cea18 | Christos Stavrakakis | and exclude functions of QuerySet.
|
80 | 225cea18 | Christos Stavrakakis |
|
81 | 225cea18 | Christos Stavrakakis | e.g. filter_by="foo>=2, baz!=4" -> ({"foo__gte": "2"}, {"baz": "4"})
|
82 | 225cea18 | Christos Stavrakakis |
|
83 | 225cea18 | Christos Stavrakakis | """
|
84 | 225cea18 | Christos Stavrakakis | |
85 | 225cea18 | Christos Stavrakakis | filter_dict = {} |
86 | 225cea18 | Christos Stavrakakis | exclude_dict = {} |
87 | 225cea18 | Christos Stavrakakis | |
88 | 225cea18 | Christos Stavrakakis | filter_list = filter_by.split(",")
|
89 | 225cea18 | Christos Stavrakakis | |
90 | 225cea18 | Christos Stavrakakis | def map_field_type(query): |
91 | 225cea18 | Christos Stavrakakis | if "!=" in query: |
92 | 225cea18 | Christos Stavrakakis | key, val = query.split("!=")
|
93 | 225cea18 | Christos Stavrakakis | exclude_dict[key] = parse_bool(val, strict=False)
|
94 | 225cea18 | Christos Stavrakakis | return
|
95 | 225cea18 | Christos Stavrakakis | |
96 | 225cea18 | Christos Stavrakakis | OP_MAP = { |
97 | 225cea18 | Christos Stavrakakis | ">=": "__gte", |
98 | 225cea18 | Christos Stavrakakis | "=>": "__gte", |
99 | 225cea18 | Christos Stavrakakis | ">": "__gt", |
100 | 225cea18 | Christos Stavrakakis | "<=": "__lte", |
101 | 225cea18 | Christos Stavrakakis | "=<": "__lte", |
102 | 225cea18 | Christos Stavrakakis | "<": "__lt", |
103 | 225cea18 | Christos Stavrakakis | "=": "", |
104 | 225cea18 | Christos Stavrakakis | } |
105 | 225cea18 | Christos Stavrakakis | |
106 | 225cea18 | Christos Stavrakakis | for op, new_op in OP_MAP.items(): |
107 | 225cea18 | Christos Stavrakakis | if op in query: |
108 | 225cea18 | Christos Stavrakakis | key, val = query.split(op) |
109 | 225cea18 | Christos Stavrakakis | filter_dict[key + new_op] = parse_bool(val, strict=False)
|
110 | 225cea18 | Christos Stavrakakis | return
|
111 | 225cea18 | Christos Stavrakakis | |
112 | 225cea18 | Christos Stavrakakis | map(lambda x: map_field_type(x), filter_list) |
113 | 225cea18 | Christos Stavrakakis | |
114 | 225cea18 | Christos Stavrakakis | return (filter_dict, exclude_dict)
|
115 | 225cea18 | Christos Stavrakakis | |
116 | 225cea18 | Christos Stavrakakis | |
117 | b0e7f310 | Christos Stavrakakis | def pprint_table(out, table, headers=None, output_format='pretty', |
118 | b0e7f310 | Christos Stavrakakis | separator=None):
|
119 | 225cea18 | Christos Stavrakakis | """Print a pretty, aligned string representation of table.
|
120 | 225cea18 | Christos Stavrakakis |
|
121 | 225cea18 | Christos Stavrakakis | Works by finding out the max width of each column and padding to data
|
122 | 225cea18 | Christos Stavrakakis | to this value.
|
123 | 225cea18 | Christos Stavrakakis | """
|
124 | 225cea18 | Christos Stavrakakis | |
125 | 225cea18 | Christos Stavrakakis | assert(isinstance(table, (list, tuple))), "Invalid table type" |
126 | 225cea18 | Christos Stavrakakis | if headers:
|
127 | 225cea18 | Christos Stavrakakis | assert(isinstance(headers, (list, tuple))), "Invalid headers type" |
128 | 225cea18 | Christos Stavrakakis | |
129 | b0e7f310 | Christos Stavrakakis | sep = separator if separator else " " |
130 | b0e7f310 | Christos Stavrakakis | |
131 | b0e7f310 | Christos Stavrakakis | def stringnify(obj): |
132 | 225cea18 | Christos Stavrakakis | if isinstance(obj, (unicode, str)): |
133 | 225cea18 | Christos Stavrakakis | return udec(obj)
|
134 | 225cea18 | Christos Stavrakakis | else:
|
135 | 225cea18 | Christos Stavrakakis | return str(obj) |
136 | 225cea18 | Christos Stavrakakis | |
137 | b0e7f310 | Christos Stavrakakis | headers = map(stringnify, headers)
|
138 | b0e7f310 | Christos Stavrakakis | table = [map(stringnify, row) for row in table] |
139 | b0e7f310 | Christos Stavrakakis | |
140 | b0e7f310 | Christos Stavrakakis | if output_format == "json": |
141 | b0e7f310 | Christos Stavrakakis | table = [dict(zip(headers, row)) for row in table] |
142 | b0e7f310 | Christos Stavrakakis | out.write(json.dumps(table, indent=4))
|
143 | b0e7f310 | Christos Stavrakakis | out.write("\n")
|
144 | b0e7f310 | Christos Stavrakakis | elif output_format == "csv": |
145 | b0e7f310 | Christos Stavrakakis | if headers:
|
146 | b0e7f310 | Christos Stavrakakis | line = ",".join("\"%s\"" % uenc(v) for v in headers) |
147 | b0e7f310 | Christos Stavrakakis | out.write(line + "\n")
|
148 | b0e7f310 | Christos Stavrakakis | for row in table: |
149 | b0e7f310 | Christos Stavrakakis | line = ",".join("\"%s\"" % uenc(v) for v in row) |
150 | b0e7f310 | Christos Stavrakakis | out.write(line + "\n")
|
151 | b0e7f310 | Christos Stavrakakis | elif output_format == "pretty": |
152 | b0e7f310 | Christos Stavrakakis | # Find out the max width of each column
|
153 | b0e7f310 | Christos Stavrakakis | widths = [max(map(len, col)) for col in zip(*([headers] + table))] |
154 | b0e7f310 | Christos Stavrakakis | |
155 | b0e7f310 | Christos Stavrakakis | t_length = sum(widths) + len(sep) * (len(widths) - 1) |
156 | b0e7f310 | Christos Stavrakakis | if headers:
|
157 | b0e7f310 | Christos Stavrakakis | # pretty print the headers
|
158 | b0e7f310 | Christos Stavrakakis | line = sep.join(uenc(v.rjust(w)) for v, w in zip(headers, widths)) |
159 | b0e7f310 | Christos Stavrakakis | out.write(line + "\n")
|
160 | b0e7f310 | Christos Stavrakakis | out.write("-" * t_length + "\n") |
161 | b0e7f310 | Christos Stavrakakis | |
162 | b0e7f310 | Christos Stavrakakis | # print the rest table
|
163 | b0e7f310 | Christos Stavrakakis | for row in table: |
164 | b0e7f310 | Christos Stavrakakis | line = sep.join(uenc(v.rjust(w)) for v, w in zip(row, widths)) |
165 | b0e7f310 | Christos Stavrakakis | out.write(line + "\n")
|
166 | b0e7f310 | Christos Stavrakakis | else:
|
167 | b0e7f310 | Christos Stavrakakis | raise ValueError("Unknown output format '%s'" % output_format) |