# HG changeset patch # User Sylvain Thénault # Date 1255958201 -7200 # Node ID 5376aaadd16bfa31e6e5454a7cf57b0baa1a32bf # Parent 29f74716fd70365ff1b3a69e50d47a7650f2344a# Parent 7547fe738e54449c5596030f136a4a48e5a1e2e4 backport stable diff -r 29f74716fd70 -r 5376aaadd16b __init__.py diff -r 29f74716fd70 -r 5376aaadd16b common/migration.py --- a/common/migration.py Thu Oct 15 11:20:26 2009 +0200 +++ b/common/migration.py Mon Oct 19 15:16:41 2009 +0200 @@ -92,7 +92,9 @@ def __init__(self, config, interactive=True, verbosity=1): self.config = config - self.config.init_log(logthreshold=logging.ERROR, debug=True) + if config: + # no config on shell to a remote instance + self.config.init_log(logthreshold=logging.ERROR, debug=True) # 0: no confirmation, 1: only main commands confirmed, 2 ask for everything self.verbosity = verbosity self.need_wrap = True @@ -144,7 +146,7 @@ ctx['versions_map'] = vmap if self.config.accept_mode('Any') and 'cubicweb' in vmap: migrdir = self.config.migration_scripts_dir() - self.process_script(join(migrdir, 'bootstrapmigration_repository.py')) + self.cmd_process_script(join(migrdir, 'bootstrapmigration_repository.py')) for cube, fromversion, toversion in toupgrade: if cube == 'cubicweb': migrdir = self.config.migration_scripts_dir() @@ -159,7 +161,7 @@ if prevversion is not None and version != prevversion: self.cube_upgraded(cube, prevversion) prevversion = version - self.process_script(script) + self.cmd_process_script(script) self.cube_upgraded(cube, toversion) else: self.cube_upgraded(cube, toversion) @@ -261,7 +263,7 @@ context[attr[4:]] = getattr(self, attr) return context - def process_script(self, migrscript, funcname=None, *args, **kwargs): + def cmd_process_script(self, migrscript, funcname=None, *args, **kwargs): """execute a migration script in interactive mode, display the migration script path, ask for confirmation and execute it if confirmed diff -r 29f74716fd70 -r 5376aaadd16b cwctl.py --- a/cwctl.py Thu Oct 15 11:20:26 2009 +0200 +++ b/cwctl.py Mon Oct 19 15:16:41 2009 +0200 @@ -685,10 +685,16 @@ class ShellCommand(Command): - """Run an interactive migration shell. This is a python shell with - enhanced migration commands predefined in the namespace. An additional - argument may be given corresponding to a file containing commands to - execute in batch mode. + """Run an interactive migration shell on an instance. This is a python shell + with enhanced migration commands predefined in the namespace. An additional + argument may be given corresponding to a file containing commands to execute + in batch mode. + + By default it will connect to a local instance using an in memory + connection, unless -P option is specified, in which case you will be + connected through pyro. In the later case, you won't have access to + repository internals (session, etc...) so most migration commands won't be + available. the identifier of the instance to connect. @@ -698,46 +704,87 @@ options = ( ('system-only', {'short': 'S', 'action' : 'store_true', - 'default': False, 'help': 'only connect to the system source when the instance is ' 'using multiple sources. You can\'t use this option and the ' - '--ext-sources option at the same time.'}), + '--ext-sources option at the same time.', + 'group': 'local' + }), ('ext-sources', {'short': 'E', 'type' : 'csv', 'metavar': '', - 'default': None, 'help': "For multisources instances, specify to which sources the \ repository should connect to for upgrading. When unspecified or 'all' given, \ will connect to all defined sources. If 'migration' is given, appropriate \ sources for migration will be automatically selected.", + 'group': 'local' }), ('force', {'short': 'f', 'action' : 'store_true', - 'default' : False, - 'help': 'don\'t check instance is up to date.'} - ), + 'help': 'don\'t check instance is up to date.', + 'group': 'local' + }), + + ('pyro', + {'short': 'P', 'action' : 'store_true', + 'help': 'connect to a running instance through Pyro.', + 'group': 'remote', + }), + ('pyro-ns-host', + {'short': 'H', 'type' : 'string', 'metavar': '', + 'help': 'Pyro name server host. If not set, will be detected by ' + 'using a broadcast query.', + 'group': 'remote' + }), ) def run(self, args): appid = pop_arg(args, 99, msg="No instance specified !") - config = cwcfg.config_for(appid) - if self.config.ext_sources: - assert not self.config.system_only - sources = self.config.ext_sources - elif self.config.system_only: - sources = ('system',) + if self.config.pyro: + from cubicweb import AuthenticationError + from cubicweb.dbapi import connect + from cubicweb.server.utils import manager_userpasswd + from cubicweb.server.migractions import ServerMigrationHelper + while True: + try: + login, pwd = manager_userpasswd(msg=None) + cnx = connect(appid, login=login, password=pwd, + host=self.config.pyro_ns_host, mulcnx=False) + except AuthenticationError, ex: + print ex + except (KeyboardInterrupt, EOFError): + print + sys.exit(0) + else: + break + cnx.load_appobjects() + repo = cnx._repo + mih = ServerMigrationHelper(None, repo=repo, cnx=cnx, + # hack so it don't try to load fs schema + schema=1) else: - sources = ('all',) - config.set_sources_mode(sources) - config.repairing = self.config.force - mih = config.migration_handler() - if args: - for arg in args: - mih.process_script(arg) - else: - mih.interactive_shell() - mih.shutdown() + config = cwcfg.config_for(appid) + if self.config.ext_sources: + assert not self.config.system_only + sources = self.config.ext_sources + elif self.config.system_only: + sources = ('system',) + else: + sources = ('all',) + config.set_sources_mode(sources) + config.repairing = self.config.force + mih = config.migration_handler() + try: + if args: + for arg in args: + mih.cmd_process_script(arg) + else: + mih.interactive_shell() + finally: + if not self.config.pyro: + mih.shutdown() + else: + cnx.close() class RecompileInstanceCatalogsCommand(InstanceCommand): diff -r 29f74716fd70 -r 5376aaadd16b cwvreg.py --- a/cwvreg.py Thu Oct 15 11:20:26 2009 +0200 +++ b/cwvreg.py Mon Oct 19 15:16:41 2009 +0200 @@ -29,7 +29,7 @@ def use_interfaces(obj): - """return interfaces used by the given object by searchinf for implements + """return interfaces used by the given object by searching for implements selectors, with a bw compat fallback to accepts_interfaces attribute """ from cubicweb.selectors import implements @@ -62,16 +62,28 @@ pass @deprecated('[3.6] select object, then use obj.render()') - def render(self, __oid, req, __fallback_oid=None, rset=None, **kwargs): - """select object, or fallback object if specified and the first one - isn't selectable, then render it + def render(self, __oid, req, __fallback_oid=None, rset=None, initargs=None, + **kwargs): + """Select object with the given id (`__oid`) then render it. If the + object isn't selectable, try to select fallback object if + `__fallback_oid` is specified. + + If specified `initargs` is expected to be a dictionnary containing + arguments that should be given to selection (hence to object's __init__ + as well), but not to render(). Other arbitrary keyword arguments will be + given to selection *and* to render(), and so should be handled by + object's call or cell_call method.. """ + if initargs is None: + initargs = kwargs + else: + initargs.update(kwargs) try: - obj = self.select(__oid, req, rset=rset, **kwargs) + obj = self.select(__oid, req, rset=rset, **initargs) except NoSelectableObject: if __fallback_oid is None: raise - obj = self.select(__fallback_oid, req, rset=rset, **kwargs) + obj = self.select(__fallback_oid, req, rset=rset, **initargs) return obj.render(**kwargs) @deprecated('[3.6] use select_or_none and test for obj.cw_propval("visible")') @@ -305,9 +317,11 @@ self.register_objects(searchpath, force_reload=False) # map lowered entity type names to their actual name self.case_insensitive_etypes = {} - for etype in self.schema.entities(): - etype = str(etype) + for eschema in self.schema.entities(): + etype = str(eschema) self.case_insensitive_etypes[etype.lower()] = etype + clear_cache(eschema, 'ordered_relations') + clear_cache(eschema, 'meta_attributes') def _set_schema(self, schema): """set instance'schema""" @@ -379,7 +393,7 @@ implemented_interfaces = set() if 'Any' in self.get('etypes', ()): for etype in self.schema.entities(): - if etype.is_final(): + if etype.final: continue cls = self['etypes'].etype_class(etype) for iface in cls.__implements__: diff -r 29f74716fd70 -r 5376aaadd16b dbapi.py --- a/dbapi.py Thu Oct 15 11:20:26 2009 +0200 +++ b/dbapi.py Mon Oct 19 15:16:41 2009 +0200 @@ -448,7 +448,7 @@ return self._repo.get_schema() def load_appobjects(self, cubes=_MARKER, subpath=None, expand=True, - force_reload=None): + force_reload=None): config = self.vreg.config if cubes is _MARKER: cubes = self._repo.get_cubes() diff -r 29f74716fd70 -r 5376aaadd16b devtools/devctl.py --- a/devtools/devctl.py Thu Oct 15 11:20:26 2009 +0200 +++ b/devtools/devctl.py Mon Oct 19 15:16:41 2009 +0200 @@ -144,13 +144,13 @@ if etype not in libschema: add_msg(w, etype) add_msg(w, '%s_plural' % etype) - if not eschema.is_final(): + if not eschema.final: add_msg(w, 'This %s' % etype) add_msg(w, 'New %s' % etype) if eschema.description and not eschema.description in done: done.add(eschema.description) add_msg(w, eschema.description) - if eschema.is_final(): + if eschema.final: continue for rschema, targetschemas, role in eschema.relation_definitions(True): for tschema in targetschemas: @@ -201,7 +201,7 @@ for subjschema in rschema.subjects(): if not subjschema in libsubjects: add_msg(w, rtype, subjschema.type) - if not (schema.rschema(rtype).is_final() or rschema.symetric): + if not (schema.rschema(rtype).final or rschema.symetric): if rschema not in no_context_rtypes: libobjects = librschema and librschema.objects() or () for objschema in rschema.objects(): diff -r 29f74716fd70 -r 5376aaadd16b devtools/fill.py --- a/devtools/fill.py Thu Oct 15 11:20:26 2009 +0200 +++ b/devtools/fill.py Mon Oct 19 15:16:41 2009 +0200 @@ -347,7 +347,7 @@ queries = [] # 1/ skip final relations and explictly ignored relations rels = [rschema for rschema in self.schema.relations() - if not (rschema.is_final() or rschema in ignored_relations)] + if not (rschema.final or rschema in ignored_relations)] # for each relation # 2/ take each possible couple (subj, obj) # 3/ analyze cardinality of relation @@ -397,9 +397,12 @@ restrictions = ', '.join(c.restriction for c in constraints) q += ', %s' % restrictions # restrict object eids if possible + # XXX the attempt to restrict below in completely wrong + # disabling it for now objeids = select(restrictions, self.cursor) else: objeids = oedict.get(obj, frozenset()) +## objeids = oedict.get(obj, frozenset()) if subjcard in '?1' or objcard in '?1': for subjeid, objeid in used: if subjcard in '?1' and subjeid in subjeids: diff -r 29f74716fd70 -r 5376aaadd16b devtools/testlib.py --- a/devtools/testlib.py Thu Oct 15 11:20:26 2009 +0200 +++ b/devtools/testlib.py Mon Oct 19 15:16:41 2009 +0200 @@ -45,7 +45,6 @@ file('/tmp/toto.html', 'w').write(data) webbrowser.open('file:///tmp/toto.html') - def line_context_filter(line_no, center, before=3, after=None): """return true if line are in context @@ -715,7 +714,7 @@ # compute how many entities by type we need to be able to satisfy relation constraint relmap = {} for rschema in schema.relations(): - if rschema.is_final(): + if rschema.final: continue for subj, obj in rschema.iter_rdefs(): card = rschema.rproperty(subj, obj, 'cardinality') @@ -759,6 +758,7 @@ def post_populate(self, cursor): pass + @nocoverage def auto_populate(self, how_many): """this method populates the database with `how_many` entities @@ -779,9 +779,9 @@ rset = cu.execute('%s X' % etype) edict[str(etype)] = set(row[0] for row in rset.rows) existingrels = {} - ignored_relations = SYSTEM_RELATIONS | set(self.ignored_relations) + ignored_relations = SYSTEM_RELATIONS + self.ignored_relations for rschema in self.schema.relations(): - if rschema.is_final() or rschema in ignored_relations: + if rschema.final or rschema in ignored_relations: continue rset = cu.execute('DISTINCT Any X,Y WHERE X %s Y' % rschema) existingrels.setdefault(rschema.type, set()).update((x, y) for x, y in rset) diff -r 29f74716fd70 -r 5376aaadd16b doc/book/en/annexes/rql/language.rst --- a/doc/book/en/annexes/rql/language.rst Thu Oct 15 11:20:26 2009 +0200 +++ b/doc/book/en/annexes/rql/language.rst Mon Oct 19 15:16:41 2009 +0200 @@ -11,13 +11,9 @@ :: - DISTINCT, INSERT, SET, DELETE, - WHERE, AND, OR, NOT, EXISTS, - IN, LIKE, UNION, WITH, BEING, - TRUE, FALSE, NULL, TODAY, NOW, - LIMIT, OFFSET, - HAVING, GROUPBY, ORDERBY, ASC, DESC - + AND, ASC, BEING, DELETE, DESC, DISTINCT, EXISTS, FALSE, GROUPBY, + HAVING, ILIKE, IN, INSERT, LIKE, LIMIT, NOT, NOW, NULL, OFFSET, + OR, ORDERBY, SET, TODAY, TRUE, UNION, WHERE, WITH Variables and Typing ~~~~~~~~~~~~~~~~~~~~ @@ -76,7 +72,7 @@ ```````````````````` :: - =, <, <=, >=, >, ~=, IN, LIKE + =, <, <=, >=, >, ~=, IN, LIKE, ILIKE * The operator `=` is the default operator. @@ -88,6 +84,8 @@ Any X WHERE X name ~= 'Th%' Any X WHERE X name LIKE '%lt' +* The operator `ILIKE` is the case insensitive version of `LIKE`. + * The operator `IN` provides a list of possible values: :: diff -r 29f74716fd70 -r 5376aaadd16b entities/__init__.py --- a/entities/__init__.py Thu Oct 15 11:20:26 2009 +0200 +++ b/entities/__init__.py Mon Oct 19 15:16:41 2009 +0200 @@ -63,7 +63,7 @@ def dc_description(self, format='text/plain'): """return a suitable description for this entity""" - if self.e_schema.has_subject_relation('description'): + if 'description' in self.e_schema.subjrels: return self.printable_value('description', format=format) return u'' diff -r 29f74716fd70 -r 5376aaadd16b entities/wfobjs.py --- a/entities/wfobjs.py Thu Oct 15 11:20:26 2009 +0200 +++ b/entities/wfobjs.py Mon Oct 19 15:16:41 2009 +0200 @@ -446,15 +446,12 @@ kwargs['comment'] = comment if commentformat is not None: kwargs['comment_format'] = commentformat - args = [('wf_info_for', 'E')] - kwargs['E'] = self.eid + kwargs['wf_info_for'] = self if treid is not None: - args.append( ('by_transition', 'T') ) - kwargs['T'] = treid + kwargs['by_transition'] = self.req.entity_from_eid(treid) if tseid is not None: - args.append( ('to_state', 'S') ) - kwargs['S'] = tseid - return self._cw.create_entity('TrInfo', *args, **kwargs) + kwargs['to_state'] = self.req.entity_from_eid(tseid) + return self._cw.create_entity('TrInfo', **kwargs) def fire_transition(self, tr, comment=None, commentformat=None): """change the entity's state by firing transition of the given name in diff -r 29f74716fd70 -r 5376aaadd16b entity.py --- a/entity.py Thu Oct 15 11:20:26 2009 +0200 +++ b/entity.py Mon Oct 19 15:16:41 2009 +0200 @@ -139,7 +139,7 @@ _fetchattrs = [] for attr in fetchattrs: try: - rschema = eschema.subject_relation(attr) + rschema = eschema.subjrels[attr] except KeyError: cls.warning('skipping fetch_attr %s defined in %s (not found in schema)', attr, cls.__regid__) @@ -150,7 +150,7 @@ selection.append(var) restriction = '%s %s %s' % (mainvar, attr, var) restrictions.append(restriction) - if not rschema.is_final(): + if not rschema.final: # XXX this does not handle several destination types desttype = rschema.objects(eschema.type)[0] card = rschema.rproperty(eschema, desttype, 'cardinality')[0] @@ -184,7 +184,7 @@ needcheck = not cls.e_schema.has_unique_values(mainattr) else: for rschema in cls.e_schema.subject_relations(): - if rschema.is_final() and rschema != 'eid' and cls.e_schema.has_unique_values(rschema): + if rschema.final and rschema != 'eid' and cls.e_schema.has_unique_values(rschema): mainattr = str(rschema) needcheck = False break @@ -383,7 +383,7 @@ assert self.has_eid() execute = self._cw.execute for rschema in self.e_schema.subject_relations(): - if rschema.is_final() or rschema.meta: + if rschema.final or rschema.meta: continue # skip already defined relations if getattr(self, rschema.type): @@ -431,7 +431,7 @@ def to_complete_relations(self): """by default complete final relations to when calling .complete()""" for rschema in self.e_schema.subject_relations(): - if rschema.is_final(): + if rschema.final: continue if len(rschema.objects(self.e_schema)) > 1: # ambigous relations, the querier doesn't handle @@ -591,14 +591,14 @@ if targettypes is None: targettypes = rschema.objects(self.e_schema) else: - restriction += 'E is IN (%s)' % ','.join(targettypes) + restriction += ', X is IN (%s)' % ','.join(targettypes) card = greater_card(rschema, (self.e_schema,), targettypes, 0) else: restriction = 'E eid %%(x)s, X %s E' % rtype if targettypes is None: targettypes = rschema.subjects(self.e_schema) else: - restriction += 'E is IN (%s)' % ','.join(targettypes) + restriction += ', X is IN (%s)' % ','.join(targettypes) card = greater_card(rschema, targettypes, (self.e_schema,), 1) if len(targettypes) > 1: fetchattrs_list = [] @@ -706,7 +706,7 @@ else raise `KeyError` """ res = self._related_cache['%s_%s' % (rtype, role)][entities] - if limit is not None: + if limit is not None and limit < len(res): if entities: res = res[:limit] else: diff -r 29f74716fd70 -r 5376aaadd16b goa/__init__.py --- a/goa/__init__.py Thu Oct 15 11:20:26 2009 +0200 +++ b/goa/__init__.py Mon Oct 19 15:16:41 2009 +0200 @@ -65,7 +65,7 @@ edef.name = edef.name.encode() assert re.match(r'[A-Z][A-Za-z0-9]*[a-z]+[0-9]*$', edef.name), repr(edef.name) eschema = super(CubicWebSchema, self).add_entity_type(edef) - if not eschema.is_final(): + if not eschema.final: # automatically add the eid relation to non final entity types rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Bytes', cardinality='?1', uid=True) diff -r 29f74716fd70 -r 5376aaadd16b goa/appobjects/components.py --- a/goa/appobjects/components.py Thu Oct 15 11:20:26 2009 +0200 +++ b/goa/appobjects/components.py Mon Oct 19 15:16:41 2009 +0200 @@ -67,7 +67,7 @@ """ req = self.req for eschema in eschemas: - if eschema.is_final() or not (eschema.has_perm(req, 'read') or + if eschema.final or not (eschema.has_perm(req, 'read') or eschema.has_local_role('read')): continue etype = eschema.type diff -r 29f74716fd70 -r 5376aaadd16b goa/appobjects/dbmgmt.py --- a/goa/appobjects/dbmgmt.py Thu Oct 15 11:20:26 2009 +0200 +++ b/goa/appobjects/dbmgmt.py Mon Oct 19 15:16:41 2009 +0200 @@ -175,7 +175,7 @@ # XXX should use unsafe_execute with all hooks deactivated # XXX step by catching datastore errors? for eschema in self.schema.entities(): - if eschema.is_final() or eschema in self.skip_etypes: + if eschema.final or eschema in self.skip_etypes: continue self.req.execute('DELETE %s X' % eschema) self.w(u'deleted all %s entities
' % eschema) diff -r 29f74716fd70 -r 5376aaadd16b goa/db.py --- a/goa/db.py Thu Oct 15 11:20:26 2009 +0200 +++ b/goa/db.py Mon Oct 19 15:16:41 2009 +0200 @@ -148,7 +148,7 @@ def __initialize__(cls): super(Model, cls).__initialize__() cls._attributes = frozenset(rschema for rschema in cls.e_schema.subject_relations() - if rschema.is_final()) + if rschema.final) def __init__(self, *args, **kwargs): # db.Model prototype: @@ -163,7 +163,7 @@ super(Model, self).__init__(None, None) # if Model instances are given in kwargs, turn them into db model for key, val in kwargs.iteritems(): - if key in self.e_schema.subject_relations() and not self.e_schema.schema[key].is_final(): + if key in self.e_schema.subject_relations() and not self.e_schema.schema[key].final: if isinstance(kwargs, (list, tuple)): val = [isinstance(x, Model) and x._dbmodel or x for x in val] elif isinstance(val, Model): diff -r 29f74716fd70 -r 5376aaadd16b goa/dbinit.py --- a/goa/dbinit.py Thu Oct 15 11:20:26 2009 +0200 +++ b/goa/dbinit.py Mon Oct 19 15:16:41 2009 +0200 @@ -90,7 +90,7 @@ eschema = schema.eschema('CWEType') execute(rql, {'name': u'CWEType', 'descr': unicode(eschema.description)}) for eschema in schema.entities(): - if eschema.is_final() or eschema == 'CWEType': + if eschema.final or eschema == 'CWEType': continue execute(rql, {'name': unicode(eschema), 'descr': unicode(eschema.description)}) diff -r 29f74716fd70 -r 5376aaadd16b goa/overrides/rqlannotation.py --- a/goa/overrides/rqlannotation.py Thu Oct 15 11:20:26 2009 +0200 +++ b/goa/overrides/rqlannotation.py Mon Oct 19 15:16:41 2009 +0200 @@ -13,7 +13,7 @@ def __init__(self, schema): self.schema = schema self.nfdomain = frozenset(eschema.type for eschema in schema.entities() - if not eschema.is_final()) + if not eschema.final) def annotate(self, rqlst): rqlst.has_text_query = False rqlst.need_distinct = False diff -r 29f74716fd70 -r 5376aaadd16b goa/rqlinterpreter.py --- a/goa/rqlinterpreter.py Thu Oct 15 11:20:26 2009 +0200 +++ b/goa/rqlinterpreter.py Mon Oct 19 15:16:41 2009 +0200 @@ -156,7 +156,7 @@ myvar = self.rhs.name ovar = self.var.name rtype = self.rtype - if self.schema.rschema(rtype).is_final(): + if self.schema.rschema(rtype).final: # should be detected by rql.stcheck: "Any C WHERE NOT X attr C" doesn't make sense #if self._not: # raise NotImplementedError() @@ -595,7 +595,7 @@ # ok, we *may* process this Not node (not implemented error will be # raised later if we can't) extra[node.parent] = True - if rschema.is_final(): + if rschema.final: self._visit_final_relation(rschema, node, constraints, extra) elif neged: self._visit_non_final_neged_relation(rschema, node, constraints) diff -r 29f74716fd70 -r 5376aaadd16b hooks/integrity.py --- a/hooks/integrity.py Thu Oct 15 11:20:26 2009 +0200 +++ b/hooks/integrity.py Mon Oct 19 15:16:41 2009 +0200 @@ -63,8 +63,11 @@ __abstract__ = True category = 'integrity' +class UserIntegrityHook(IntegrityHook): + __select__ == IntegrityHook.__select__ & ~regular_session() -class CheckCardinalityHook(IntegrityHook): + +class CheckCardinalityHook(UserIntegrityHook): """check cardinalities are satisfied""" __regid__ = 'checkcard' events = ('after_add_entity', 'before_delete_relation') @@ -139,7 +142,7 @@ pass -class CheckConstraintHook(IntegrityHook): +class CheckConstraintHook(UserIntegrityHook): """check the relation satisfy its constraints this is delayed to a precommit time operation since other relation which @@ -155,7 +158,7 @@ _CheckConstraintsOp(self._cw, constraints=constraints, rdef=(self.eidfrom, self.rtype, self.eidto)) -class CheckAttributeConstraintHook(IntegrityHook): +class CheckAttributeConstraintHook(UserIntegrityHook): """check the attribute relation satisfy its constraints this is delayed to a precommit time operation since other relation which @@ -168,7 +171,7 @@ schema = self._cw.vreg.schema entity = self.entity for attr in entity.edited_attributes: - if schema.rschema(attr).is_final(): + if schema.rschema(attr).final: constraints = [c for c in entity.e_schema.constraints(attr) if isinstance(c, RQLVocabularyConstraint)] if constraints: @@ -176,7 +179,7 @@ rdef=(entity.eid, attr, None)) -class CheckUniqueHook(IntegrityHook): +class CheckUniqueHook(UserIntegrityHook): __regid__ = 'checkunique' events = ('before_add_entity', 'before_update_entity') @@ -184,7 +187,7 @@ entity = self.entity eschema = entity.e_schema for attr in entity.edited_attributes: - if eschema.subject_relation(attr).is_final() and \ + if eschema.subject_relation(attr).final and \ eschema.has_unique_values(attr): val = entity[attr] if val is None: @@ -253,7 +256,7 @@ self.entity['name'] = newname -class TidyHtmlFields(IntegrityHook): +class TidyHtmlFields(UserIntegrityHook): """tidy HTML in rich text strings""" __regid__ = 'htmltidy' events = ('before_add_entity', 'before_update_entity') diff -r 29f74716fd70 -r 5376aaadd16b hooks/metadata.py --- a/hooks/metadata.py Thu Oct 15 11:20:26 2009 +0200 +++ b/hooks/metadata.py Mon Oct 19 15:16:41 2009 +0200 @@ -80,14 +80,18 @@ session = self._cw entity = self.entity try: - session.add_relation(entity.eid, 'is', - eschema_type_eid(session, entity.__regid__)) + #session.add_relation(entity.eid, 'is', + # eschema_type_eid(session, entity.__regid__)) + session.system_sql('INSERT INTO is_relation(eid_from,eid_to) VALUES (%s,%s)' + % (entity.eid, eschema_type_eid(session, entity.id))) except IndexError: # during schema serialization, skip return for etype in entity.e_schema.ancestors() + [entity.e_schema]: - session.add_relation(entity.eid, 'is_instance_of', - eschema_type_eid(session, etype)) + #session.add_relation(entity.eid, 'is_instance_of', + # eschema_type_eid(session, etype)) + session.system_sql('INSERT INTO is_instance_of_relation(eid_from,eid_to) VALUES (%s,%s)' + % (entity.eid, eschema_type_eid(session, etype))) class SetOwnershipHook(MetaDataHook): diff -r 29f74716fd70 -r 5376aaadd16b hooks/security.py --- a/hooks/security.py Thu Oct 15 11:20:26 2009 +0200 +++ b/hooks/security.py Mon Oct 19 15:16:41 2009 +0200 @@ -25,8 +25,8 @@ for attr in editedattrs: if attr in defaults: continue - rschema = eschema.subject_relation(attr) - if rschema.is_final(): # non final relation are checked by other hooks + rschema = eschema.subjrels[attr] + if rschema.final: # non final relation are checked by other hooks # add/delete should be equivalent (XXX: unify them into 'update' ?) rschema.check_perm(session, 'add', eid) diff -r 29f74716fd70 -r 5376aaadd16b hooks/syncschema.py --- a/hooks/syncschema.py Thu Oct 15 11:20:26 2009 +0200 +++ b/hooks/syncschema.py Mon Oct 19 15:16:41 2009 +0200 @@ -216,7 +216,7 @@ def precommit_event(self): session = self.session rschema = self.rschema - if rschema.is_final() or not 'inlined' in self.values: + if rschema.final or not 'inlined' in self.values: return # nothing to do inlined = self.values['inlined'] entity = self.entity @@ -454,7 +454,7 @@ sysource.create_index(self.session, table, column) else: sysource.drop_index(self.session, table, column) - if 'cardinality' in self.values and self.rschema.is_final(): + if 'cardinality' in self.values and self.rschema.final: adbh = self.session.pool.source('system').dbhelper if not adbh.alter_column_support: # not supported (and NOT NULL not set by yams in that case, so @@ -816,7 +816,25 @@ self._cw.execute('DELETE Workflow X WHERE NOT X workflow_of Y') +<<<<<<< /home/syt/src/fcubicweb/cubicweb/hooks/syncschema.py class AfterAddCWETypeHook(DelCWETypeHook): +======= +def after_del_relation_type(session, rdefeid, rtype, rteid): + + +# addition hooks ############################################################### + +def before_add_eetype(session, entity): + """before adding a CWEType entity: + * check that we are not using an existing entity type, + """ + name = entity['name'] + schema = session.schema + if name in schema and schema[name].eid is not None: + raise RepositoryError('an entity type %s already exists' % name) + +def after_add_eetype(session, entity): +>>>>>>> /tmp/schemahooks.py~other.2drHhu """after adding a CWEType entity: * create the necessary table * set creation_date and modification_date by creating the necessary @@ -974,10 +992,11 @@ def __call__(self): session = self._cw subjschema, rschema, objschema = session.vreg.schema.schema_by_eid(self.eidfrom) + subjschema, rschema, objschema = session.schema.schema_by_eid(rdefeid) pendings = session.transaction_data.get('pendingeids', ()) pendingrdefs = session.transaction_data.setdefault('pendingrdefs', set()) # first delete existing relation if necessary - if rschema.is_final(): + if rschema.final: rdeftype = 'CWAttribute' pendingrdefs.add((subjschema, rschema)) else: @@ -987,7 +1006,6 @@ session.execute('DELETE X %s Y WHERE X is %s, Y is %s' % (rschema, subjschema, objschema)) execute = session.unsafe_execute - rteid = self.eidto rset = execute('Any COUNT(X) WHERE X is %s, X relation_type R,' 'R eid %%(x)s' % rdeftype, {'x': rteid}) lastrel = rset[0][0] == 0 @@ -995,7 +1013,7 @@ # relations, but only if it's the last instance for this relation type # for other relations - if (rschema.is_final() or rschema.inlined): + if (rschema.final or rschema.inlined): rset = execute('Any COUNT(X) WHERE X is %s, X relation_type R, ' 'R eid %%(x)s, X from_entity E, E name %%(name)s' % rdeftype, {'x': rteid, 'name': str(subjschema)}) diff -r 29f74716fd70 -r 5376aaadd16b req.py --- a/req.py Thu Oct 15 11:20:26 2009 +0200 +++ b/req.py Mon Oct 19 15:16:41 2009 +0200 @@ -108,7 +108,8 @@ # XXX move to CWEntityManager or even better as factory method (unclear # where yet...) - def create_entity(self, etype, **kwargs): + + def create_entity(self, etype, _cw_unsafe=False, **kwargs): """add a new entity of the given type Example (in a shell session): @@ -117,16 +118,21 @@ create_entity('Person', works_for=c, firstname=u'John', lastname=u'Doe') """ + if _cw_unsafe: + execute = self.unsafe_execute + else: + execute = self.execute rql = 'INSERT %s X' % etype relations = [] restrictions = set() cachekey = [] pending_relations = [] - for attr, value in kwargs.iteritems(): + for attr, value in kwargs.items(): if isinstance(value, (tuple, list, set, frozenset)): if len(value) == 1: value = iter(value).next() else: + del kwargs[attr] pending_relations.append( (attr, value) ) continue if hasattr(value, 'eid'): # non final relation @@ -147,13 +153,13 @@ rql = '%s: %s' % (rql, ', '.join(relations)) if restrictions: rql = '%s WHERE %s' % (rql, ', '.join(restrictions)) - created = self.execute(rql, kwargs, cachekey).get_entity(0, 0) + created = execute(rql, kwargs, cachekey).get_entity(0, 0) for attr, values in pending_relations: if attr.startswith('reverse_'): restr = 'Y %s X' % attr[len('reverse_'):] else: restr = 'X %s Y' % attr - self.execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % ( + execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % ( restr, ','.join(str(r.eid) for r in values)), {'x': created.eid}, 'x') return created diff -r 29f74716fd70 -r 5376aaadd16b rqlrewrite.py --- a/rqlrewrite.py Thu Oct 15 11:20:26 2009 +0200 +++ b/rqlrewrite.py Mon Oct 19 15:16:41 2009 +0200 @@ -32,7 +32,7 @@ allpossibletypes = {} for solution in solutions: for varname, etype in solution.iteritems(): - if not varname in newroot.defined_vars or eschema(etype).is_final(): + if not varname in newroot.defined_vars or eschema(etype).final: continue allpossibletypes.setdefault(varname, set()).add(etype) for varname in sorted(allpossibletypes): @@ -289,7 +289,7 @@ stinfo = self.varinfo['stinfo'] for rel in stinfo['relations']: rschema = self.schema.rschema(rel.r_type) - if rschema.is_final() or (rschema.inlined and + if rschema.final or (rschema.inlined and not rel in stinfo['rhsrelations']): self.select.remove_node(rel) rel.children[0].name = selectvar diff -r 29f74716fd70 -r 5376aaadd16b rset.py --- a/rset.py Thu Oct 15 11:20:26 2009 +0200 +++ b/rset.py Mon Oct 19 15:16:41 2009 +0200 @@ -396,7 +396,7 @@ etype = self.description[row][col] try: eschema = self.vreg.schema.eschema(etype) - if eschema.is_final(): + if eschema.final: raise NotAnEntity(etype) except KeyError: raise NotAnEntity(etype) @@ -461,14 +461,14 @@ if outerselidx is None: continue if x == 'subject': - rschema = eschema.subject_relation(attr) - if rschema.is_final(): + rschema = eschema.subjrels[attr] + if rschema.final: entity[attr] = rowvalues[outerselidx] continue tetype = rschema.objects(etype)[0] card = rschema.rproperty(etype, tetype, 'cardinality')[0] else: - rschema = eschema.object_relation(attr) + rschema = eschema.objrels[attr] tetype = rschema.subjects(etype)[0] card = rschema.rproperty(tetype, etype, 'cardinality')[1] # only keep value if it can't be multivalued @@ -541,7 +541,7 @@ locate_query_col = col rqlst = self.syntax_tree() etype = self.description[row][col] - if self.vreg.schema.eschema(etype).is_final(): + if self.vreg.schema.eschema(etype).final: # final type, find a better one to locate the correct subquery # (ambiguous if possible) for i in xrange(len(rqlst.children[0].selection)): @@ -550,7 +550,7 @@ coletype = self.description[row][i] if coletype is None: continue - if not self.vreg.schema.eschema(coletype).is_final(): + if not self.vreg.schema.eschema(coletype).final: etype = coletype locate_query_col = i if len(self.column_types(i)) > 1: diff -r 29f74716fd70 -r 5376aaadd16b schema.py --- a/schema.py Thu Oct 15 11:20:26 2009 +0200 +++ b/schema.py Mon Oct 19 15:16:41 2009 +0200 @@ -239,7 +239,7 @@ """return system entity types only: skip final, schema and application entities """ for eschema in schema.entities(): - if eschema.is_final() or eschema.schema_entity(): + if eschema.final or eschema.schema_entity(): continue yield eschema.type @@ -301,7 +301,7 @@ may_need_has_text, has_has_text = False, False need_has_text = None for rschema in self.subject_relations(): - if rschema.is_final(): + if rschema.final: if rschema == 'has_text': has_has_text = True elif self.rproperty(rschema, 'fulltextindexed'): @@ -433,7 +433,7 @@ def rql_expression(self, expression, mainvars=None, eid=None): """rql expression factory""" - if self.is_final(): + if self.final: return ERQLExpression(expression, mainvars, eid) return RRQLExpression(expression, mainvars, eid) @@ -473,7 +473,7 @@ edef.name = bw_normalize_etype(edef.name) assert re.match(r'[A-Z][A-Za-z0-9]*[a-z]+[0-9]*$', edef.name), repr(edef.name) eschema = super(CubicWebSchema, self).add_entity_type(edef) - if not eschema.is_final(): + if not eschema.final: # automatically add the eid relation to non final entity types rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Int', cardinality='11', uid=True) diff -r 29f74716fd70 -r 5376aaadd16b schemaviewer.py --- a/schemaviewer.py Thu Oct 15 11:20:26 2009 +0200 +++ b/schemaviewer.py Mon Oct 19 15:16:41 2009 +0200 @@ -47,7 +47,7 @@ klass='titleUnderline'),)) layout.append(esection) eschemas = [eschema for eschema in schema.entities() - if not (eschema.is_final() or eschema in skiptypes)] + if not (eschema.final or eschema in skiptypes)] for eschema in sorted(eschemas): esection.append(self.visit_entityschema(eschema, skiptypes)) if display_relations: @@ -55,7 +55,7 @@ rsection = Section(children=(title,)) layout.append(rsection) relations = [rschema for rschema in schema.relations() - if not (rschema.is_final() or rschema.type in skiptypes)] + if not (rschema.final or rschema.type in skiptypes)] keys = [(rschema.type, rschema) for rschema in relations] for key, rschema in sorted(keys): relstr = self.visit_relationschema(rschema) @@ -143,7 +143,7 @@ data.append(Section(children=rels, klass='rels')) data.append(Section(children=t_vars, klass='vars')) layout.append(Section(children=data, klass='entityAttributes')) - if eschema.is_final(): # stop here for final entities + if eschema.final: # stop here for final entities return layout _ = self.req._ if self.req.user.matching_groups('managers'): diff -r 29f74716fd70 -r 5376aaadd16b selectors.py --- a/selectors.py Thu Oct 15 11:20:26 2009 +0200 +++ b/selectors.py Mon Oct 19 15:16:41 2009 +0200 @@ -684,9 +684,9 @@ eschema = eclass.e_schema try: if self.role == 'object': - rschema = eschema.object_relation(self.rtype) + rschema = eschema.objrels[self.rtype] else: - rschema = eschema.subject_relation(self.rtype) + rschema = eschema.subjrels[self.rtype] except KeyError: return 0 if self.target_etype is not None: @@ -901,7 +901,7 @@ """ def score(self, cls, req, etype): eschema = req.vreg.schema.eschema(etype) - if not (eschema.is_final() or eschema.is_subobject(strict=True)) \ + if not (eschema.final or eschema.is_subobject(strict=True)) \ and eschema.has_perm(req, 'add'): return 1 return 0 diff -r 29f74716fd70 -r 5376aaadd16b server/__init__.py --- a/server/__init__.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/__init__.py Mon Oct 19 15:16:41 2009 +0200 @@ -176,6 +176,10 @@ # reloging using the admin user config._cubes = None # avoid assertion error repo, cnx = in_memory_cnx(config, login, password=pwd) + # trigger vreg initialisation of entity classes + config.cubicweb_appobject_path = set(('entities',)) + config.cube_appobject_path = set(('entities',)) + repo.vreg.set_schema(repo.schema) assert len(repo.sources) == 1, repo.sources handler = config.migration_handler(schema, interactive=False, cnx=cnx, repo=repo) diff -r 29f74716fd70 -r 5376aaadd16b server/checkintegrity.py --- a/server/checkintegrity.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/checkintegrity.py Mon Oct 19 15:16:41 2009 +0200 @@ -83,7 +83,7 @@ repo.do_fti = True # ensure full-text indexation is activated etypes = set() for eschema in schema.entities(): - if eschema.is_final(): + if eschema.final: continue indexable_attrs = tuple(eschema.indexable_attributes()) # generator if not indexable_attrs: @@ -161,7 +161,7 @@ print >> sys.stderr print 'Checking entities tables' for eschema in schema.entities(): - if eschema.is_final(): + if eschema.final: continue table = SQL_PREFIX + eschema.type column = SQL_PREFIX + 'eid' @@ -193,7 +193,7 @@ """check all relations registered in the repo system table""" print 'Checking relations' for rschema in schema.relations(): - if rschema.is_final() or rschema in PURE_VIRTUAL_RTYPES: + if rschema.final or rschema in PURE_VIRTUAL_RTYPES: continue if rschema.inlined: for subjtype in rschema.subjects(): diff -r 29f74716fd70 -r 5376aaadd16b server/hook.py --- a/server/hook.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/hook.py Mon Oct 19 15:16:41 2009 +0200 @@ -245,12 +245,12 @@ eschema = self.schema.eschema(self._cw.describe(self.eidfrom)[0]) execute = self._cw.unsafe_execute for rel in self.subject_relations: - if eschema.has_subject_relation(rel): + if rel in eschema.subjrels: execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' 'X %s R, NOT R %s P' % (self.rtype, rel, self.rtype), {'x': self.eidfrom, 'p': self.eidto}, 'x') for rel in self.object_relations: - if eschema.has_object_relation(rel): + if rel in eschema.objrels: execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' 'R %s X, NOT R %s P' % (self.rtype, rel, self.rtype), {'x': self.eidfrom, 'p': self.eidto}, 'x') @@ -269,12 +269,12 @@ eschema = self.schema.eschema(self._cw.describe(self.eidfrom)[0]) execute = self._cw.unsafe_execute for rel in self.subject_relations: - if eschema.has_subject_relation(rel): + if rel in eschema.subjrels: execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' 'X %s R' % (self.rtype, rel), {'x': self.eidfrom, 'p': self.eidto}, 'x') for rel in self.object_relations: - if eschema.has_object_relation(rel): + if rel in eschema.objrels: execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' 'R %s X' % (self.rtype, rel), {'x': self.eidfrom, 'p': self.eidto}, 'x') @@ -328,10 +328,15 @@ """return the index of the lastest instance which is not a LateOperation instance """ - for i, op in enumerate(self.session.pending_operations): + # faster by inspecting operation in reverse order for heavy transactions + i = None + for i, op in enumerate(reversed(self.session.pending_operations)): if isinstance(op, (LateOperation, SingleLastOperation)): - return i - return None + continue + return -i or None + if i is None: + return None + return -(i + 1) def handle_event(self, event): """delegate event handling to the opertaion""" @@ -395,10 +400,15 @@ """return the index of the lastest instance which is not a SingleLastOperation instance """ - for i, op in enumerate(self.session.pending_operations): + # faster by inspecting operation in reverse order for heavy transactions + i = None + for i, op in enumerate(reversed(self.session.pending_operations)): if isinstance(op, SingleLastOperation): - return i - return None + continue + return -i or None + if i is None: + return None + return -(i + 1) class SingleOperation(Operation): @@ -418,10 +428,9 @@ def equivalent_index(self, operations): """return the index of the equivalent operation if any""" - equivalents = [i for i, op in enumerate(operations) - if op.__class__ is self.__class__] - if equivalents: - return equivalents[0] + for i, op in enumerate(reversed(operations)): + if op.__class__ is self.__class__: + return -(i+1) return None diff -r 29f74716fd70 -r 5376aaadd16b server/hooksmanager.py diff -r 29f74716fd70 -r 5376aaadd16b server/migractions.py --- a/server/migractions.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/migractions.py Mon Oct 19 15:16:41 2009 +0200 @@ -54,6 +54,7 @@ def __init__(self, config, schema, interactive=True, repo=None, cnx=None, verbosity=1, connect=True): MigrationHelper.__init__(self, config, interactive, verbosity) + # no config on shell to a remote instance if not interactive: assert cnx assert repo @@ -61,7 +62,8 @@ assert repo self._cnx = cnx self.repo = repo - self.session.data['rebuild-infered'] = False + if config is not None: + self.session.data['rebuild-infered'] = False elif connect: self.repo_connect() if not schema: @@ -93,7 +95,7 @@ self.backup_database(askconfirm=False) super(ServerMigrationHelper, self).migrate(vcconf, toupgrade, options) - def process_script(self, migrscript, funcname=None, *args, **kwargs): + def cmd_process_script(self, migrscript, funcname=None, *args, **kwargs): """execute a migration script in interactive mode, display the migration script path, ask for confirmation and execute it if confirmed @@ -103,7 +105,7 @@ if self.execscript_confirm(migrscript): sqlexec(open(migrscript).read(), self.session.system_sql) else: - return super(ServerMigrationHelper, self).process_script( + return super(ServerMigrationHelper, self).cmd_process_script( migrscript, funcname, *args, **kwargs) self.commit() except: @@ -233,7 +235,10 @@ @property def session(self): - return self.repo._get_session(self.cnx.sessionid) + if self.config is not None: + return self.repo._get_session(self.cnx.sessionid) + # no access to session on remote instance + return None def commit(self): if hasattr(self, '_cnx'): @@ -255,7 +260,8 @@ 'sql': self.sqlexec, 'rql': self.rqlexec, 'rqliter': self.rqliter, - 'schema': self.repo.schema, + 'schema': self.repo.get_schema(), + 'cnx': self.cnx, 'fsschema': self.fs_schema, 'session' : self.session, 'repo' : self.repo, @@ -268,8 +274,7 @@ @cached def group_mapping(self): """cached group mapping""" - self.session.set_pool() - return ss.group_mapping(self.session) + return ss.group_mapping(self._cw) def exec_event_script(self, event, cubepath=None, funcname=None, *args, **kwargs): @@ -289,7 +294,7 @@ self.confirm = yes self.execscript_confirm = yes try: - return self.process_script(apc, funcname, *args, **kwargs) + return self.cmd_process_script(apc, funcname, *args, **kwargs) finally: self.confirm = confirm self.execscript_confirm = execscript_confirm @@ -306,7 +311,7 @@ return newrschema = self.fs_schema[ertype] teid = self.repo.schema[ertype].eid - if 'update' in newrschema.ACTIONS or newrschema.is_final(): + if 'update' in newrschema.ACTIONS or newrschema.final: # entity type exprtype = u'ERQLExpression' else: @@ -643,7 +648,7 @@ # XXX (syt) plz explain: if we're adding an entity type, it should # not be there... eschema = instschema[etype] - if eschema.is_final(): + if eschema.final: instschema.del_entity_type(etype) else: eschema = self.fs_schema.eschema(etype) @@ -686,7 +691,7 @@ if role == 'subject': subjschema = spschema objschema = tschema - if rschema.final and instspschema.has_subject_relation(rschema): + if rschema.final and rschema in instspschema.subjrels: # attribute already set, has_rdef would check if # it's of the same type, we don't want this so # simply skip here @@ -852,7 +857,7 @@ """unregister an existing relation definition""" rschema = self.repo.schema.rschema(rtype) # unregister the definition from CWAttribute or CWRelation - if rschema.is_final(): + if rschema.final: etype = 'CWAttribute' else: etype = 'CWRelation' @@ -981,7 +986,6 @@ :rtype: `Workflow` """ - self.session.set_pool() # ensure pool is set wf = self.cmd_create_entity('Workflow', name=unicode(name), **kwargs) if not isinstance(wfof, (list, tuple)): @@ -1001,7 +1005,6 @@ # XXX remove once cmd_add_[state|transition] are removed def _get_or_create_wf(self, etypes): - self.session.set_pool() # ensure pool is set if not isinstance(etypes, (list, tuple)): etypes = (etypes,) rset = self.rqlexec('Workflow X WHERE X workflow_of ET, ET name %(et)s', @@ -1041,16 +1044,14 @@ """set or add (if `reset` is False) groups and conditions for a transition """ - self.session.set_pool() # ensure pool is set - tr = self.session.entity_from_eid(treid) + tr = self._cw.entity_from_eid(treid) tr.set_transition_permissions(requiredgroups, conditions, reset) if commit: self.commit() @deprecated('[3.5] use entity.fire_transition("transition") or entity.change_state("state")') def cmd_set_state(self, eid, statename, commit=False): - self.session.set_pool() # ensure pool is set - self.session.entity_from_eid(eid).change_state(statename) + self._cw.entity_from_eid(eid).change_state(statename) if commit: self.commit() @@ -1074,11 +1075,18 @@ # other data migration commands ########################################### - def cmd_create_entity(self, etype, *args, **kwargs): + @property + def _cw(self): + session = self.session + if session is not None: + session.set_pool() + return session + return self.cnx.request() + + def cmd_create_entity(self, etype, **kwargs): """add a new entity of the given type""" commit = kwargs.pop('commit', False) - self.session.set_pool() - entity = self.session.create_entity(etype, *args, **kwargs) + entity = self._cw.create_entity(etype, **kwargs) if commit: self.commit() return entity @@ -1114,7 +1122,6 @@ if not isinstance(rql, (tuple, list)): rql = ( (rql, kwargs), ) res = None - self.session.set_pool() for rql, kwargs in rql: if kwargs: msg = '%s (%s)' % (rql, kwargs) @@ -1122,7 +1129,7 @@ msg = rql if not ask_confirm or self.confirm('execute rql: %s ?' % msg): try: - res = self.session.execute(rql, kwargs, cachekey) + res = self._cw.execute(rql, kwargs, cachekey) except Exception, ex: if self.confirm('error: %s\nabort?' % ex): raise @@ -1211,9 +1218,8 @@ if self.ask_confirm: if not self._h.confirm('execute rql: %s ?' % msg): raise StopIteration - self._h.session.set_pool() try: - rset = self._h.session.execute(rql, kwargs) + rset = self._h._cw.execute(rql, kwargs) except Exception, ex: if self._h.confirm('error: %s\nabort?' % ex): raise diff -r 29f74716fd70 -r 5376aaadd16b server/msplanner.py --- a/server/msplanner.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/msplanner.py Mon Oct 19 15:16:41 2009 +0200 @@ -334,7 +334,7 @@ for i, sol in enumerate(self._solutions): vartype = sol[varname] # skip final variable - if eschema(vartype).is_final(): + if eschema(vartype).final: break for source in repo.sources: if source.support_entity(vartype): @@ -381,7 +381,7 @@ # process non final relations only # note: don't try to get schema for 'is' relation (not available # during bootstrap) - if not rel.is_types_restriction() and not rschema(rel.r_type).is_final(): + if not rel.is_types_restriction() and not rschema(rel.r_type).final: # nothing to do if relation is not supported by multiple sources # or if some source has it listed in its cross_relations # attribute @@ -457,7 +457,7 @@ repo = self._repo rschema = self._schema.rschema for rel in self.plan.rqlst.main_relations: - if not rschema(rel.r_type).is_final(): + if not rschema(rel.r_type).final: # nothing to do if relation is not supported by multiple sources if len(repo.rel_type_sources(rel.r_type)) < 2: continue @@ -730,7 +730,7 @@ # its lhs/rhs variable isn't in "terms", and the # other end *is* in "terms", mark it have to be # selected - if source.uri != 'system' and not rschema(rel.r_type).is_final(): + if source.uri != 'system' and not rschema(rel.r_type).final: lhs, rhs = rel.get_variable_parts() try: lhsvar = lhs.variable @@ -1003,7 +1003,7 @@ for varname, mapping in step.outputmap.iteritems(): if varname in inputmap and \ not (mapping == inputmap[varname] or - self._schema.eschema(solutions[0][varname]).is_final()): + self._schema.eschema(solutions[0][varname]).final): self._conflicts.append((varname, inputmap[varname])) inputmap.update(step.outputmap) self.plan.add_step(step) @@ -1359,7 +1359,7 @@ return False if not self.final and not relation in self.terms: rschema = self.schema.rschema(relation.r_type) - if not rschema.is_final(): + if not rschema.final: for term in relation.get_nodes((VariableRef, Constant)): term = getattr(term, 'variable', term) termsources = sorted(set(x[0] for x in self.ppi._term_sources(term))) @@ -1370,7 +1370,7 @@ def visit_relation(self, node, newroot, terms): if not node.is_types_restriction(): if node in self.skip and self.solindices.issubset(self.skip[node]): - if not self.schema.rschema(node.r_type).is_final(): + if not self.schema.rschema(node.r_type).final: # can't really skip the relation if one variable is selected and only # referenced by this relation for vref in node.iget_nodes(VariableRef): @@ -1403,7 +1403,7 @@ vref.unregister_reference() raise ored = node.ored() - if rschema.is_final() or rschema.inlined: + if rschema.final or rschema.inlined: vrefs = node.children[1].get_nodes(VariableRef) if not vrefs: if not ored: diff -r 29f74716fd70 -r 5376aaadd16b server/pool.py diff -r 29f74716fd70 -r 5376aaadd16b server/querier.py --- a/server/querier.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/querier.py Mon Oct 19 15:16:41 2009 +0200 @@ -389,7 +389,7 @@ # add constant values to entity def value = rhs.eval(self.args) eschema = edef.e_schema - attrtype = eschema.subject_relation(rtype).objects(eschema)[0] + attrtype = eschema.subjrels[rtype].objects(eschema)[0] if attrtype == 'Password' and isinstance(value, unicode): value = value.encode('UTF8') edef[rtype] = value diff -r 29f74716fd70 -r 5376aaadd16b server/repository.py --- a/server/repository.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/repository.py Mon Oct 19 15:16:41 2009 +0200 @@ -90,6 +90,7 @@ def commit_event(self): pass + def del_existing_rel_if_needed(session, eidfrom, rtype, eidto): """delete existing relation when adding a new one if card is 1 or ? @@ -105,6 +106,7 @@ return ensure_card_respected(session.unsafe_execute, session, eidfrom, rtype, eidto) + def ensure_card_respected(execute, session, eidfrom, rtype, eidto): card = session.schema_rproperty(rtype, eidfrom, eidto, 'cardinality') # one may be tented to check for neweids but this may cause more than one @@ -122,6 +124,7 @@ execute('DELETE X %s Y WHERE NOT X eid %%(x)s, Y eid %%(y)s' % rtype, {'x': eidfrom, 'y': eidto}, 'y') + class Repository(object): """a repository provides access to a set of persistent storages for entities and relations @@ -984,8 +987,8 @@ # XXX use entity.keys here since edited_attributes is not updated for # inline relations for attr in entity.keys(): - rschema = eschema.subject_relation(attr) - if not rschema.is_final(): # inlined relation + rschema = eschema.subjrels[attr] + if not rschema.final: # inlined relation relations.append((attr, entity[attr])) entity.set_defaults() entity.check(creation=True) @@ -1003,7 +1006,7 @@ rtype = str(rschema) if rtype in schema.VIRTUAL_RTYPES: continue - if rschema.is_final(): + if rschema.final: entity.setdefault(rtype, None) else: entity.set_related_cache(rtype, 'subject', session.empty_rset()) @@ -1043,8 +1046,8 @@ for attr in edited_attributes: if attr == 'eid': continue - rschema = eschema.subject_relation(attr) - if rschema.is_final(): + rschema = eschema.subjrels[attr] + if rschema.final: if eschema.rproperty(attr, 'fulltextindexed'): need_fti_update = True only_inline_rels = False diff -r 29f74716fd70 -r 5376aaadd16b server/rqlannotation.py --- a/server/rqlannotation.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/rqlannotation.py Mon Oct 19 15:16:41 2009 +0200 @@ -201,7 +201,7 @@ for rel in select.iget_nodes(Relation): if rel.neged(strict=True) and not rel.is_types_restriction(): rschema = getrschema(rel.r_type) - if not rschema.is_final(): + if not rschema.final: # if one of the relation's variable is ambiguous but not # invariant, an intersection will be necessary for vref in rel.get_nodes(VariableRef): @@ -221,7 +221,7 @@ def __init__(self, schema): self.schema = schema self.nfdomain = frozenset(eschema.type for eschema in schema.entities() - if not eschema.is_final()) + if not eschema.final) def annotate(self, rqlst): """add information to the rql syntax tree to help sources to do their @@ -234,7 +234,7 @@ syntax tree or because a solution for this variable has been removed due to security filtering) """ - assert rqlst.TYPE == 'select', rqlst + #assert rqlst.TYPE == 'select', rqlst rqlst.has_text_query = self._annotate_union(rqlst) def _annotate_union(self, union): @@ -288,7 +288,7 @@ # set domains for each variable for varname, var in rqlst.defined_vars.iteritems(): if var.stinfo['uidrels'] or \ - self.eschema(rqlst.solutions[0][varname]).is_final(): + self.eschema(rqlst.solutions[0][varname]).final: ptypes = var.stinfo['possibletypes'] else: ptypes = set(self.nfdomain) @@ -304,7 +304,7 @@ lhs, rhs = rel.get_variable_parts() if isinstance(lhs, VariableRef) or isinstance(rhs, VariableRef): rschema = self.rschema(rel.r_type) - if rschema.inlined or rschema.is_final(): + if rschema.inlined or rschema.final: self.not_invariants.add(lhs.variable) self.set_rel_constraint(lhs, rel, rschema.subjects) self.set_rel_constraint(rhs, rel, rschema.objects) diff -r 29f74716fd70 -r 5376aaadd16b server/schemaserial.py --- a/server/schemaserial.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/schemaserial.py Mon Oct 19 15:16:41 2009 +0200 @@ -64,7 +64,7 @@ entity type tables and columns """ for etype in schema.entities(): - if etype.is_final(): + if etype.final: continue try: sql = 'ALTER TABLE %s RENAME TO cw_%s' % ( @@ -76,7 +76,7 @@ for rschema in etype.subject_relations(): if rschema == 'has_text': continue - if rschema.is_final() or rschema.inlined: + if rschema.final or rschema.inlined: sql = 'ALTER TABLE cw_%s RENAME %s TO cw_%s' % ( etype, rschema, rschema) print sql @@ -326,7 +326,7 @@ raise Exception("can't decode %s [was %s]" % (erschema.description, e)) return { 'name': type_, - 'final': erschema.is_final(), + 'final': erschema.final, 'description': desc, } @@ -340,7 +340,7 @@ def rschema_relations_values(rschema): values = _ervalues(rschema) - values['final'] = rschema.is_final() + values['final'] = rschema.final values['symetric'] = rschema.symetric values['inlined'] = rschema.inlined if HAS_FULLTEXT_CONTAINER: @@ -402,7 +402,7 @@ # don't serialize infered relations if _props.get('infered'): continue - gen = genmap[rschema.is_final()] + gen = genmap[rschema.final] for rql, values in gen(rschema, subjtype, objtype, _props): yield rql, values diff -r 29f74716fd70 -r 5376aaadd16b server/sources/__init__.py --- a/server/sources/__init__.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/sources/__init__.py Mon Oct 19 15:16:41 2009 +0200 @@ -168,7 +168,7 @@ wsupport = self.support_relations[rtype] except KeyError: rschema = self.schema.rschema(rtype) - if not rschema.is_final() or rschema == 'has_text': + if not rschema.final or rschema == 'has_text': return False for etype in rschema.subjects(): try: @@ -225,7 +225,7 @@ # delete relations referencing one of those eids eidcolum = SQL_PREFIX + 'eid' for rschema in self.schema.relations(): - if rschema.is_final() or rschema.type in VIRTUAL_RTYPES: + if rschema.final or rschema.type in VIRTUAL_RTYPES: continue if rschema.inlined: column = SQL_PREFIX + rschema.type diff -r 29f74716fd70 -r 5376aaadd16b server/sources/ldapuser.py --- a/server/sources/ldapuser.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/sources/ldapuser.py Mon Oct 19 15:16:41 2009 +0200 @@ -632,7 +632,7 @@ return '' lhs, rhs = relation.get_parts() # attribute relation - if self.source.schema.rschema(rtype).is_final(): + if self.source.schema.rschema(rtype).final: # dunno what to do here, don't pretend anything else if lhs.name != self._mainvarname: if lhs.name in self.mainvars: diff -r 29f74716fd70 -r 5376aaadd16b server/sources/native.py --- a/server/sources/native.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/sources/native.py Mon Oct 19 15:16:41 2009 +0200 @@ -71,7 +71,7 @@ try: sql.append('%s %s' % (name, typemap[ttype])) except KeyError: - # assert not schema(ttype).is_final() + # assert not schema(ttype).final sql.append('%s %s' % (name, typemap['Int'])) return ','.join(sql), varmap diff -r 29f74716fd70 -r 5376aaadd16b server/sources/pyrorql.py --- a/server/sources/pyrorql.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/sources/pyrorql.py Mon Oct 19 15:16:41 2009 +0200 @@ -303,7 +303,7 @@ needtranslation = [] rows = rset.rows for i, etype in enumerate(descr[0]): - if (etype is None or not self.schema.eschema(etype).is_final() + if (etype is None or not self.schema.eschema(etype).final or uidtype(union, i, etype, args)): needtranslation.append(i) if needtranslation: @@ -487,7 +487,7 @@ raise if node.optional in ('left', 'both'): lhs += '?' - if node.r_type == 'eid' or not self.source.schema.rschema(node.r_type).is_final(): + if node.r_type == 'eid' or not self.source.schema.rschema(node.r_type).final: self.need_translation = True self.current_operator = node.operator() if isinstance(node.children[0], Constant): diff -r 29f74716fd70 -r 5376aaadd16b server/sources/rql2sql.py --- a/server/sources/rql2sql.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/sources/rql2sql.py Mon Oct 19 15:16:41 2009 +0200 @@ -60,7 +60,7 @@ newivar = _new_var(newselect, vref.name) newselect.selection.append(VariableRef(newivar)) _fill_to_wrap_rel(vref.variable, newselect, towrap, schema) - elif rschema.is_final(): + elif rschema.final: towrap.add( (var, rel) ) def rewrite_unstable_outer_join(select, solutions, unstable, schema): @@ -616,7 +616,7 @@ return '' lhs, rhs = relation.get_parts() rschema = self.schema.rschema(rtype) - if rschema.is_final(): + if rschema.final: if rtype == 'eid' and lhs.variable._q_invariant and \ lhs.variable.stinfo['constnode']: # special case where this restriction is already generated by @@ -1096,7 +1096,7 @@ except KeyError: etype = self._state.solution[var.name] # XXX this check should be moved in rql.stcheck - if self.schema.eschema(etype).is_final(): + if self.schema.eschema(etype).final: raise BadRQLQuery(var.stmt.root) table = var.name sql = '%s.%seid' % (table, SQL_PREFIX) @@ -1211,7 +1211,7 @@ """return the table alias used by the given relation""" if relation in self._state.done: return relation._q_sqltable - assert not self.schema.rschema(relation.r_type).is_final(), relation.r_type + assert not self.schema.rschema(relation.r_type).final, relation.r_type rid = 'rel_%s%s' % (relation.r_type, self._state.count) # relation's table is belonging to the root scope if it is the principal # table of one of it's variable and if that variable belong's to parent diff -r 29f74716fd70 -r 5376aaadd16b server/sqlutils.py --- a/server/sqlutils.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/sqlutils.py Mon Oct 19 15:16:41 2009 +0200 @@ -229,8 +229,8 @@ attrs = {} eschema = entity.e_schema for attr, value in entity.items(): - rschema = eschema.subject_relation(attr) - if rschema.is_final(): + rschema = eschema.subjrels[attr] + if rschema.final: atype = str(entity.e_schema.destination(attr)) if atype == 'Boolean': value = self.dbhelper.boolean_value(value) diff -r 29f74716fd70 -r 5376aaadd16b server/ssplanner.py --- a/server/ssplanner.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/ssplanner.py Mon Oct 19 15:16:41 2009 +0200 @@ -75,8 +75,8 @@ if reverse: rdefs[i] = rtype, RelationsStep.REVERSE_RELATION else: - rschema = eschema.subject_relation(rtype) - if rschema.is_final() or rschema.inlined: + rschema = eschema.subjrels[rtype] + if rschema.final or rschema.inlined: rdefs[i] = rtype, RelationsStep.FINAL else: rdefs[i] = rtype, RelationsStep.RELATION @@ -147,7 +147,7 @@ selected_index[rhs.as_string('utf-8')] = index index += 1 rschema = getrschema(relation.r_type) - if rschema.is_final() or rschema.inlined: + if rschema.final or rschema.inlined: attrrelations.append(relation) else: relations.append(relation) diff -r 29f74716fd70 -r 5376aaadd16b server/test/unittest_migractions.py --- a/server/test/unittest_migractions.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/test/unittest_migractions.py Mon Oct 19 15:16:41 2009 +0200 @@ -154,7 +154,7 @@ self.assertEquals([str(rs) for rs in self.schema['Folder2'].object_relations()], ['filed_under2', 'identity']) self.assertEquals(sorted(str(e) for e in self.schema['filed_under2'].subjects()), - sorted(str(e) for e in self.schema.entities() if not e.is_final())) + sorted(str(e) for e in self.schema.entities() if not e.final)) self.assertEquals(self.schema['filed_under2'].objects(), ('Folder2',)) eschema = self.schema.eschema('Folder2') for cstr in eschema.constraints('name'): @@ -183,7 +183,7 @@ self.schema.rebuild_infered_relations() self.failUnless('filed_under2' in self.schema) self.assertEquals(sorted(str(e) for e in self.schema['filed_under2'].subjects()), - sorted(str(e) for e in self.schema.entities() if not e.is_final())) + sorted(str(e) for e in self.schema.entities() if not e.final)) self.assertEquals(self.schema['filed_under2'].objects(), ('Folder2',)) self.mh.cmd_drop_relation_type('filed_under2') self.failIf('filed_under2' in self.schema) diff -r 29f74716fd70 -r 5376aaadd16b server/test/unittest_msplanner.py --- a/server/test/unittest_msplanner.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/test/unittest_msplanner.py Mon Oct 19 15:16:41 2009 +0200 @@ -226,7 +226,7 @@ self.ldap: {'Y': s[0], 'X': s[0]}}, True) def test_complex_aggregat(self): - solindexes = set(range(len([e for e in self.schema.entities() if not e.is_final()]))) + solindexes = set(range(len([e for e in self.schema.entities() if not e.final]))) self._test('Any MAX(X)', {self.system: {'X': solindexes}}, False) diff -r 29f74716fd70 -r 5376aaadd16b server/test/unittest_rql2sql.py --- a/server/test/unittest_rql2sql.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/test/unittest_rql2sql.py Mon Oct 19 15:16:41 2009 +0200 @@ -1082,7 +1082,7 @@ self.assertEquals(var_sols('FROM_ENTITYOBJECT'), set(('CWAttribute', 'CWRelation'))) self.assertEquals(var_sols('FROM_ENTITYOBJECT'), delete.defined_vars['FROM_ENTITYOBJECT'].stinfo['possibletypes']) self.assertEquals(var_sols('ISOBJECT'), - set(x.type for x in self.schema.entities() if not x.is_final())) + set(x.type for x in self.schema.entities() if not x.final)) self.assertEquals(var_sols('ISOBJECT'), delete.defined_vars['ISOBJECT'].stinfo['possibletypes']) diff -r 29f74716fd70 -r 5376aaadd16b server/utils.py --- a/server/utils.py Thu Oct 15 11:20:26 2009 +0200 +++ b/server/utils.py Mon Oct 19 15:16:41 2009 +0200 @@ -71,7 +71,8 @@ def manager_userpasswd(user=None, msg=DEFAULT_MSG, confirm=False, passwdmsg='password'): if not user: - print msg + if msg: + print msg while not user: user = raw_input('login: ') user = unicode(user, sys.stdin.encoding) diff -r 29f74716fd70 -r 5376aaadd16b sobjects/notification.py --- a/sobjects/notification.py Thu Oct 15 11:20:26 2009 +0200 +++ b/sobjects/notification.py Mon Oct 19 15:16:41 2009 +0200 @@ -152,7 +152,7 @@ for attr, oldvalue, newvalue in sorted(changes): # check current user has permission to see the attribute rschema = self.vreg.schema[attr] - if rschema.is_final(): + if rschema.final: if not rschema.has_perm(self.req, 'read', eid=self.rset[0][0]): continue # XXX suppose it's a subject relation... diff -r 29f74716fd70 -r 5376aaadd16b test/unittest_entity.py --- a/test/unittest_entity.py Thu Oct 15 11:20:26 2009 +0200 +++ b/test/unittest_entity.py Mon Oct 19 15:16:41 2009 +0200 @@ -120,10 +120,10 @@ Note = self.vreg['etypes'].etype_class('Note') peschema = Personne.e_schema seschema = Societe.e_schema - peschema.subject_relation('travaille').set_rproperty(peschema, seschema, 'cardinality', '1*') - peschema.subject_relation('connait').set_rproperty(peschema, peschema, 'cardinality', '11') - peschema.subject_relation('evaluee').set_rproperty(peschema, Note.e_schema, 'cardinality', '1*') - seschema.subject_relation('evaluee').set_rproperty(seschema, Note.e_schema, 'cardinality', '1*') + peschema.subjrels['travaille'].set_rproperty(peschema, seschema, 'cardinality', '1*') + peschema.subjrels['connait'].set_rproperty(peschema, peschema, 'cardinality', '11') + peschema.subjrels['evaluee'].set_rproperty(peschema, Note.e_schema, 'cardinality', '1*') + seschema.subjrels['evaluee'].set_rproperty(seschema, Note.e_schema, 'cardinality', '1*') # testing basic fetch_attrs attribute self.assertEquals(Personne.fetch_rql(user), 'Any X,AA,AB,AC ORDERBY AA ASC ' @@ -158,13 +158,13 @@ self.assertEquals(Personne.fetch_rql(user), 'Any X,AA,AB ORDERBY AA ASC ' 'WHERE X is Personne, X nom AA, X connait AB?') # testing optional relation - peschema.subject_relation('travaille').set_rproperty(peschema, seschema, 'cardinality', '?*') + peschema.subjrels['travaille'].set_rproperty(peschema, seschema, 'cardinality', '?*') Personne.fetch_attrs = ('nom', 'prenom', 'travaille') Societe.fetch_attrs = ('nom',) self.assertEquals(Personne.fetch_rql(user), 'Any X,AA,AB,AC,AD ORDERBY AA ASC WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD') # testing relation with cardinality > 1 - peschema.subject_relation('travaille').set_rproperty(peschema, seschema, 'cardinality', '**') + peschema.subjrels['travaille'].set_rproperty(peschema, seschema, 'cardinality', '**') self.assertEquals(Personne.fetch_rql(user), 'Any X,AA,AB ORDERBY AA ASC WHERE X is Personne, X nom AA, X prenom AB') # XXX test unauthorized attribute diff -r 29f74716fd70 -r 5376aaadd16b test/unittest_schema.py --- a/test/unittest_schema.py Thu Oct 15 11:20:26 2009 +0200 +++ b/test/unittest_schema.py Mon Oct 19 15:16:41 2009 +0200 @@ -88,7 +88,7 @@ self.assertEqual(esociete.type, 'Societe') self.assertEqual(schema.has_relation('TEST'), 0) self.assertEqual(schema.has_relation('test'), 1) - self.assertEqual(eperson.subject_relation('test').type, 'test') + self.assertEqual(eperson.subjrels['test'].type, 'test') self.assertEqual(schema.has_relation('Concerne'), 0) self.assertEqual(schema.has_relation('concerne'), 1) self.assertEqual(schema.rschema('concerne').type, 'concerne') diff -r 29f74716fd70 -r 5376aaadd16b view.py --- a/view.py Thu Oct 15 11:20:26 2009 +0200 +++ b/view.py Mon Oct 19 15:16:41 2009 +0200 @@ -213,7 +213,7 @@ coltypes = rset.column_types(0) if len(coltypes) == 1: etype = iter(coltypes).next() - if not self._cw.schema.eschema(etype).is_final(): + if not self._cw.schema.eschema(etype).final: if len(rset) == 1: entity = rset.get_entity(0, 0) return entity.absolute_url(vid=self.__regid__) diff -r 29f74716fd70 -r 5376aaadd16b web/facet.py --- a/web/facet.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/facet.py Mon Oct 19 15:16:41 2009 +0200 @@ -92,7 +92,7 @@ # constant restriction # XXX: X title LOWER(T) if it makes sense? return None - if rschema.is_final(): + if rschema.final: if len(ovar.stinfo['relations']) == 1: # attribute selection return ovar diff -r 29f74716fd70 -r 5376aaadd16b web/formfields.py --- a/web/formfields.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/formfields.py Mon Oct 19 15:16:41 2009 +0200 @@ -586,7 +586,7 @@ if role == 'subject': targetschema = rschema.objects(eschema)[0] help = rschema.rproperty(eschema, targetschema, 'description') - if rschema.is_final(): + if rschema.final: if rschema.rproperty(eschema, targetschema, 'internationalizable'): kwargs.setdefault('internationalizable', True) def get_default(form, es=eschema, rs=rschema): @@ -603,7 +603,7 @@ kwargs.setdefault('label', (eschema.type, rschema.type)) kwargs['eidparam'] = True kwargs.setdefault('help', help) - if rschema.is_final(): + if rschema.final: if skip_meta_attr and rschema in eschema.meta_attributes(): return None fieldclass = FIELDS[targetschema] diff -r 29f74716fd70 -r 5376aaadd16b web/formwidgets.py --- a/web/formwidgets.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/formwidgets.py Mon Oct 19 15:16:41 2009 +0200 @@ -448,7 +448,7 @@ # XXX entity form specific entity = form.edited_entity attrs['cubicweb:etype_to'] = entity.e_schema - etype_from = entity.e_schema.subject_relation(field.name).objects(entity.e_schema)[0] + etype_from = entity.e_schema.subjrels[field.name].objects(entity.e_schema)[0] attrs['cubicweb:etype_from'] = etype_from return name, values, attrs diff -r 29f74716fd70 -r 5376aaadd16b web/uicfg.py --- a/web/uicfg.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/uicfg.py Mon Oct 19 15:16:41 2009 +0200 @@ -125,7 +125,7 @@ if rtag.get(sschema, rschema, oschema, role) is None: card = card_from_role(rschema.rproperty(sschema, oschema, 'cardinality'), role) composed = rschema.rproperty(sschema, oschema, 'composite') == neg_role(role) - if rschema.is_final(): + if rschema.final: if rschema.meta or sschema.is_metadata(rschema) \ or oschema.type in ('Password', 'Bytes'): section = 'hidden' diff -r 29f74716fd70 -r 5376aaadd16b web/views/__init__.py --- a/web/views/__init__.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/__init__.py Mon Oct 19 15:16:41 2009 +0200 @@ -39,7 +39,7 @@ if not isinstance(selected[i+1], nodes.VariableRef): return True # if this is not a final entity - if not schema.eschema(etype).is_final(): + if not schema.eschema(etype).final: return True # if this is a final entity not linked to the main variable var = selected[i+1].variable @@ -74,7 +74,7 @@ if nb_rows == 0 : return 'noresult' # entity result set - if not schema.eschema(rset.description[0][0]).is_final(): + if not schema.eschema(rset.description[0][0]).final: if need_table_view(rset, schema): return 'table' if nb_rows == 1: diff -r 29f74716fd70 -r 5376aaadd16b web/views/actions.py --- a/web/views/actions.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/actions.py Mon Oct 19 15:16:41 2009 +0200 @@ -40,7 +40,7 @@ 'optional argument', DeprecationWarning) editableattrs = form.editable_attributes() for rschema, targetschemas, role in editableattrs: - if not rschema.is_final(): + if not rschema.final: return 1 return 0 @@ -66,7 +66,7 @@ if len(select.defined_vars) == 1 and len(select.solutions) == 1: rset._searched_etype = select.solutions[0].itervalues().next() eschema = req.schema.eschema(rset._searched_etype) - if not (eschema.is_final() or eschema.is_subobject(strict=True)) \ + if not (eschema.final or eschema.is_subobject(strict=True)) \ and eschema.has_perm(req, 'add'): return 1 return 0 @@ -270,7 +270,7 @@ for role, rschemas in (('subject', eschema.subject_relations()), ('object', eschema.object_relations())): for rschema in rschemas: - if rschema.is_final(): + if rschema.final: continue # check the relation can be added as well # XXX consider autoform_permissions_overrides? diff -r 29f74716fd70 -r 5376aaadd16b web/views/autoform.py diff -r 29f74716fd70 -r 5376aaadd16b web/views/baseviews.py --- a/web/views/baseviews.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/baseviews.py Mon Oct 19 15:16:41 2009 +0200 @@ -115,7 +115,7 @@ __regid__ = 'secondary' title = _('secondary') - def cell_call(self, row, col): + def cell_call(self, row, col, **kwargs): """the secondary view for an entity secondary = icon + view(oneline) """ @@ -128,7 +128,7 @@ __regid__ = 'oneline' title = _('oneline') - def cell_call(self, row, col): + def cell_call(self, row, col, **kwargs): """the one line view for an entity: linked text view """ entity = self.cw_rset.get_entity(row, col) diff -r 29f74716fd70 -r 5376aaadd16b web/views/bookmark.py --- a/web/views/bookmark.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/bookmark.py Mon Oct 19 15:16:41 2009 +0200 @@ -10,7 +10,7 @@ from logilab.mtconverter import xml_escape from cubicweb import Unauthorized -from cubicweb.selectors import implements +from cubicweb.selectors import implements, one_line_rset from cubicweb.web.htmlwidgets import BoxWidget, BoxMenu, RawBoxItem from cubicweb.web import action, box, uicfg from cubicweb.web.views import primary @@ -21,7 +21,7 @@ class FollowAction(action.Action): __regid__ = 'follow' - __select__ = implements('Bookmark') + __select__ = one_line_rset() & implements('Bookmark') title = _('follow') category = 'mainactions' diff -r 29f74716fd70 -r 5376aaadd16b web/views/csvexport.py --- a/web/views/csvexport.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/csvexport.py Mon Oct 19 15:16:41 2009 +0200 @@ -45,7 +45,7 @@ csvrow = [] for colindex, val in enumerate(row): etype = descr[rowindex][colindex] - if val is not None and not eschema(etype).is_final(): + if val is not None and not eschema(etype).final: # csvrow.append(val) # val is eid in that case content = self._cw.view('textincontext', rset, row=rowindex, col=colindex) diff -r 29f74716fd70 -r 5376aaadd16b web/views/editcontroller.py diff -r 29f74716fd70 -r 5376aaadd16b web/views/editforms.py --- a/web/views/editforms.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/editforms.py Mon Oct 19 15:16:41 2009 +0200 @@ -171,7 +171,7 @@ rschema = schema.rschema(rtype) lzone = self._build_landing_zone(landing_zone) # compute value, checking perms, build form - if rschema.is_final(): + if rschema.final: onsubmit = ("return inlineValidateAttributeForm('%(rtype)s', '%(eid)s', '%(divid)s', " "%(reload)s, '%(default)s');") form = self._build_form( @@ -398,7 +398,7 @@ form.form_add_hidden(eid_param('__cloned_eid', entity.eid), self.copying.eid) for rschema, role in form.editable_attributes(): - if not rschema.is_final(): + if not rschema.final: # ensure relation cache is filed rset = self.copying.related(rschema, role) self.newentity.set_related_cache(rschema, role, rset) diff -r 29f74716fd70 -r 5376aaadd16b web/views/facets.py --- a/web/views/facets.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/facets.py Mon Oct 19 15:16:41 2009 +0200 @@ -100,8 +100,6 @@ w(u'\n\n') finally: rqlst.recover() - import cubicweb - cubicweb.info('after facets with rql: %s' % repr(rqlst)) def display_bookmark_link(self, rset): eschema = self._cw.schema.eschema('Bookmark') diff -r 29f74716fd70 -r 5376aaadd16b web/views/forms.py --- a/web/views/forms.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/forms.py Mon Oct 19 15:16:41 2009 +0200 @@ -349,7 +349,7 @@ return super(EntityFieldsForm, self).form_field_value(field, load_bytes) if attr == '__type': return entity.__regid__ - if self._cw.schema.rschema(attr).is_final(): + if self.schema.rschema(attr).final: attrtype = entity.e_schema.destination(attr) if attrtype == 'Password': return entity.has_eid() and INTERNAL_FIELD_VALUE or '' @@ -456,7 +456,7 @@ if isinstance(rtype, basestring): rtype = self._cw.vreg.schema.rschema(rtype) done = None - assert not rtype.is_final(), rtype + assert not rtype.final, rtype if entity.has_eid(): done = set(e.eid for e in getattr(entity, str(rtype))) result = [] diff -r 29f74716fd70 -r 5376aaadd16b web/views/magicsearch.py --- a/web/views/magicsearch.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/magicsearch.py Mon Oct 19 15:16:41 2009 +0200 @@ -279,7 +279,7 @@ eschema = self._cw.schema.eschema(etype) rtype = self._get_attribute_name(word2, eschema) # expand shortcut if rtype is a non final relation - if not self._cw.schema.rschema(rtype).is_final(): + if not self._cw.schema.rschema(rtype).final: return self._expand_shortcut(etype, rtype, word3) if '%' in word3: searchop = 'LIKE ' diff -r 29f74716fd70 -r 5376aaadd16b web/views/navigation.py --- a/web/views/navigation.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/navigation.py Mon Oct 19 15:16:41 2009 +0200 @@ -64,7 +64,7 @@ def index_display(row): entity = rset.get_entity(row, col) return entity.printable_value(attrname, format='text/plain') - elif self._cw.schema.eschema(rset.description[0][col]).is_final(): + elif self._cw.schema.eschema(rset.description[0][col]).final: def index_display(row): return unicode(rset[row][col]) else: @@ -99,7 +99,7 @@ attrname = rel.r_type if attrname == 'is': continue - if not rschema(attrname).is_final(): + if not rschema(attrname).final: col = var.selected_index() attrname = None if col is None: diff -r 29f74716fd70 -r 5376aaadd16b web/views/owl.py --- a/web/views/owl.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/owl.py Mon Oct 19 15:16:41 2009 +0200 @@ -80,7 +80,7 @@ """get a layout for a whole schema""" self.skiptypes = skiptypes entities = sorted(eschema for eschema in self._cw.schema.entities() - if not eschema.is_final() or eschema in skiptypes) + if not eschema.final or eschema in skiptypes) self.w(u'') for eschema in entities: self.visit_entityschema(eschema) diff -r 29f74716fd70 -r 5376aaadd16b web/views/plots.py --- a/web/views/plots.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/plots.py Mon Oct 19 15:16:41 2009 +0200 @@ -112,7 +112,8 @@ for idx, (label, plot) in enumerate(zip(self.labels, self.plots)): plotid = '%s_%s' % (figid, idx) plotdefs.append('var %s = %s;' % (plotid, self.dump_plot(plot))) - plotdata.append("{label: '%s', data: %s}" % (label, plotid)) + # XXX ugly but required in order to not crash my demo + plotdata.append("{label: '%s', data: %s}" % (label.replace(u'&', u''), plotid)) req.html_headers.add_onload(self.onload % {'plotdefs': '\n'.join(plotdefs), 'figid': figid, @@ -177,7 +178,7 @@ def _guess_vid(self, row): etype = self.cw_rset.description[row][0] - if self._cw.schema.eschema(etype).is_final(): + if self._cw.schema.eschema(etype).final: return 'final' return 'textincontext' diff -r 29f74716fd70 -r 5376aaadd16b web/views/primary.py --- a/web/views/primary.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/primary.py Mon Oct 19 15:16:41 2009 +0200 @@ -105,7 +105,7 @@ def render_entity_attributes(self, entity, siderelations=None): for rschema, tschemas, role, dispctrl in self._section_def(entity, 'attributes'): vid = dispctrl.get('vid', 'reledit') - if rschema.is_final() or vid == 'reledit': + if rschema.final or vid == 'reledit': value = entity.view(vid, rtype=rschema.type, role=role) else: rset = self._relation_rset(entity, rschema, role, dispctrl) @@ -176,11 +176,8 @@ def _relation_rset(self, entity, rschema, role, dispctrl): try: - if dispctrl.get('limit'): - rset = entity.related(rschema.type, role, - limit=self.maxrelated+1) - else: - rset = entity.related(rschema.type, role) + dispctrl.setdefault('limit', self.maxrelated) + rset = entity.related(rschema.type, role, limit=dispctrl['limit']+1) except Unauthorized: return if 'filter' in dispctrl: @@ -191,11 +188,11 @@ self.w(u'
') if showlabel: self.w(u'

