def detail_view(self, req, cat, page, ticket_type): # All keys are saved lower-cased, but this is not done # automatically for retrieval calc_prop = self.agilo_config.get_list( '%s.%s' % (ticket_type, LinkOption.CALCULATE), section=AgiloConfig.AGILO_LINKS) calculated_properties = [] if len(calc_prop) > 0: for definition in calc_prop: parts = definition.split('=', 1) if len(parts) == 2: property_name, formula = parts calculated_properties.append( (property_name.strip(), formula.strip())) else: message = u"Ignoring broken definition for " \ "calculated property: %s" % definition warning(self, message) data = { 'calculate': calculated_properties, 'view': 'detail', 'type': ticket_type, 'alias': self.agilo_config.ALIASES.get(ticket_type, ''), 'type_fields': self._get_fields(ticket_type), 'labels': self._get_field_labels(), } return 'agilo_admin_types.html', data
def detail_view(self, req, cat, page, ticket_type): # All keys are saved lower-cased, but this is not done # automatically for retrieval calc_prop = self.agilo_config.get_list('%s.%s' % (ticket_type, LinkOption.CALCULATE), section=AgiloConfig.AGILO_LINKS) calculated_properties = [] if len(calc_prop) > 0: for definition in calc_prop: parts = definition.split('=', 1) if len(parts) == 2: property_name, formula = parts calculated_properties.append((property_name.strip(), formula.strip())) else: message = u"Ignoring broken definition for " \ "calculated property: %s" % definition warning(self, message) data = { 'calculate' : calculated_properties, 'view': 'detail', 'type': ticket_type, 'alias' : self.agilo_config.ALIASES.get(ticket_type, ''), 'type_fields' : self._get_fields(ticket_type), 'labels' : self._get_field_labels(), } return 'agilo_admin_types.html', data
def _load_json_data(self, http_body): try: data = json.loads(http_body) except Exception, e: msg = u'Received invalid JSON request %s' % \ exception_to_unicode(e) log.warning(self, msg) data = None
def interesting_fieldnames(self): fieldnames = [] for field in AgiloTicketSystem(self.env).get_ticket_fields(): fieldname = field[Key.NAME] # AT: here key must be a string or will break the call # afterwards try: fieldname = str(fieldname) except ValueError, e: warning(self, "Fieldname: %s is not a string... %s" % \ (repr(fieldname), exception_to_unicode(e))) continue fieldnames.append(fieldname)
def get_tickets_matching(self, t_id, summary): """ Returns a list of dictionaries (id: value, summary: value) matching the summary request and excluding the requesting ticket having id = id. """ try: t_id = int(t_id) # Make sure it is an int :-) keyword = re.compile(summary, re.IGNORECASE) db = self.env.get_db_cnx() from agilo.ticket.model import AgiloTicketModelManager sql = """SELECT id, type, summary FROM ticket WHERE id != $id $allowed AND id NOT IN (SELECT dest FROM %s WHERE src = $id UNION SELECT src FROM %s WHERE dest = $id) ORDER BY summary""" \ % (LINKS_TABLE, LINKS_TABLE) sql_query = string.Template(sql) sql_allowed = "AND ticket.type IN ('%s')" t_type = AgiloTicketModelManager( self.env).get(tkt_id=t_id).get_type() linkconfig = LinksConfiguration(self.env) if linkconfig.is_allowed_source_type(t_type): allowed_types = linkconfig.get_allowed_destination_types( t_type) allowed = sql_allowed % '\', \''.join(allowed_types) else: debug(self, "No Key found for #%s#" % repr(t_type)) allowed = '' sql_query = sql_query.substitute({'id': t_id, 'allowed': allowed}) debug(self, "SQL: %s" % sql_query) cursor = db.cursor() cursor.execute(sql_query) results = [] for row in cursor: if keyword.search(row[2] or ''): results.append({ 'id': row[0], 'type': row[1], 'summary': row[2] }) debug(self, "Search Results: %s" % str(results)) return results except Exception, e: warning(self, e) msg = "[%s]: ERROR: Search module unable to complete query!" % \ self.__class__.__name__ raise TracError(msg)
def get_users_last_visits(env, db=None): """Returns a list of tuples (username, lastvisit) from the session table""" db, handle_ta = get_db_for_write(env, db) users = [] try: cursor = db.cursor() cursor.execute("SELECT sid, last_visit FROM session WHERE authenticated = 1") for row in cursor.fetchall(): if row and len(row) == 2: users.append((row[0], row[1])) return users except Exception, e: warning(env, _("Could not load users from session table: %s" % \ exception_to_unicode(e)))
def _iterate(self, data, key=None, command=None): """ Operator to iterate over a sequence and return the items matching the given condition. If no condition is supplied an Alias replacing will be attempted on the whole list. The operator returns a list """ # Check if the key contains also a condition condition = realkey = None if key is not None and isinstance(key, tuple): realkey, condition = key else: realkey = key #debug(self, "[Iterate]: Processing %s with %s, command: #%s#" % \ # (repr(data), key, command)) # Now process the data, take the analyzed data that should be pointers to the # real ones, so that the real_data gets modified too if data is not None and hasattr(data, '__iter__'): for i, item in enumerate(data): #debug(self, "[Iterate]: Command left: %s\ni: %d\ndata[%d] = %s" % \ # (command, i, i, data[i])) if (condition is not None and eval(condition)) or condition is None: if realkey is not None: try: if not command: #debug(self, "[Iterate]: No command left, " \ # "calculating aliases...") data[i][realkey] = self._aliasize( item[realkey]) else: #debug(self, "[Iterate]: Processing next " \ # "command... %s" % command) # The command in this case is not consumed, # because we are in a cycle and the same command # has to be used to evaluate all items. acc, newkey, newcommand = self._parse_command( command) if acc is not None: #debug(self, "[Iterate]: calling\nacc: %s\n" \ # "data[%s], data: %s\nkey: %s\n\n" % \ # (acc, realkey, data[i], newkey)) acc(data[i][realkey], newkey, newcommand) except KeyError, e: warning( self, "[Iterate]: Warning %s" % exception_to_unicode(e)) else: data[i] = self._aliasize(item)
def get_users_last_visits(env, db=None): """Returns a list of tuples (username, lastvisit) from the session table""" db, handle_ta = get_db_for_write(env, db) users = [] try: cursor = db.cursor() cursor.execute( "SELECT sid, last_visit FROM session WHERE authenticated = 1") for row in cursor.fetchall(): if row and len(row) == 2: users.append((row[0], row[1])) return users except Exception, e: warning(env, _("Could not load users from session table: %s" % \ exception_to_unicode(e)))
def _get_day_key(self, day): """Returns the key and the date for the given day""" d_day = None if isinstance(day, datetime): d_day = day.date() elif isinstance(day, date): d_day = day elif isinstance(day, basestring): d_day = parse_date(day).date() elif isinstance(day, (int, long)): try: d_day = to_datetime(day).date() except TypeError, e: warning(self, _("Unable to covert %s to a date: %s" % \ (day, to_unicode(e))))
def get_user_attribute_from_session(env, attr, username, db=None): """ Returns the given attribute value if present in the session_attribute table, for this team members """ db = get_db_for_read(env, db) try: cursor = db.cursor() cursor.execute("SELECT value FROM session_attribute WHERE sid=%s AND name=%s", [username, attr]) value = cursor.fetchone() if value is not None: return value[0] except Exception, e: warning(env, _("Could not load attribute: %s for TeamMember: %s => %s" % \ (attr, username, exception_to_unicode(e))))
def set_user_attribute_in_session(env, attr, value, username, db=None): db, handle_ta = get_db_for_write(env, db) try: cursor = db.cursor() if get_user_attribute_from_session(env, attr, username, db=db) is not None: cursor.execute("UPDATE session_attribute SET value=%s WHERE sid=%s" \ " AND name=%s", [value, username, attr]) else: cursor.execute("INSERT INTO session_attribute (sid, authenticated, name, value)" \ " VALUES (%s, %s, %s, %s)", [username, 1, attr, value]) if handle_ta: db.commit() except Exception, e: if handle_ta: db.rollback() warning(env, _("Could not store attribute: %s=%s for TeamMember: %s => %s" % \ (attr, value, username, exception_to_unicode(e))))
def get_user_attribute_from_session(env, attr, username, db=None): """ Returns the given attribute value if present in the session_attribute table, for this team members """ db = get_db_for_read(env, db) try: cursor = db.cursor() cursor.execute( "SELECT value FROM session_attribute WHERE sid=%s AND name=%s", [username, attr]) value = cursor.fetchone() if value is not None: return value[0] except Exception, e: warning(env, _("Could not load attribute: %s for TeamMember: %s => %s" % \ (attr, username, exception_to_unicode(e))))
def _process(prop_type): """ Process the final property """ try: if prop_type in self._type_to_alias: #debug(self, "[Aliasize]: Returning %s for %s" % \ # (self._type_to_alias[prop_type], prop_type)) return self._type_to_alias[prop_type] elif prop_type in self._alias_mapping: #debug(self, "[Aliasize]: Returning %s for %s" % \ # (self._alias_mapping[prop_type], prop_type)) return self._alias_mapping[prop_type] # else: # warning(self, "No alias found for %s..." % prop_type) except TypeError, e: warning(self, "[Aliasize]: Error, %s" % exception_to_unicode(e))
def get_tickets_matching(self, t_id, summary): """ Returns a list of dictionaries (id: value, summary: value) matching the summary request and excluding the requesting ticket having id = id. """ try: t_id = int(t_id) # Make sure it is an int :-) keyword = re.compile(summary, re.IGNORECASE) db = self.env.get_db_cnx() from agilo.ticket.model import AgiloTicketModelManager sql = """SELECT id, type, summary FROM ticket WHERE id != $id $allowed AND id NOT IN (SELECT dest FROM %s WHERE src = $id UNION SELECT src FROM %s WHERE dest = $id) ORDER BY summary""" \ % (LINKS_TABLE, LINKS_TABLE) sql_query = string.Template(sql) sql_allowed = "AND ticket.type IN ('%s')" t_type = AgiloTicketModelManager(self.env).get(tkt_id=t_id).get_type() linkconfig = LinksConfiguration(self.env) if linkconfig.is_allowed_source_type(t_type): allowed_types = linkconfig.get_allowed_destination_types(t_type) allowed = sql_allowed % '\', \''.join(allowed_types) else: debug(self, "No Key found for #%s#" % repr(t_type)) allowed = '' sql_query = sql_query.substitute({'id' : t_id, 'allowed' : allowed}) debug(self, "SQL: %s" % sql_query) cursor = db.cursor() cursor.execute(sql_query) results = [] for row in cursor: if keyword.search(row[2] or ''): results.append({'id': row[0], 'type': row[1], 'summary': row[2]}) debug(self, "Search Results: %s" % str(results)) return results except Exception, e: warning(self, e) msg = "[%s]: ERROR: Search module unable to complete query!" % \ self.__class__.__name__ raise TracError(msg)
def _iterate(self, data, key=None, command=None): """ Operator to iterate over a sequence and return the items matching the given condition. If no condition is supplied an Alias replacing will be attempted on the whole list. The operator returns a list """ # Check if the key contains also a condition condition = realkey = None if key is not None and isinstance(key, tuple): realkey, condition = key else: realkey = key #debug(self, "[Iterate]: Processing %s with %s, command: #%s#" % \ # (repr(data), key, command)) # Now process the data, take the analyzed data that should be pointers to the # real ones, so that the real_data gets modified too if data is not None and hasattr(data, '__iter__'): for i, item in enumerate(data): #debug(self, "[Iterate]: Command left: %s\ni: %d\ndata[%d] = %s" % \ # (command, i, i, data[i])) if (condition is not None and eval(condition)) or condition is None: if realkey is not None: try: if not command: #debug(self, "[Iterate]: No command left, " \ # "calculating aliases...") data[i][realkey] = self._aliasize(item[realkey]) else: #debug(self, "[Iterate]: Processing next " \ # "command... %s" % command) # The command in this case is not consumed, # because we are in a cycle and the same command # has to be used to evaluate all items. acc, newkey, newcommand = self._parse_command(command) if acc is not None: #debug(self, "[Iterate]: calling\nacc: %s\n" \ # "data[%s], data: %s\nkey: %s\n\n" % \ # (acc, realkey, data[i], newkey)) acc(data[i][realkey], newkey, newcommand) except KeyError, e: warning(self, "[Iterate]: Warning %s" % exception_to_unicode(e)) else: data[i] = self._aliasize(item)
def _get_values_for_property_name(self, ticket, property_name): values = [] found_attribute = False property_names = property_name.split('.', 1) name = property_names[0] property_value = None try: property_value = getattr(ticket, name) found_attribute = True except AttributeError: found_attribute = False if not found_attribute: # We can't rely on the ticket's knowlegde of its fields because the # alias module will replace the type which will cause all fields to # be resetted to [] # if hasattr(ticket, 'is_readable_field'): # if ticket.is_readable_field(name): # property_value = ticket[name] # found_attribute = True # else: try: property_value = ticket[name] found_attribute = (property_value != None) except TypeError: pass if not found_attribute and self.component: msg = u"No attribute '%s' found in '%s'" % (ticket, name) warning(self.component, msg) if found_attribute and callable(property_value): # for performance reasons, tickets of types which are not included in the backlog are not loaded # so here we need to force loading them for the calculation to be correct if str(property_value.__name__) == 'get_outgoing' or str( property_value.__name__) == 'get_incoming': property_value = property_value(force_reload=True) else: property_value = property_value() found_attribute = (property_value != None) if found_attribute: if self._is_iterable(property_value): for item in property_value: values.append((ticket, item)) else: values.append((ticket, property_value)) if len(property_names) > 1: if len(values) == 0: # A empty list was retrieved from the ticket values = None else: real_values = [] attribute_name = property_names[1] for old_base_object, item in values: real_value = self._get_values_for_property_name( item, attribute_name) if real_value != None: real_values.extend(real_value) if len(values) == 1 and len(real_values) == 0: real_values = None values = real_values else: values = None return values
def _get_values_for_property_name(self, ticket, property_name): values = [] found_attribute = False property_names = property_name.split('.', 1) name = property_names[0] property_value = None try: property_value = getattr(ticket, name) found_attribute = True except AttributeError: found_attribute = False if not found_attribute: # We can't rely on the ticket's knowlegde of its fields because the # alias module will replace the type which will cause all fields to # be resetted to [] # if hasattr(ticket, 'is_readable_field'): # if ticket.is_readable_field(name): # property_value = ticket[name] # found_attribute = True # else: try: property_value = ticket[name] found_attribute = (property_value != None) except TypeError: pass if not found_attribute and self.component: msg = u"No attribute '%s' found in '%s'" % (ticket, name) warning(self.component, msg) if found_attribute and callable(property_value): # for performance reasons, tickets of types which are not included in the backlog are not loaded # so here we need to force loading them for the calculation to be correct if str(property_value.__name__) == 'get_outgoing' or str(property_value.__name__) == 'get_incoming': property_value = property_value(force_reload=True) else: property_value = property_value() found_attribute = (property_value != None) if found_attribute: if self._is_iterable(property_value): for item in property_value: values.append((ticket, item)) else: values.append((ticket, property_value)) if len(property_names) > 1: if len(values) == 0: # A empty list was retrieved from the ticket values = None else: real_values = [] attribute_name = property_names[1] for old_base_object, item in values: real_value = self._get_values_for_property_name(item, attribute_name) if real_value != None: real_values.extend(real_value) if len(values) == 1 and len(real_values) == 0: real_values = None values = real_values else: values = None return values