def _query_link_words(self, context, name, value, class_, prepend=None, append=None): """Splits a list of words and makes a query link to each separately""" from trac.ticket.query import QueryModule if not (isinstance(value, basestring) and # None or other non-splitable self.env.is_component_enabled(QueryModule)): return value args = arg_list_to_args(parse_arg_list(self.ticketlink_query)) items = [] if prepend: items.extend(prepend) for i, word in enumerate(re.split(r'([;,\s]+)', value)): if i % 2: items.append(' ') elif word: backgroundColor = self.keyword_labels_section.get(word.lower()) fontColor = self.keyword_labels_section.get(word.lower() + '.font_color', 'white') if not backgroundColor: backgroundColor = ColorHash(word.encode('utf-8')).hex styles = { 'backgroundColor': backgroundColor, 'fontColor': fontColor, } word_args = args.copy() word_args[name] = '~' + word items.append(tag.a(word, style='background-color: {backgroundColor}; color: {fontColor}'.format(**styles), class_=class_, href=context.href.query(word_args))) if append: items.extend(append) return tag(items)
def test_qs_unicode(self): args = parse_arg_list(u'ké%3Dy=re%26su=mé&résu%26mé') self.assertTrue(unicode, type(args[0][0])) self.assertTrue(unicode, type(args[0][1])) self.assertEqual(u'ké=y', args[0][0]) self.assertEqual(u're&su=mé', args[0][1]) self.assertTrue(unicode, type(args[1][0])) self.assertEqual(u'résu&mé', args[1][0])
def test_qs_str(self): args = parse_arg_list('k%C3%A9y=resum%C3%A9&r%C3%A9sum%C3%A9') self.assertTrue(unicode, type(args[0][0])) self.assertTrue(unicode, type(args[0][1])) self.assertEqual(u'kéy', args[0][0]) self.assertEqual(u'resumé', args[0][1]) self.assertTrue(unicode, type(args[1][0])) self.assertEqual(u'résumé', args[1][0])
def test_qs_str_with_prefix(self): """The leading `?` should be stripped from the query string.""" args = parse_arg_list('?k%C3%A9y=resum%C3%A9&r%C3%A9sum%C3%A9') self.assertTrue(unicode, type(args[0][0])) self.assertTrue(unicode, type(args[0][1])) self.assertEqual(u'kéy', args[0][0]) self.assertEqual(u'resumé', args[0][1]) self.assertTrue(unicode, type(args[1][0])) self.assertEqual(u'résumé', args[1][0])
def next_link_args(limit): req = self.create_request(path_info='/log/mock/file', args={'revs': '70,79-82,94-100', 'limit': str(limit)}) template, data, ctype = self.process_request(req) links = req.chrome['links'] if 'next' in links: link = links['next'][0]['href'] path_info, query_string = link.split('?', 1) return dict(parse_arg_list(query_string)) else: return None
def _format_name(self, req, url): linkname = url name = "" missing = False path_info = url query_string = '' idx = path_info.find('?') if idx >= 0: path_info, query_string = path_info[:idx], path_info[idx:] href = req.href(path_info) + query_string args = arg_list_to_args(parse_arg_list(query_string.lstrip('?'))) version = args.get('version', False) path = path_info.strip('/').split('/') realm = path[0] class_ = realm if len(path) > 1: resource = Resource(realm, path[1]) if resource: if realm == 'ticket': linkname = get_resource_shortname(self.env, resource) try: name = get_resource_summary(self.env, resource) except ResourceNotFound: missing = True else: from trac.ticket.model import Ticket class_ = Ticket(self.env, resource.id)['status'] + \ ' ' + class_ elif realm == 'milestone': linkname = get_resource_name(self.env, resource) elif realm == 'wiki': resource = Resource(realm, '/'.join(path[1:]), version) linkname = get_resource_shortname(self.env, resource) if version: linkname += '@' + version elif realm == 'report': linkname = "{%s}" % path[1] name = self._format_report_name(path[1]) elif realm == 'changeset': rev = path[1] parent = Resource('source', '/'.join(path[2:])) resource = Resource(realm, rev, False, parent) linkname = "[%s]" % rev name = get_resource_description(self.env, resource) elif realm == 'browser': rm = RepositoryManager(self.env) reponame, repos, path = rm.get_repository_by_path('/'.join( path[1:])) parent = Resource('source', reponame) resource = Resource('source', path, False, parent) linkname = get_resource_description(self.env, resource) name = get_resource_summary(self.env, resource) elif realm == 'attachment': # Assume a file and check existence parent = Resource(path[1], '/'.join(path[2:-1])) resource = Resource(realm, path[-1], parent=parent) linkname = get_resource_name(self.env, resource) if not resource_exists(self.env, resource): # Assume an attachment list page and check existence parent = Resource(path[1], '/'.join(path[2:])) if resource_exists(self.env, parent): resource = Resource(realm, parent=parent) linkname = get_resource_name(self.env, resource) if not query_string: # Trailing slash needed for Trac < 1.0, t:#10280 href += '/' else: # Assume it's a missing attachment missing = True else: linkname = get_resource_shortname(self.env, resource) name = get_resource_summary(self.env, resource) elif len(path) == 1 and path[0] and path[0] != 'wiki': linkname = path[0].capitalize() else: class_ = 'wiki' linkname = 'WikiStart' if missing: href = None class_ = 'missing ' + realm return { 'class_': class_, 'href': href, 'linkname': linkname, 'name': name, 'delete': req.href.bookmark('delete_in_page', url), }
def process_request(self, req): self.log.debug('HTTP request: %s, method: %s, user: %s' % (req.path_info, req.method, req.authname)) if req.method != 'GET' and req.method != 'POST': return req.send([], content_type='application/json') board_id = None is_ticket_call = False match = self.request_regexp.match(req.path_info) if match: board_id = match.group('bid') is_ticket_call = match.group('ticket') is not None if not self.ticket_fields: self.ticket_fields = TicketSystem(self.env).get_ticket_fields() if board_id is None: meta_data = {} meta_data['ticketFields'] = self.ticket_fields return req.send(json.dumps(meta_data), content_type='application/json') arg_list = parse_arg_list(req.query_string) detailed_tickets = [] added_tickets = [] removed_tickets= [] for arg in arg_list: if arg[0] == 'detailed': detailed_tickets = self._parse_id_list(arg[1]) elif arg[0] == 'add': added_tickets = self._parse_id_list(arg[1]) elif arg[0] == 'remove': removed_tickets = self._parse_id_list(arg[1]) board = KanbanBoard(board_id, detailed_tickets, self.ticket_fields, self.env, self.log) added = 0 if len(added_tickets) > 0: added = board.add_tickets(added_tickets) removed = 0 if len(removed_tickets) > 0: removed = board.remove_tickets(removed_tickets) # We need to update board data to match (possibly changed) ticket states is_editable = 'WIKI_MODIFY' in req.perm and 'TICKET_MODIFY' in req.perm board.fix_ticket_columns(req, is_editable, added > 0 or removed > 0) if req.method == 'GET': return req.send(board.get_json(True, False), content_type='application/json') else: if is_ticket_call: ticket_data = json.loads(req.read()) is_new = 'id' not in ticket_data id = self.save_ticket(ticket_data, req.authname) if is_new: board.add_tickets([id]) else: board.update_tickets([id]) else: modified_tickets = [] column_data = json.loads(req.read()) for col in column_data: for ticket in col['tickets']: for key, value in ticket.items(): if key != 'id': self.save_ticket(ticket, req.authname) modified_tickets.append(ticket['id']) break board.update_columns(column_data) if modified_tickets: board.update_tickets(modified_tickets) board.fix_ticket_columns(req, True, True) return req.send(board.get_json(True, False), content_type='application/json')
def _format_name(self, req, url): linkname = url name = "" missing = False path_info = url query_string = '' idx = path_info.find('?') if idx >= 0: path_info, query_string = path_info[:idx], path_info[idx:] href = req.href(path_info) + query_string args = arg_list_to_args(parse_arg_list(query_string.lstrip('?'))) version = args.get('version', False) path = path_info.strip('/').split('/') realm = path[0] class_ = realm if len(path) > 1: resource = Resource(realm, path[1]) if resource: if realm == 'ticket': linkname = get_resource_shortname(self.env, resource) try: name = get_resource_summary(self.env, resource) except ResourceNotFound: missing = True else: from trac.ticket.model import Ticket class_ = Ticket(self.env, resource.id)['status'] + \ ' ' + class_ elif realm == 'milestone': linkname = get_resource_name(self.env, resource) elif realm == 'wiki': resource = Resource(realm, '/'.join(path[1:]), version) linkname = get_resource_shortname(self.env, resource) if version: linkname += '@' + version elif realm == 'report': linkname = "{%s}" % path[1] name = self._format_report_name(path[1]) elif realm == 'changeset': rev = path[1] parent = Resource('source', '/'.join(path[2:])) resource = Resource(realm, rev, False, parent) linkname = "[%s]" % rev name = get_resource_description(self.env, resource) elif realm == 'browser': parent = Resource('source', path[1]) resource = Resource('source', '/'.join(path[2:]), False, parent) linkname = get_resource_description(self.env, resource) name = get_resource_summary(self.env, resource) elif realm == 'attachment': # Assume a file and check existence parent = Resource(path[1], '/'.join(path[2:-1])) resource = Resource(realm, path[-1], parent=parent) linkname = get_resource_name(self.env, resource) if not resource_exists(self.env, resource): # Assume an attachment list page and check existence parent = Resource(path[1], '/'.join(path[2:])) if resource_exists(self.env, parent): resource = Resource(realm, parent=parent) linkname = get_resource_name(self.env, resource) if not query_string: # Trailing slash needed for Trac < 1.0, t:#10280 href += '/' else: # Assume it's a missing attachment missing = True else: linkname = get_resource_shortname(self.env, resource) name = get_resource_summary(self.env, resource) elif len(path) == 1 and path[0] and path[0] != 'wiki': linkname = path[0].capitalize() else: class_ = 'wiki' linkname = 'WikiStart' if missing: href = None class_ = 'missing ' + realm return { 'class_': class_, 'href': href, 'linkname': linkname, 'name': name, 'delete': req.href.bookmark('delete_in_page', url), }