%s

' % self._cw._(dispctrl['label'])) - self.wview(dispctrl.get('vid', defaultvid), rset) + initargs={'dispctrl': dispctrl}) self.w(u'
') def _render_attribute(self, rschema, value, role='subject'): - if rschema.is_final(): + if rschema.final: show_label = self.show_attr_label else: show_label = self.show_rel_label @@ -205,12 +202,16 @@ class RelatedView(EntityView): __regid__ = 'autolimited' - def call(self, title=None, **kwargs): - # if not too many entities, show them all in a list - maxrelated = self._cw.property_value('navigation.related-limit') - if title: - self.w(u'
%s
' % title) - if self.cw_rset.rowcount <= maxrelated: + + def call(self, **kwargs): + # nb: rset retreived using entity.related with limit + 1 if any + # because of that, we known that rset.printable_rql() will return + # rql with no limit set anyway (since it's handled manually) + if 'dispctrl' in self.extra_kwargs: + limit = self.extra_kwargs['dispctrl'].get('limit') + else: + limit = None + if limit is None or self.cw_rset.rowcount <= limit: if self.cw_rset.rowcount == 1: self.wview('incontext', self.cw_rset, row=0) elif 1 < self.cw_rset.rowcount <= 5: @@ -222,7 +223,7 @@ # else show links to display related entities else: rql = self.cw_rset.printable_rql() - self.cw_rset.limit(maxrelated) + self.cw_rset.limit(maxrelated) # remove extra entity self.w(u'
') self.wview('simplelist', self.cw_rset) self.w(u'[%s]' % (self._cw.build_url(rql=rql), diff -r 29f74716fd70 -r 5376aaadd16b web/views/schema.py --- a/web/views/schema.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/schema.py Mon Oct 19 15:16:41 2009 +0200 @@ -88,11 +88,11 @@ schema = self._cw.schema # compute entities entities = sorted(eschema for eschema in schema.entities() - if not (eschema.is_final() or eschema in skiptypes)) + if not (eschema.final or eschema in skiptypes)) # compute relations if display_relations: relations = sorted(rschema for rschema in schema.relations() - if not (rschema.is_final() + if not (rschema.final or rschema in skiptypes or rschema in META_RTYPES)) else: @@ -337,7 +337,7 @@ viewer = SchemaViewer(self._cw) layout = viewer.visit_relationschema(rschema) self.w(uilib.ureport_as_html(layout)) - if not rschema.is_final(): + if not rschema.final: msg = self._cw._('graphical schema for %s') % entity.name self.w(tags.img(src=entity.absolute_url(vid='schemagraph'), alt=msg)) diff -r 29f74716fd70 -r 5376aaadd16b web/views/sparql.py --- a/web/views/sparql.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/sparql.py Mon Oct 19 15:16:41 2009 +0200 @@ -102,7 +102,7 @@ def cell_binding(self, row, col, varname): celltype = self.cw_rset.description[row][col] - if self._cw.schema.eschema(celltype).is_final(): + if self._cw.schema.eschema(celltype).final: cellcontent = self.view('cell', self.cw_rset, row=row, col=col) return E.binding(E.literal(cellcontent, datatype=xmlschema(celltype)), diff -r 29f74716fd70 -r 5376aaadd16b web/views/startup.py --- a/web/views/startup.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/startup.py Mon Oct 19 15:16:41 2009 +0200 @@ -130,7 +130,7 @@ """ req = self._cw for eschema in eschemas: - if eschema.is_final() or (not eschema.has_perm(req, 'read') and + if eschema.final or (not eschema.has_perm(req, 'read') and not eschema.has_local_role('read')): continue etype = eschema.type diff -r 29f74716fd70 -r 5376aaadd16b web/views/tableview.py --- a/web/views/tableview.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/tableview.py Mon Oct 19 15:16:41 2009 +0200 @@ -80,7 +80,7 @@ eschema = self._cw.vreg.schema.eschema for i, etype in enumerate(self.cw_rset.description[0]): try: - if not eschema(etype).is_final(): + if not eschema(etype).final: return i except KeyError: # XXX possible? continue @@ -207,7 +207,7 @@ # join, use the default non final subvid) if cellvids and colindex in cellvids: column.append_renderer(cellvids[colindex], colindex) - elif coltype is not None and self._cw.schema.eschema(coltype).is_final(): + elif coltype is not None and self._cw.schema.eschema(coltype).final: column.append_renderer(self.finalview, colindex) else: column.append_renderer(subvid or 'incontext', colindex) @@ -236,7 +236,7 @@ if val is None: return u'' etype = self.cw_rset.description[row][col] - if self._cw.schema.eschema(etype).is_final(): + if self._cw.schema.eschema(etype).final: entity, rtype = self.cw_rset.related_entity(row, col) if entity is None: return val # remove_html_tags() ? @@ -261,7 +261,7 @@ :param cellvid: cell view (defaults to 'outofcontext') """ etype, val = self.cw_rset.description[row][col], self.cw_rset[row][col] - if val is not None and not self._cw.schema.eschema(etype).is_final(): + if val is not None and not self._cw.schema.eschema(etype).final: e = self.cw_rset.get_entity(row, col) e.view(cellvid or 'outofcontext', w=self.w) elif val is None: diff -r 29f74716fd70 -r 5376aaadd16b web/views/urlpublishing.py --- a/web/views/urlpublishing.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/urlpublishing.py Mon Oct 19 15:16:41 2009 +0200 @@ -158,7 +158,7 @@ if len(parts) == 2: attrname = parts.pop(0).lower() try: - cls.e_schema.subject_relation(attrname) + cls.e_schema.subjrels[attrname] except KeyError: raise PathDontMatch() else: diff -r 29f74716fd70 -r 5376aaadd16b web/views/xmlrss.py --- a/web/views/xmlrss.py Thu Oct 15 11:20:26 2009 +0200 +++ b/web/views/xmlrss.py Mon Oct 19 15:16:41 2009 +0200 @@ -89,7 +89,7 @@ if '(' in tag: attrs['expr'] = tag tag = 'funccall' - if val is not None and not eschema(etype).is_final(): + if val is not None and not eschema(etype).final: attrs['eid'] = val # csvrow.append(val) # val is eid in that case val = self._cw.view('textincontext', rset,