Commit 9032c995 authored by Sylvain Thénault's avatar Sylvain Thénault
Browse files

pep8 + docstrings and comments improvments

parent b4dcfd734686
......@@ -69,7 +69,7 @@ class BaseTestCase(TestCase):
@classproperty
@cached
def datadir(cls): # pylint: disable=E0213
def datadir(cls): # pylint: disable=E0213
"""helper attribute holding the standard test's data directory
"""
mod = sys.modules[cls.__module__]
......@@ -889,7 +889,6 @@ class CubicWebTC(BaseTestCase):
return req, self.session
def assertAuthSuccess(self, req, origsession, nbsessions=1):
sh = self.app.session_handler
session = self.app.get_session(req)
cnx = repoapi.Connection(session)
req.set_cnx(cnx)
......@@ -927,7 +926,7 @@ class CubicWebTC(BaseTestCase):
'text/x-vcard': None,
'text/calendar': None,
'image/png': None,
}
}
# maps vid : validator name (override content_type_validators)
vid_validators = dict((vid, htmlparser.VALMAP[valkey])
for vid, valkey in VIEW_VALIDATORS.items())
......@@ -1055,7 +1054,7 @@ class CubicWebTC(BaseTestCase):
# the line number
content = u'\n'.join(line_template % (idx + 1, line)
for idx, line in enumerate(content)
if line_context_filter(idx+1, position))
if line_context_filter(idx + 1, position))
msg += u'\nfor content:\n%s' % content
exc = AssertionError(msg)
exc.__traceback__ = tcbk
......
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
......@@ -132,7 +132,7 @@ class CWUser(AnyEntity):
groups = frozenset((groups,))
elif isinstance(groups, (tuple, list)):
groups = frozenset(groups)
return len(groups & self.groups) # XXX return the resulting set instead of its size
return len(groups & self.groups) # XXX return the resulting set instead of its size
def is_in_group(self, group):
"""convience / shortcut method to test if the user belongs to `group`
......@@ -141,9 +141,8 @@ class CWUser(AnyEntity):
def is_anonymous(self):
""" checks if user is an anonymous user"""
#FIXME on the web-side anonymous user is detected according
# to config['anonymous-user'], we don't have this info on
# the server side.
# FIXME on the web-side anonymous user is detected according to config['anonymous-user'],
# we don't have this info on the server side.
return self.groups == frozenset(('guests', ))
def owns(self, eid):
......@@ -162,7 +161,7 @@ class CWUser(AnyEntity):
if self.firstname and self.surname:
return self._cw._('%(firstname)s %(surname)s') % {
'firstname': self.firstname, 'surname' : self.surname}
'firstname': self.firstname, 'surname': self.surname}
if self.firstname:
return self.firstname
return self.login
......
......@@ -338,7 +338,6 @@ class Entity(AppObject):
return
else:
visited.add(eschema.type)
_fetchattrs = []
for attr in sorted(fetchattrs):
try:
rschema = eschema.subjrels[attr]
......@@ -366,7 +365,7 @@ class Entity(AppObject):
# later information here, systematically add it.
rel.change_optional('right')
targettypes = rschema.objects(eschema.type)
vreg = user._cw.vreg # XXX user._cw.vreg iiiirk
vreg = user._cw.vreg # XXX user._cw.vreg iiiirk
etypecls = vreg['etypes'].etype_class(targettypes[0])
if len(targettypes) > 1:
# find fetch_attrs common to all destination types
......
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
......@@ -18,8 +18,8 @@
"""Core hooks: synchronize living session on persistent data changes"""
__docformat__ = "restructuredtext en"
from cubicweb import _
from cubicweb import _
from cubicweb import UnknownProperty, BadConnectionId, validation_error
from cubicweb.predicates import is_instance
from cubicweb.server import hook
......@@ -55,7 +55,7 @@ class _GroupOperation(hook.Operation):
class _DeleteGroupOp(_GroupOperation):
"""synchronize user when a in_group relation has been deleted"""
"""Synchronize user when a in_group relation has been deleted"""
def postcommit_event(self):
"""the observed connections set has been commited"""
......@@ -67,7 +67,8 @@ class _DeleteGroupOp(_GroupOperation):
class _AddGroupOp(_GroupOperation):
"""synchronize user when a in_group relation has been added"""
"""Synchronize user when a in_group relation has been added"""
def postcommit_event(self):
"""the observed connections set has been commited"""
groups = self.cnxuser.groups
......@@ -79,6 +80,7 @@ class _AddGroupOp(_GroupOperation):
class SyncInGroupHook(SyncSessionHook):
"""Watch addition/removal of in_group relation to synchronize living sessions accordingly"""
__regid__ = 'syncingroup'
__select__ = SyncSessionHook.__select__ & hook.match_rtype('in_group')
events = ('after_delete_relation', 'after_add_relation')
......@@ -99,11 +101,10 @@ class _DelUserOp(hook.Operation):
hook.Operation.__init__(self, cnx)
def postcommit_event(self):
"""the observed connections set has been commited"""
try:
self.cnx.repo.close(self.sessionid)
except BadConnectionId:
pass # already closed
pass # already closed
class CloseDeletedUserSessionsHook(SyncSessionHook):
......@@ -112,7 +113,6 @@ class CloseDeletedUserSessionsHook(SyncSessionHook):
events = ('after_delete_entity',)
def __call__(self):
"""modify user permission, need to update users"""
for session in get_user_sessions(self._cw.repo, self.entity.eid):
_DelUserOp(self._cw, session.sessionid)
......@@ -211,11 +211,10 @@ class DeleteCWPropertyHook(AddCWPropertyHook):
events = ('before_delete_entity',)
def __call__(self):
eid = self.entity.eid
cnx = self._cw
for eidfrom, rtype, eidto in cnx.transaction_data.get('pendingrelations', ()):
if rtype == 'for_user' and eidfrom == self.entity.eid:
# if for_user was set, delete has already been handled
# if for_user was set, delete already handled by hook on for_user deletion
break
else:
_DelCWPropertyOp(cnx, cwpropdict=cnx.vreg['propertyvalues'],
......@@ -233,7 +232,7 @@ class AddForUserRelationHook(SyncSessionHook):
if not cnx.entity_metas(eidfrom)['type'] == 'CWProperty':
return
key, value = cnx.execute('Any K,V WHERE P eid %(x)s,P pkey K,P value V',
{'x': eidfrom})[0]
{'x': eidfrom})[0]
if cnx.vreg.property_info(key)['sitewide']:
msg = _("site-wide property can't be set for user")
raise validation_error(eidfrom, {('for_user', 'subject'): msg})
......@@ -248,8 +247,7 @@ class DelForUserRelationHook(AddForUserRelationHook):
def __call__(self):
cnx = self._cw
key = cnx.execute('Any K WHERE P eid %(x)s, P pkey K',
{'x': self.eidfrom})[0][0]
key = cnx.execute('Any K WHERE P eid %(x)s, P pkey K', {'x': self.eidfrom})[0][0]
cnx.transaction_data.setdefault('pendingrelations', []).append(
(self.eidfrom, self.rtype, self.eidto))
for session in get_user_sessions(cnx.repo, self.eidto):
......
# -*- coding: utf-8 -*-
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
......@@ -27,6 +27,7 @@ from six import text_type
from cubicweb import ValidationError
from cubicweb.devtools.testlib import CubicWebTC
class CWPropertyHooksTC(CubicWebTC):
def test_unexistant_cwproperty(self):
......
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
......@@ -23,7 +23,9 @@ from warnings import warn
from datetime import time, datetime, timedelta
from six import PY2, PY3, text_type
from six.moves.urllib.parse import parse_qs, parse_qsl, quote as urlquote, unquote as urlunquote, urlsplit, urlunsplit
from six.moves.urllib.parse import (parse_qs, parse_qsl,
quote as urlquote, unquote as urlunquote,
urlsplit, urlunsplit)
from logilab.common.decorators import cached
from logilab.common.deprecation import deprecated
......@@ -38,9 +40,11 @@ from cubicweb.rset import ResultSet
ONESECOND = timedelta(0, 1, 0)
CACHE_REGISTRY = {}
class FindEntityError(Exception):
"""raised when find_one_entity() can not return one and only one entity"""
class Cache(dict):
def __init__(self):
super(Cache, self).__init__()
......@@ -59,13 +63,13 @@ class RequestSessionBase(object):
:attribute vreg.schema: the instance's schema
:attribute vreg.config: the instance's configuration
"""
is_request = True # False for repository session
is_request = True # False for repository session
def __init__(self, vreg):
self.vreg = vreg
try:
encoding = vreg.property_value('ui.encoding')
except Exception: # no vreg or property not registered
except Exception: # no vreg or property not registered
encoding = 'utf-8'
self.encoding = encoding
# cache result of execution for (rql expr / eids),
......@@ -117,10 +121,12 @@ class RequestSessionBase(object):
def etype_rset(self, etype, size=1):
"""return a fake result set for a particular entity type"""
rset = ResultSet([('A',)]*size, '%s X' % etype,
description=[(etype,)]*size)
rset = ResultSet([('A',)] * size, '%s X' % etype,
description=[(etype,)] * size)
def get_entity(row, col=0, etype=etype, req=self, rset=rset):
return req.vreg['etypes'].etype_class(etype)(req, rset, row, col)
rset.get_entity = get_entity
rset.req = self
return rset
......@@ -255,7 +261,7 @@ class RequestSessionBase(object):
if _now > cache.latest_cache_lookup + ONESECOND:
ecache = self.execute(
'Any C,T WHERE C is CWCache, C name %(name)s, C timestamp T',
{'name':cachename}).get_entity(0,0)
{'name': cachename}).get_entity(0, 0)
cache.latest_cache_lookup = _now
if not ecache.valid(cache.cache_creation_date):
cache.clear()
......@@ -330,7 +336,7 @@ class RequestSessionBase(object):
quoted = quoted.encode(self.encoding)
try:
return unicode(urlunquote(quoted), self.encoding)
except UnicodeDecodeError: # might occurs on manually typed URLs
except UnicodeDecodeError: # might occurs on manually typed URLs
return unicode(urlunquote(quoted), 'iso-8859-1')
def url_parse_qsl(self, querystring):
......@@ -344,10 +350,9 @@ class RequestSessionBase(object):
for key, val in parse_qsl(querystring):
try:
yield unicode(key, self.encoding), unicode(val, self.encoding)
except UnicodeDecodeError: # might occurs on manually typed URLs
except UnicodeDecodeError: # might occurs on manually typed URLs
yield unicode(key, 'iso-8859-1'), unicode(val, 'iso-8859-1')
def rebuild_url(self, url, **newparams):
"""return the given url with newparams inserted. If any new params
is already specified in the url, it's overriden by the new value
......@@ -410,12 +415,11 @@ class RequestSessionBase(object):
else:
initargs.update(kwargs)
try:
view = self.vreg[__registry].select(__vid, self, rset=rset, **initargs)
view = self.vreg[__registry].select(__vid, self, rset=rset, **initargs)
except NoSelectableObject:
if __fallback_oid is None:
raise
view = self.vreg[__registry].select(__fallback_oid, self,
rset=rset, **initargs)
view = self.vreg[__registry].select(__fallback_oid, self, rset=rset, **initargs)
return view.render(w=w, **kwargs)
def printable_value(self, attrtype, value, props=None, displaytime=True,
......@@ -474,8 +478,8 @@ class RequestSessionBase(object):
elif etype == 'Time':
format = self.property_value('ui.time-format')
try:
# (adim) I can't find a way to parse a Time with a custom format
date = strptime(value, format) # this returns a DateTime
# (adim) I can't find a way to parse a time with a custom format
date = strptime(value, format) # this returns a datetime
return time(date.hour, date.minute, date.second)
except ValueError:
raise ValueError(self._('can\'t parse %(value)r (expected %(format)s)')
......
This diff is collapsed.
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
......@@ -29,7 +29,6 @@ from __future__ import print_function
__docformat__ = "restructuredtext en"
import threading
from warnings import warn
from itertools import chain
from time import time, localtime, strftime
......@@ -51,10 +50,13 @@ from cubicweb import cwvreg, schema, server
from cubicweb.server import ShuttingDown, utils, hook, querier, sources
from cubicweb.server.session import Session, InternalManager
NO_CACHE_RELATIONS = set( [('owned_by', 'object'),
('created_by', 'object'),
('cw_source', 'object'),
])
NO_CACHE_RELATIONS = set([
('owned_by', 'object'),
('created_by', 'object'),
('cw_source', 'object'),
])
def prefill_entity_caches(entity):
cnx = entity._cw
......@@ -74,6 +76,7 @@ def prefill_entity_caches(entity):
continue
entity.cw_set_relation_cache(rtype, 'object', cnx.empty_rset())
def del_existing_rel_if_needed(cnx, eidfrom, rtype, eidto):
"""delete existing relation when adding a new one if card is 1 or ?
......@@ -120,7 +123,7 @@ def preprocess_inlined_relations(cnx, entity):
eschema = entity.e_schema
for attr in entity.cw_edited:
rschema = eschema.subjrels[attr]
if not rschema.final: # inlined relation
if not rschema.final: # inlined relation
value = entity.cw_edited[attr]
relations.append((attr, value))
cnx.update_rel_cache_add(entity.eid, attr, value)
......@@ -128,7 +131,7 @@ def preprocess_inlined_relations(cnx, entity):
if rdef.cardinality[1] in '1?' and activeintegrity:
with cnx.security_enabled(read=False):
cnx.execute('DELETE X %s Y WHERE Y eid %%(y)s' % attr,
{'x': entity.eid, 'y': value})
{'x': entity.eid, 'y': value})
return relations
......@@ -168,7 +171,7 @@ class Repository(object):
self._running_threads = []
# initial schema, should be build or replaced latter
self.schema = schema.CubicWebSchema(config.appid)
self.vreg.schema = self.schema # until actual schema is loaded...
self.vreg.schema = self.schema # until actual schema is loaded...
# shutdown flag
self.shutting_down = False
# sources (additional sources info in the system database)
......@@ -186,6 +189,7 @@ class Repository(object):
self.init_cnxset_pool()
# the hooks manager
self.hm = hook.HooksManager(self.vreg)
# registry hook to fix user class on registry reload
@onevent('after-registry-reload', self)
def fix_user_classes(self):
......@@ -247,7 +251,8 @@ class Repository(object):
# 4. close initialization connection set and reopen fresh ones for
# proper initialization
self._get_cnxset().close(True)
self.cnxsets = [] # list of available cnxsets (can't iterate on a Queue)
# list of available cnxsets (can't iterate on a Queue)
self.cnxsets = []
for i in range(config['connections-pool-size']):
self.cnxsets.append(self.system_source.wrapped_connection())
self._cnxsets_pool.put_nowait(self.cnxsets[-1])
......@@ -256,15 +261,14 @@ class Repository(object):
def init_sources_from_database(self):
self.sources_by_eid = {}
if self.config.quick_start \
or not 'CWSource' in self.schema: # # 3.10 migration
if self.config.quick_start or 'CWSource' not in self.schema: # 3.10 migration
self.system_source.init_creating()
return
with self.internal_cnx() as cnx:
# FIXME: sources should be ordered (add_entity priority)
for sourceent in cnx.execute(
'Any S, SN, SA, SC WHERE S is_instance_of CWSource, '
'S name SN, S type SA, S config SC').entities():
'Any S, SN, SA, SC WHERE S is_instance_of CWSource, '
'S name SN, S type SA, S config SC').entities():
if sourceent.name == 'system':
self.system_source.eid = sourceent.eid
self.sources_by_eid[sourceent.eid] = self.system_source
......@@ -349,8 +353,9 @@ class Repository(object):
# register a task to cleanup expired session
self.cleanup_session_time = self.config['cleanup-session-time'] or 60 * 60 * 24
assert self.cleanup_session_time > 0
cleanup_session_interval = min(60*60, self.cleanup_session_time / 3)
assert self._tasks_manager is not None, "This Repository is not intended to be used as a server"
cleanup_session_interval = min(60 * 60, self.cleanup_session_time / 3)
assert self._tasks_manager is not None, \
"This Repository is not intended to be used as a server"
self._tasks_manager.add_looping_task(cleanup_session_interval,
self.clean_sessions)
......@@ -365,7 +370,8 @@ class Repository(object):
XXX __init__ or in external codes (various server managers).
"""
self._prepare_startup()
assert self._tasks_manager is not None, "This Repository is not intended to be used as a server"
assert self._tasks_manager is not None,\
"This Repository is not intended to be used as a server"
self._tasks_manager.start()
def looping_task(self, interval, func, *args):
......@@ -374,14 +380,14 @@ class Repository(object):
looping tasks can only be registered during repository initialization,
once done this method will fail.
"""
assert self._tasks_manager is not None, "This Repository is not intended to be used as a server"
assert self._tasks_manager is not None,\
"This Repository is not intended to be used as a server"
self._tasks_manager.add_looping_task(interval, func, *args)
def threaded_task(self, func):
"""start function in a separated thread"""
utils.RepoThread(func, self._running_threads).start()
#@locked
def _get_cnxset(self):
try:
return self._cnxsets_pool.get(True, timeout=5)
......@@ -430,8 +436,8 @@ class Repository(object):
hits, misses = self.system_source.cache_hit, self.system_source.cache_miss
self.info('sql cache hit/miss: %s/%s (%s%% hits)', hits, misses,
(hits * 100) / (hits + misses))
nocache = self.system_source.no_cache
self.info('sql cache usage: %s/%s (%s%%)', hits+ misses, nocache,
nocache = self.system_source.no_cache
self.info('sql cache usage: %s/%s (%s%%)', hits + misses, nocache,
((hits + misses) * 100) / (hits + misses + nocache))
except ZeroDivisionError:
pass
......@@ -458,7 +464,7 @@ class Repository(object):
eid = self.check_auth_info(cnx, login, authinfo)
cwuser = self._build_user(cnx, eid)
if self.config.consider_user_state and \
not cwuser.cw_adapt_to('IWorkflowable').state in cwuser.AUTHENTICABLE_STATES:
not cwuser.cw_adapt_to('IWorkflowable').state in cwuser.AUTHENTICABLE_STATES:
raise AuthenticationError('user is not in authenticable state')
return cwuser
......@@ -480,7 +486,7 @@ class Repository(object):
# public (dbapi) interface ################################################
@deprecated("[3.19] use _cw.call_service('repo_stats')")
def stats(self): # XXX restrict to managers session?
def stats(self): # XXX restrict to managers session?
"""Return a dictionary containing some statistics about the repository
resources usage.
......@@ -548,8 +554,8 @@ class Repository(object):
vcconf = {}
with self.internal_cnx() as cnx:
for pk, version in cnx.execute(
'Any K,V WHERE P is CWProperty, P value V, P pkey K, '
'P pkey ~="system.version.%"', build_descr=False):
'Any K,V WHERE P is CWProperty, P value V, P pkey K, '
'P pkey ~="system.version.%"', build_descr=False):
cube = pk.split('.')[-1]
# XXX cubicweb migration
if cube in CW_MIGRATION_MAP:
......@@ -692,8 +698,7 @@ class Repository(object):
connections have all hooks beside security enabled.
"""
with Session(InternalManager(), self).new_cnx() as cnx:
cnx.user._cw = cnx # XXX remove when "vreg = user._cw.vreg"
# hack in entity.py is gone
cnx.user._cw = cnx # XXX remove when "vreg = user._cw.vreg" hack in entity.py is gone
with cnx.security_enabled(read=False, write=False):
yield cnx
......@@ -732,12 +737,12 @@ class Repository(object):
rqlcache = self.querier._rql_cache
for eid in eids:
try:
etype, extid, auri = etcache.pop(int(eid)) # may be a string in some cases
rqlcache.pop( ('%s X WHERE X eid %s' % (etype, eid),), None)
etype, extid, auri = etcache.pop(int(eid)) # may be a string in some cases
rqlcache.pop(('%s X WHERE X eid %s' % (etype, eid),), None)
extidcache.pop(extid, None)
except KeyError:
etype = None
rqlcache.pop( ('Any X WHERE X eid %s' % eid,), None)
rqlcache.pop(('Any X WHERE X eid %s' % eid,), None)
self.system_source.clear_eid_cache(eid, etype)
def type_from_eid(self, eid, cnx):
......@@ -846,7 +851,7 @@ class Repository(object):
with cnx.running_hooks_ops():
for rschema, _, role in entities[0].e_schema.relation_definitions():
if rschema.rule:
continue # computed relation
continue # computed relation
rtype = rschema.type
if rtype in schema.VIRTUAL_RTYPES or rtype in pendingrtypes:
continue
......@@ -861,9 +866,10 @@ class Repository(object):
except ValidationError:
raise
except Unauthorized:
self.exception('Unauthorized exception while cascading delete for entity %s. '
'RQL: %s.\nThis should not happen since security is disabled here.',
entities, rql)
self.exception(
'Unauthorized exception while cascading delete for entity %s. '
'RQL: %s.\nThis should not happen since security is disabled here.',
entities, rql)
raise
except Exception:
if self.config.mode == 'test':
......@@ -891,7 +897,7 @@ class Repository(object):
the entity instance
"""
entity = edited.entity
entity._cw_is_saved = False # entity has an eid but is not yet saved
entity._cw_is_saved = False # entity has an eid but is not yet saved
# init edited_attributes before calling before_add_entity hooks
entity.cw_edited = edited
source = self.system_source
......@@ -920,9 +926,9 @@ class Repository(object):
# call hooks for inlined relations
for attr, value in relations:
self.hm.call_hooks('before_add_relation', cnx,
eidfrom=entity.eid, rtype=attr, eidto=value)
eidfrom=entity.eid, rtype=attr, eidto=value)
self.hm.call_hooks('after_add_relation', cnx,
eidfrom=entity.eid, rtype=attr, eidto=value)
eidfrom=entity.eid, rtype=attr, eidto=value)
return entity.eid
def glob_update_entity(self, cnx, edited):
......@@ -954,7 +960,7 @@ class Repository(object):
# inlined relation
previous_value = entity.related(attr) or None
if previous_value is not None:
previous_value = previous_value[0][0] # got a result set
previous_value = previous_value[0][0] # got a result set
if previous_value == entity.cw_attr_cache[attr]:
previous_value = None
else:
......@@ -996,7 +1002,6 @@ class Repository(object):
if orig_edited is not None:
entity.cw_edited = orig_edited
def glob_delete_entities(self, cnx, eids):
"""delete a list of entities and all related entities from the repository"""
# mark eids as being deleted in cnx info and setup cache update
......@@ -1009,7 +1014,7 @@ class Repository(object):
eids = frozenset(eids)
eids = eids - op._container
op._container |= eids
data_by_etype = {} # values are [list of entities]
data_by_etype = {} # values are [list of entities]
#
# WARNING: the way this dictionary is populated is heavily optimized
# and does not use setdefault on purpose. Unless a new release
......@@ -1026,7 +1031,7 @@ class Repository(object):
source = self.system_source
for etype, entities in data_by_etype.items():
if server.DEBUG & server.DBG_REPO:
print('DELETE entities', etype, [entity.eid for entity in entities])
print('DELETE entities', etype, [e.eid for e in entities])
self.hm.call_hooks('before_delete_entity', cnx, entities=entities)
self._delete_cascade_multi(cnx, entities)
source.delete_entities(cnx, entities)
......@@ -1111,13 +1116,11 @@ class Repository(object):
self.hm.call_hooks('after_delete_relation', cnx,
eidfrom=subject, rtype=rtype, eidto=object)
# these are overridden by set_log_methods below
# only defining here to prevent pylint from complaining
info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None
from logging import getLogger
from cubicweb import set_log_methods
set_log_methods(Repository, getLogger('cubicweb.repository'))
# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
......@@ -20,12 +20,13 @@ from __future__ import print_function
__docformat__ = "restructuredtext en"
import functools
import sys
from time import time
from uuid import uuid4
from warnings import warn
import functools
from contextlib import contextmanager
from logging import getLogger
from six import text_type
......@@ -33,7 +34,8 @@ from logilab.common.deprecation import deprecated
from logilab.common.textutils import unormalize
from logilab.common.registry import objectify_predicate