15 # |
15 # |
16 # You should have received a copy of the GNU Lesser General Public License along |
16 # You should have received a copy of the GNU Lesser General Public License along |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
18 """Base class for request/session""" |
18 """Base class for request/session""" |
19 |
19 |
20 from warnings import warn |
|
21 from datetime import time, datetime, timedelta |
20 from datetime import time, datetime, timedelta |
22 |
21 |
23 from six import PY2, PY3, text_type |
22 from six import PY2, PY3, text_type |
24 from six.moves.urllib.parse import (parse_qs, parse_qsl, |
23 from six.moves.urllib.parse import (parse_qs, parse_qsl, |
25 quote as urlquote, unquote as urlunquote, |
24 quote as urlquote, unquote as urlunquote, |
26 urlsplit, urlunsplit) |
25 urlsplit, urlunsplit) |
27 |
26 |
28 from logilab.common.decorators import cached |
27 from logilab.common.decorators import cached |
29 from logilab.common.deprecation import deprecated |
|
30 from logilab.common.date import ustrftime, strptime, todate, todatetime |
28 from logilab.common.date import ustrftime, strptime, todate, todatetime |
31 |
29 |
32 from rql.utils import rqlvar_maker |
30 from rql.utils import rqlvar_maker |
33 |
31 |
34 from cubicweb import (Unauthorized, NoSelectableObject, NoResultError, |
32 from cubicweb import Unauthorized, NoSelectableObject, uilib |
35 MultipleResultsError, uilib) |
|
36 from cubicweb.rset import ResultSet |
33 from cubicweb.rset import ResultSet |
37 |
34 |
38 ONESECOND = timedelta(0, 1, 0) |
35 ONESECOND = timedelta(0, 1, 0) |
39 CACHE_REGISTRY = {} |
36 CACHE_REGISTRY = {} |
40 |
37 |
179 ... works_for=c) |
176 ... works_for=c) |
180 |
177 |
181 """ |
178 """ |
182 cls = self.vreg['etypes'].etype_class(etype) |
179 cls = self.vreg['etypes'].etype_class(etype) |
183 return cls.cw_instantiate(self.execute, **kwargs) |
180 return cls.cw_instantiate(self.execute, **kwargs) |
184 |
|
185 @deprecated('[3.18] use find(etype, **kwargs).entities()') |
|
186 def find_entities(self, etype, **kwargs): |
|
187 """find entities of the given type and attribute values. |
|
188 |
|
189 >>> users = find_entities('CWGroup', name=u'users') |
|
190 >>> groups = find_entities('CWGroup') |
|
191 """ |
|
192 return self.find(etype, **kwargs).entities() |
|
193 |
|
194 @deprecated('[3.18] use find(etype, **kwargs).one()') |
|
195 def find_one_entity(self, etype, **kwargs): |
|
196 """find one entity of the given type and attribute values. |
|
197 raise :exc:`FindEntityError` if can not return one and only one entity. |
|
198 |
|
199 >>> users = find_one_entity('CWGroup', name=u'users') |
|
200 >>> groups = find_one_entity('CWGroup') |
|
201 Exception() |
|
202 """ |
|
203 try: |
|
204 return self.find(etype, **kwargs).one() |
|
205 except (NoResultError, MultipleResultsError) as e: |
|
206 raise FindEntityError("%s: (%s, %s)" % (str(e), etype, kwargs)) |
|
207 |
181 |
208 def find(self, etype, **kwargs): |
182 def find(self, etype, **kwargs): |
209 """find entities of the given type and attribute values. |
183 """find entities of the given type and attribute values. |
210 |
184 |
211 :returns: A :class:`ResultSet` |
185 :returns: A :class:`ResultSet` |
246 """raise an exception if the given rql is not a select query""" |
220 """raise an exception if the given rql is not a select query""" |
247 first = rql.split(None, 1)[0].lower() |
221 first = rql.split(None, 1)[0].lower() |
248 if first in ('insert', 'set', 'delete'): |
222 if first in ('insert', 'set', 'delete'): |
249 raise Unauthorized(self._('only select queries are authorized')) |
223 raise Unauthorized(self._('only select queries are authorized')) |
250 |
224 |
251 def get_cache(self, cachename): |
|
252 """cachename should be dotted names as in : |
|
253 |
|
254 - cubicweb.mycache |
|
255 - cubes.blog.mycache |
|
256 - etc. |
|
257 """ |
|
258 warn.warning('[3.19] .get_cache will disappear soon. ' |
|
259 'Distributed caching mechanisms are being introduced instead.' |
|
260 'Other caching mechanism can be used more reliably ' |
|
261 'to the same effect.', |
|
262 DeprecationWarning) |
|
263 if cachename in CACHE_REGISTRY: |
|
264 cache = CACHE_REGISTRY[cachename] |
|
265 else: |
|
266 cache = CACHE_REGISTRY[cachename] = Cache() |
|
267 _now = datetime.now() |
|
268 if _now > cache.latest_cache_lookup + ONESECOND: |
|
269 ecache = self.execute( |
|
270 'Any C,T WHERE C is CWCache, C name %(name)s, C timestamp T', |
|
271 {'name': cachename}).get_entity(0, 0) |
|
272 cache.latest_cache_lookup = _now |
|
273 if not ecache.valid(cache.cache_creation_date): |
|
274 cache.clear() |
|
275 cache.cache_creation_date = _now |
|
276 return cache |
|
277 |
|
278 # url generation methods ################################################## |
225 # url generation methods ################################################## |
279 |
226 |
280 def build_url(self, *args, **kwargs): |
227 def build_url(self, *args, **kwargs): |
281 """return an absolute URL using params dictionary key/values as URL |
228 """return an absolute URL using params dictionary key/values as URL |
282 parameters. Values are automatically URL quoted, and the |
229 parameters. Values are automatically URL quoted, and the |
294 method = 'view' |
241 method = 'view' |
295 # XXX I (adim) think that if method is passed explicitly, we should |
242 # XXX I (adim) think that if method is passed explicitly, we should |
296 # not try to process it and directly call req.build_url() |
243 # not try to process it and directly call req.build_url() |
297 base_url = kwargs.pop('base_url', None) |
244 base_url = kwargs.pop('base_url', None) |
298 if base_url is None: |
245 if base_url is None: |
299 if kwargs.pop('__secure__', None) is not None: |
|
300 warn('[3.25] __secure__ argument is deprecated', |
|
301 DeprecationWarning, stacklevel=2) |
|
302 base_url = self.base_url() |
246 base_url = self.base_url() |
303 path = self.build_url_path(method, kwargs) |
247 path = self.build_url_path(method, kwargs) |
304 if not kwargs: |
248 if not kwargs: |
305 return u'%s%s' % (base_url, path) |
249 return u'%s%s' % (base_url, path) |
306 return u'%s%s?%s' % (base_url, path, self.build_url_params(**kwargs)) |
250 return u'%s%s?%s' % (base_url, path, self.build_url_params(**kwargs)) |
503 return todate(dt) |
447 return todate(dt) |
504 except ValueError: |
448 except ValueError: |
505 raise ValueError(self._('can\'t parse %(value)r (expected %(format)s)') |
449 raise ValueError(self._('can\'t parse %(value)r (expected %(format)s)') |
506 % {'value': value, 'format': format}) |
450 % {'value': value, 'format': format}) |
507 |
451 |
508 def base_url(self, **kwargs): |
452 def base_url(self): |
509 """Return the root url of the instance.""" |
453 """Return the root url of the instance.""" |
510 secure = kwargs.pop('secure', None) |
|
511 if secure is not None: |
|
512 warn('[3.25] secure argument is deprecated', DeprecationWarning, stacklevel=2) |
|
513 if kwargs: |
|
514 raise TypeError('base_url got unexpected keyword arguments %s' % ', '.join(kwargs)) |
|
515 url = self.vreg.config['base-url'] |
454 url = self.vreg.config['base-url'] |
516 return url if url is None else url.rstrip('/') + '/' |
455 return url if url is None else url.rstrip('/') + '/' |