def get_search_query(self): permission = self.get_value('permission') if permission == 'add': names = ['path'] else: names = ['path', 'format'] # Query query = AndQuery() for name in names: field_name = 'search_%s' % name field = self.get_field(field_name) value = field.get_value(self, field_name) if not value: continue if name == 'path': depth = self.get_value('search_path_depth') depth = None if depth == '*' else int(depth) subquery = get_base_path_query(value, 0, depth) elif field.multiple: err = "access rules don't yet support multiple fields" raise NotImplementedError, err else: subquery = PhraseQuery(name, value) query.append(subquery) # Ok return query
def get_payment_ways(self, enabled=None, as_results=False): query = AndQuery( get_base_path_query(self.get_canonical_path()), PhraseQuery('is_payment_way', True)) if enabled is not None: query.append(PhraseQuery('enabled', enabled)) results = self.get_root().search(query) if as_results is True: return results return results.get_documents()
def get_resource_by_uuid_query(uuid, base_class_id=None, class_id=None): # Base query query = AndQuery(PhraseQuery('uuid', uuid)) # Add filtering query elements if base_class_id: query.append(PhraseQuery('base_classes', base_class_id)) elif class_id: query.append(PhraseQuery('format', class_id)) # Ok return query
def check(self, value): from itools.database import AndQuery, NotQuery from itools.database import PhraseQuery if not value: return context = self.context here = context.resource query = AndQuery( NotQuery(PhraseQuery('abspath', str(here.abspath))), PhraseQuery(self.field_name, value)) if self.base_query: query.append(self.base_query) search = context.database.search(query) nb_results = len(search) if nb_results > 0: kw = {'nb_results': nb_results} self.raise_default_error(kw)
def get_events(self, day=None, *args): query = AndQuery(*args) query.append(PhraseQuery('base_classes', 'event')) if day: query.append(PhraseQuery('dates', day)) # Do not show hidden calendars context = get_context() for calendar in context.search(format='calendar').get_resources(): if context.user.name in calendar.get_value('hidden_for_users'): abspath = str(calendar.abspath) query.append(NotQuery(PhraseQuery('calendar', abspath))) # Ok search = self.context.search(query) return search.get_resources(sort_by='dtstart')
def test_AndQuery_single(self): query = AndQuery(PhraseQuery("data", u"mouse")) query.append(NotQuery(PhraseQuery("data", u"lion"))) results = self.database.search(query) self.assertEqual(len(results), 2)
def action(self, resource, context, form): filename, mimetype, body = form['file'] # Clean up f*ing Google export with no quote body = cleanup_gmail_csv(body) csv = CSVFile() csv.load_state_from_string(body) rows = csv.get_rows() # Decode header header = rows.next() root = context.root language = context.site_root.get_default_language() companies = resource.get_resource('companies') contacts = resource.get_resource('contacts') abspath = str(resource.get_canonical_path()) base_path_query = get_base_path_query(abspath) contacts_added = {} contacts_updated = [] companies_added = {} for row in rows: # Find company company_title = find_value_by_column(header, row, GMAIL_COMPANY) if company_title: company = None # FIXME the catalog should do this key = company_title.lower().translate(transmap) if key in companies_added: # Already added company = companies_added[key] else: # Search existing company query = AndQuery(base_path_query, PhraseQuery('format', 'company'), TextQuery('title', company_title)) results = root.search(query) for document in results.get_documents(): # Found company = root.get_resource(document.abspath) break else: # Creating company company = companies.add_company( title={language: company_title}) companies_added[key] = company else: company = thingy(name=None) # Find contact by name and company if available contact = None firstname = find_value_by_column(header, row, GMAIL_FIRST_NAME) lastname = find_value_by_column(header, row, GMAIL_LAST_NAME) email = find_value_by_column(header, row, GMAIL_EMAIL) key = (firstname, lastname, email, company_title) if key in contacts_added: # Already added contact = contacts_added[key] else: # Search existing contact query = AndQuery(base_path_query, PhraseQuery('format', 'contact')) if firstname: query.append(TextQuery('crm_p_firstname', firstname)) if lastname: query.append(TextQuery('crm_p_lastname', lastname)) if email: query.append(TextQuery('crm_p_email', email)) if company.name is not None: query.append(PhraseQuery('crm_p_company', company.name)) results = root.search(query) for document in results.get_documents(): # Found contact = root.get_resource(document.abspath) contacts_updated.append(contact) break else: # Creating contact contact = contacts.add_contact( crm_p_firstname=firstname, crm_p_lastname=lastname, crm_p_email=email, crm_p_company=company.name, crm_p_status='lead') contacts_added[key] = contact # Update contact for title, name in import_columns.iteritems(): if title in (GMAIL_FIRST_NAME, GMAIL_LAST_NAME, GMAIL_EMAIL, GMAIL_COMPANY): continue value = find_value_by_column(header, row, title) if value is not None: datatype = contact.get_property_datatype(name) if issubclass(datatype, String): value = value.encode('utf8') contact.set_property(name, value) message = [] pattern = u'<a href="{0}">{1}</a>' if contacts_added: n = len(contacts_added) contacts_added = u", ".join(pattern.format( context.get_link(contact), XMLContent.encode(contact.get_title())) for contact in contacts_added.itervalues()) message.append(MSG_CONTACTS_ADDED(n=n, added=contacts_added)) if contacts_updated: n = len(contacts_updated) contacts_updated = u", ".join(pattern.format( context.get_link(contact), XMLContent.encode(contact.get_title())) for contact in contacts_updated) message.append(MSG_CONTACTS_UPDATED(n=n, updated=contacts_updated)) if not message: message = ERR_NO_CONTACT_FOUND context.message = message
def test_AndQuery_empty(self): query = AndQuery() query.append(PhraseQuery('data', u'mouse')) query.append(NotQuery(PhraseQuery('data', u'lion'))) results = self.database.search(query) self.assertEqual(len(results), 2)
def get_search_query(self, resource, context): query = AndQuery() form = context.query for key, datatype in self.search_schema.items(): value = form[key] if value is None or value == '': continue # Special case: search on text, title and name AS AndQuery if key == 'text': text_query = [] value = value.split(' ') for v in value: t_query = OrQuery(TextQuery('title', v), TextQuery('text', v), PhraseQuery('name', v)) text_query.append(t_query) if len(text_query) == 1: text_query = text_query[0] else: text_query = AndQuery(*text_query) query.append(text_query) # Special case: type elif key == 'format': squery = [ PhraseQuery('format', x) for x in value.split(',') ] squery = squery[0] if len(squery) == 1 else OrQuery(*squery) query.append(squery) # Multiple elif datatype.multiple is True: query.append(OrQuery(*[ PhraseQuery(key, x) for x in value ])) # Singleton else: if value is False: # FIXME No value means False in xapian query.append(NotQuery(PhraseQuery(key, True))) else: query.append(PhraseQuery(key, value)) return query
def find_versions_to_update(context, force=False): database = context.database cls_errors = [] cls_to_update = [] # Find classes for cls in database.get_resource_classes(): # Class version class_version = class_version_to_date(cls.class_version) class_version_tomorrow = class_version + timedelta(days=1) # Search for code older than the instance query = AndQuery( PhraseQuery('format', cls.class_id), RangeQuery('class_version', class_version_tomorrow, None)) search = database.search(query) if search: resource = search.get_resources().next() kw = { 'class_id': resource.class_id, 'class_title': resource.class_title, 'abspath': str(resource.abspath), 'resource_version': resource.metadata.version, 'cls_version': resource.class_version } cls_errors.append(kw) if force is False: break # Find out the versions to upgrade classes_and_versions = [] for sub_cls in cls.mro(): for name in sub_cls.__dict__.keys(): if not name.startswith('update_'): continue kk, version = name.split('_', 1) if len(version) != 8: continue if not version.isdigit(): continue class_version = class_version_to_date(version) if class_version > class_version_to_date(cls.class_version): msg = "'{0}' class_version is bad ({1} > {2})" msg = msg.format(sub_cls.class_id, version, cls.class_version) raise ValueError(msg) class_version_yesterday = class_version - timedelta(days=1) query = AndQuery( PhraseQuery('format', cls.class_id), RangeQuery('class_version', None, class_version_yesterday)) search = database.search(query) if not search: continue class_and_version = (cls.class_id, version) if class_and_version in classes_and_versions: # Overriden update method in sub classes # So update method should be done one time continue classes_and_versions.append(class_and_version) update_title_name = 'update_{0}_title'.format(version) update_title = getattr(cls, update_title_name, MSG(u'Unknow')) if isinstance(update_title, MSG): update_title = update_title.gettext() kw = { 'class_id': cls.class_id, 'class_title': cls.class_title, 'class_version': version, 'class_version_date': class_version, 'class_version_pretty': context.format_date(class_version), 'update_title': update_title, 'nb_resources': len(search) } cls_to_update.append(kw) # Sort cls_to_update.sort(key=itemgetter('class_version_date')) # Ok return {'cls_to_update': cls_to_update, 'cls_errors': cls_errors}
def run_next_update_method(context, force=False): """Update the database to the given versions. """ database = context.database log = open('{0}/log/update'.format(database.path), 'w') messages = [] versions = find_versions_to_update(context, force) if not versions['cls_to_update']: return # Update version = versions['cls_to_update'][0] class_version = version['class_version_date'] class_version_yesterday = class_version - timedelta(days=1) query = AndQuery( PhraseQuery('format', version['class_id']), RangeQuery('class_version', None, class_version_yesterday)) search = context.database.search(query) # Commit message (Do not override the mtime/author) git_message = u'Upgrade {0} to version {1}'.format( version['class_id'], version['class_version']) print(git_message) context.git_message = git_message context.set_mtime = False # Update i = 0 resources_old2new = database.resources_old2new for resource in search.get_resources(): i += 1 path = str(resource.abspath) abspath = resources_old2new.get(path, path) if abspath is None: # resource deleted continue # Inconsistency on resource: we reindex it obj_version = resource.metadata.version cls_version = resource.class_version next_versions = resource.get_next_versions() if (obj_version == cls_version or not next_versions or next_versions[0] != version['class_version']): database.catalog.unindex_document(str(resource.abspath)) values = resource.get_catalog_values() database.catalog.index_document(values) continue try: if resource is not None: # If resource has not been deleted by update method, we update class_version resource.update(version['class_version']) except Exception: line = 'ERROR: "{0}" - class_id: "{1}"\n'.format( resource.abspath, resource.__class__.class_id) log.write(line) print_exc(file=log) log.write('\n') # Add message messages.append(line) if force is False: return messages # Commit every 200 resources for better performances if i % 200 == 0: database.save_changes() # Commit if not database.has_changed: # We reindex so the class_version is reindexed database.catalog.save_changes() else: database.save_changes() # Ok return messages
def search_forms(self): query = AndQuery(PhraseQuery('base_classes', 'form'), get_base_path_query(self.abspath)) return get_context().search(query)