1 import math
2 import random
3 import string
4 import urlparse
5 import flask
6
7 from coprs import constants
8
9 from rpmUtils.miscutils import splitFilename
13 """ Generate a random string used as token to access the API
14 remotely.
15
16 :kwarg: size, the size of the token to generate, defaults to 30
17 chars.
18 :return: a string, the API token for the user.
19 """
20 return ''.join(random.choice(string.ascii_lowercase) for x in range(size))
21
24
26 if isinstance(attr, int):
27 for k, v in self.vals.items():
28 if v == attr:
29 return k
30 raise KeyError("num {0} is not mapped".format(attr))
31 else:
32 return self.vals[attr]
33
36 __metaclass__ = EnumType
37 vals = {"nothing": 0, "request": 1, "approved": 2}
38
39 @classmethod
41 return [(n, k) for k, n in cls.vals.items() if n != without]
42
45 __metaclass__ = EnumType
46 vals = {"delete": 0, "rename": 1, "legal-flag": 2}
47
50 __metaclass__ = EnumType
51 vals = {"waiting": 0, "success": 1, "failure": 2}
52
55 __metaclass__ = EnumType
56 vals = {"user": 0, "admin": 1}
57
60 __metaclass__ = EnumType
61 vals = {"failed": 0,
62 "succeeded": 1,
63 "canceled": 2,
64 "running": 3,
65 "pending": 4,
66 "skipped": 5,
67 "starting": 6}
68
71
72 - def __init__(self, query, total_count, page=1,
73 per_page_override=None, urls_count_override=None):
74
75 self.query = query
76 self.total_count = total_count
77 self.page = page
78 self.per_page = per_page_override or constants.ITEMS_PER_PAGE
79 self.urls_count = urls_count_override or constants.PAGES_URLS_COUNT
80 self._sliced_query = None
81
82 - def page_slice(self, page):
83 return (self.per_page * (page - 1),
84 self.per_page * page)
85
86 @property
88 if not self._sliced_query:
89 self._sliced_query = self.query[slice(*self.page_slice(self.page))]
90 return self._sliced_query
91
92 @property
94 return int(math.ceil(self.total_count / float(self.per_page)))
95
97 if start:
98 if self.page - 1 > self.urls_count / 2:
99 return (self.url_for_other_page(request, 1), 1)
100 else:
101 if self.page < self.pages - self.urls_count / 2:
102 return (self.url_for_other_page(request, self.pages),
103 self.pages)
104
105 return None
106
108 left_border = self.page - self.urls_count / 2
109 left_border = 1 if left_border < 1 else left_border
110 right_border = self.page + self.urls_count / 2
111 right_border = self.pages if right_border > self.pages else right_border
112
113 return [(self.url_for_other_page(request, i), i)
114 for i in range(left_border, right_border + 1)]
115
116 - def url_for_other_page(self, request, page):
117 args = request.view_args.copy()
118 args["page"] = page
119 return flask.url_for(request.endpoint, **args)
120
123 """
124 Parse package name from possibly incomplete nvra string.
125 """
126
127 if pkg.count(".") >= 3 and pkg.count("-") >= 2:
128 return splitFilename(pkg)[0]
129
130
131 result = ""
132 pkg = pkg.replace(".rpm", "").replace(".src", "")
133
134 for delim in ["-", "."]:
135 if delim in pkg:
136 parts = pkg.split(delim)
137 for part in parts:
138 if any(map(lambda x: x.isdigit(), part)):
139 return result[:-1]
140
141 result += part + "-"
142
143 return result[:-1]
144
145 return pkg
146
160
163
165 """
166 Usage:
167
168 SQLAlchObject.to_dict() => returns a flat dict of the object
169 SQLAlchObject.to_dict({"foo": {}}) => returns a dict of the object
170 and will include a flat dict of object foo inside of that
171 SQLAlchObject.to_dict({"foo": {"bar": {}}, "spam": {}}) => returns
172 a dict of the object, which will include dict of foo
173 (which will include dict of bar) and dict of spam.
174
175 Options can also contain two special values: __columns_only__
176 and __columns_except__
177
178 If present, the first makes only specified fiels appear,
179 the second removes specified fields. Both of these fields
180 must be either strings (only works for one field) or lists
181 (for one and more fields).
182
183 SQLAlchObject.to_dict({"foo": {"__columns_except__": ["id"]},
184 "__columns_only__": "name"}) =>
185
186 The SQLAlchObject will only put its "name" into the resulting dict,
187 while "foo" all of its fields except "id".
188
189 Options can also specify whether to include foo_id when displaying
190 related foo object (__included_ids__, defaults to True).
191 This doesn"t apply when __columns_only__ is specified.
192 """
193
194 result = {}
195 if options is None:
196 options = {}
197 columns = self.serializable_attributes
198
199 if "__columns_only__" in options:
200 columns = options["__columns_only__"]
201 else:
202 columns = set(columns)
203 if "__columns_except__" in options:
204 columns_except = options["__columns_except__"]
205 if not isinstance(options["__columns_except__"], list):
206 columns_except = [options["__columns_except__"]]
207
208 columns -= set(columns_except)
209
210 if ("__included_ids__" in options and
211 options["__included_ids__"] is False):
212
213 related_objs_ids = [
214 r + "_id" for r, _ in options.items()
215 if not r.startswith("__")]
216
217 columns -= set(related_objs_ids)
218
219 columns = list(columns)
220
221 for column in columns:
222 result[column] = getattr(self, column)
223
224 for related, values in options.items():
225 if hasattr(self, related):
226 result[related] = getattr(self, related).to_dict(values)
227 return result
228
229 @property
231 return map(lambda x: x.name, self.__table__.columns)
232