def submit(self, req): ticket = Ticket(self.env) # required fields ticket['aid'] = req.args['aid'] description = req.args['description'] ticket['description'] = description ticket['summary'] = req.args.get('summary', description) # other fields excluded = ['aid', 'description', 'summary'] fields = [ field['name'] for field in ticket.fields if field['name'] not in excluded ] for field in fields: arg = req.args.get(field) if arg is not None: ticket[field] = arg # create the ticket _id = ticket.insert() # yield the ticket ID return {"servicerequestid": _id}
def save_changesets(self, ticket_id, author, rev, when=0): """ Store ticket setchangesets in the database. The ticket must already exist in the database. """ # TODO: fetch ticket and assert it exists ticket = Ticket(self.env, ticket_id) assert ticket.exists, 'Cannot update a new ticket' db = None if not db: db = self.env.get_db_cnx() handle_ta = True else: handle_ta = False cursor = db.cursor() when = int(when or time.time()) cursor.execute( "INSERT INTO ticket_revision (rev,ticket_id) VALUES(%s,%s)", (rev, ticket_id)) if handle_ta: db.commit() ticket._old = {} ticket.time_changed = when
def process_request(self, req): """Process the request.""" id = int(req.args.get('id')) req.perm('ticket', id).require('TICKET_VIEW') if 'TICKET_REMINDER_MODIFY' not in req.perm and \ 'TICKET_ADMIN' not in req.perm: raise PermissionError('TICKET_REMINDER_MODIFY', req.perm._resource, self.env) ticket = Ticket(self.env, id) if 'cancel' in req.args: req.redirect(get_resource_url(self.env, ticket.resource, req.href)) ticket_name = get_resource_name(self.env, ticket.resource) ticket_url = get_resource_url(self.env, ticket.resource, req.href) add_link(req, 'up', ticket_url, ticket_name) add_ctxtnav(req, _('Back to %(ticket)s', ticket=ticket_name), ticket_url) add_stylesheet(req, 'ticketreminder/css/ticketreminder.css') if req.args['action'] == "addreminder": return self._process_add(req, ticket) elif req.args['action'] == "deletereminder": return self._process_delete(req, ticket) else: raise ValueError('Unknown action "%s"' % (req.args['action'],))
def _handle_ripe_save(self, req): """ hander for save """ # TODO: workflow # get ticket id ticket_id = req.args.get("ticket_id") value = req.args.get("value", "").strip() field = req.args.get("field") old_value = req.args.get("old_value") # ticket ticket = Ticket(self.env, ticket_id) current_value = ticket.values.get(field) # validation if current_value != old_value and (old_value or current_value): self.log.info("Field value should be %s, got %s" % (repr(current_value), repr(old_value))) raise TracError("field value inconsistant.") # set params params = {} params[field] = value ticket.populate(params) # save ticket comment = "Updated from report" author = get_reporter_id(req, 'author') ticket.save_changes(author, comment) return value
def _insert_ticket(cls, env, summary, **kw): """Helper for inserting a ticket into the database""" ticket = Ticket(env) ticket["summary"] = summary for k, v in kw.items(): ticket[k] = v return ticket.insert()
def _get_action_controls(self, req, tickets): action_controls = [] ts = TicketSystem(self.env) tickets_by_action = {} for t in tickets: ticket = Ticket(self.env, t['id']) available_actions = ts.get_available_actions(req, ticket) for action in available_actions: tickets_by_action.setdefault(action, []).append(ticket) # Sort the allowed actions by the 'default' key. allowed_actions = set(tickets_by_action.keys()) workflow = ConfigurableTicketWorkflow(self.env) all_actions = sorted( ((action['default'], name) for name, action in workflow.get_all_actions().iteritems()), reverse=True) sorted_actions = [ action[1] for action in all_actions if action[1] in allowed_actions ] for action in sorted_actions: first_label = None hints = [] widgets = [] ticket = tickets_by_action[action][0] for controller in self._get_action_controllers( req, ticket, action): label, widget, hint = controller.render_ticket_action_control( req, ticket, action) if not first_label: first_label = label widgets.append(widget) hints.append(hint) action_controls.append((action, first_label, tag(widgets), hints)) return action_controls
def process_request(self, req): req.perm.assert_permission('TICKET_VIEW') action = req.args.get('action', 'view') if not req.args.has_key('id'): req.redirect(self.env.href.wiki()) db = self.env.get_db_cnx() id = int(req.args.get('id')) ticket = Ticket(self.env, id, db=db) reporter_id = util.get_reporter_id(req) if req.method == 'POST': if not req.args.has_key('preview'): self._do_save(req, db, ticket) else: # Use user supplied values ticket.populate(req.args) req.hdf['ticket.action'] = action req.hdf['ticket.ts'] = req.args.get('ts') req.hdf['ticket.reassign_owner'] = req.args.get('reassign_owner') \ or req.authname req.hdf['ticket.resolve_resolution'] = req.args.get('resolve_resolution') reporter_id = req.args.get('author') comment = req.args.get('comment') if comment: req.hdf['ticket.comment'] = util.escape(comment) # Wiki format a preview of comment req.hdf['ticket.comment_preview'] = wiki_to_html(comment, self.env, req, db) else: req.hdf['ticket.reassign_owner'] = req.authname # Store a timestamp in order to detect "mid air collisions" req.hdf['ticket.ts'] = ticket.time_changed self._insert_ticket_data(req, db, ticket, reporter_id) # If the ticket is being shown in the context of a query, add # links to help navigate in the query result set if 'query_tickets' in req.session: tickets = req.session['query_tickets'].split() if str(id) in tickets: idx = tickets.index(str(ticket.id)) if idx > 0: add_link(req, 'first', self.env.href.ticket(tickets[0]), 'Ticket #%s' % tickets[0]) add_link(req, 'prev', self.env.href.ticket(tickets[idx - 1]), 'Ticket #%s' % tickets[idx - 1]) if idx < len(tickets) - 1: add_link(req, 'next', self.env.href.ticket(tickets[idx + 1]), 'Ticket #%s' % tickets[idx + 1]) add_link(req, 'last', self.env.href.ticket(tickets[-1]), 'Ticket #%s' % tickets[-1]) add_link(req, 'up', req.session['query_href']) add_stylesheet(req, 'common/css/ticket.css') return 'ticket.cs', None
def _get_action_controls(self, req, tickets): action_controls = [] ts = TicketSystem(self.env) tickets_by_action = {} for t in tickets: ticket = Ticket(self.env, t['id']) actions = ts.get_available_actions(req, ticket) for action in actions: tickets_by_action.setdefault(action, []).append(ticket) sorted_actions = sorted(set(tickets_by_action.keys())) for action in sorted_actions: first_label = None hints = [] widgets = [] ticket = tickets_by_action[action][0] for controller in self._get_action_controllers( req, ticket, action): label, widget, hint = controller.render_ticket_action_control( req, ticket, action) if not first_label: first_label = label widgets.append(widget) hints.append(hint) action_controls.append((action, first_label, tag(widgets), hints)) return action_controls
def _update_ticket(self, changeset, biff_names, biff_cc): ticket_updator = self.env.compmgr.components.get(CommitTicketUpdater) if not ticket_updator: self.env.log.error('CommitTicketUpdater is not available, ' 'enable it to parse changeset message') return date = datetime.now(utc) tickets = ticket_updator._parse_message(changeset.message) perm = PermissionCache(self.env, changeset.author) for tkt_id, cmds in tickets.iteritems(): try: has_permission = False with self.env.db_transaction: ticket = Ticket(self.env, tkt_id) ticket_perm = perm(ticket.resource) for cmd in cmds: if cmd(ticket, changeset, ticket_perm) is not False: has_permission = True if has_permission: cc_list = ', ' + ', '.join(biff_cc) ticket['cc'] += cc_list fb_field = FileBiffTicketCustomField(ticket) fb_field.add(biff_names) if fb_field.is_updated: ticket.save_changes(changeset.author, '', date) except Exception as e: self.env.log.error('Unexpected error while processing ticket ' '#%s: %s', tkt_id, exception_to_unicode(e))
def process_action(self, msg, author, githash=None): self.env.log.debug('process_action') # Find all the #123 strings in the commit message. ticket_re = re.compile('#[0-9]+') ticket_numbers = ticket_re.findall(msg) # Turn the ticket numbers into ints. ticket_numbers = set( [int(ticket_number[1:]) for ticket_number in ticket_numbers]) # For each ticket date = datetime_now(utc) for ticket_number in ticket_numbers: self.env.log.debug( 'Found ticket number: {n}'.format(n=str(ticket_number))) if (githash is not None and self._githash_storecheck(ticket_number, githash)): continue try: db = self.env.get_db_cnx() ticket = Ticket(self.env, int(ticket_number), db) ticket.save_changes(author, msg, date) db.commit() self._notify(ticket, date) self.env.log.debug('Comment added') except ResourceNotFound, e: self.log.error( 'Ticket not found: {n}'.format(n=str(ticket_number))) continue
def test_can_add_a_comment_if_captcha_was_entered_correctly(self): ticket = self.add_ticket() self.grant_permission('anonymous', 'TICKET_APPEND') response = self.post_comment(ticket, 'foo', fake_captcha='open sesame') self.assert_equals(303, response.code()) self.assert_number_of_comments_for_ticket( 1, Ticket(self.env, tkt_id=ticket.id))
def _create_ticket_by_full_id(self, resource): env = self._get_env_for_resource(resource) if resource.realm == "ticket": return Ticket(env, resource.id) else: raise TracError("Resource type %s is not supported by " + "Bloodhound Relations" % resource.realm)
def _save_ticket_changes(self, req, env, log, selectedTickets, tickets, values, comment, modify_changetime, send_notifications): for id in selectedTickets: if id in tickets: t = Ticket(env, int(id)) new_changetime = datetime.now(utc) log_msg = "" if not modify_changetime: original_changetime = to_timestamp(t.time_changed) _values = values.copy() for field in [f for f in values.keys() \ if f in self._fields_as_list]: _values[field] = self._merge_keywords( t.values[field], values[field], log) t.populate(_values) t.save_changes(req.authname, comment, when=new_changetime) if send_notifications: tn = TicketNotifyEmail(env) tn.notify(t, newticket=0, modtime=new_changetime) if not modify_changetime: self._reset_changetime(env, original_changetime, t) log_msg = "(changetime not modified)" log.debug('BatchModifyPlugin: saved changes to #%s %s' % (id, log_msg))
def process(self, commit, status, branch): self.closestatus = status milestones = [ m.name for m in Milestone.select(self.env) if m.name != 'unknown' ] if branch.startswith('fixes/'): branch = branch[6:] milestones = [m for m in milestones if m.startswith(branch)] self.milestone = sorted(milestones)[-1] msg = commit['message'] self.env.log.debug("Processing Commit: %s", msg) msg = "%s \n Branch: %s \n Changeset: %s" % (msg, branch, commit['id']) # author = commit['author']['name'] author = 'Github' timestamp = datetime.now(utc) cmd_groups = command_re.findall(msg) self.env.log.debug("Function Handlers: %s" % cmd_groups) tickets = {} for cmd, tkts in cmd_groups: funcname = self.__class__._supported_cmds.get(cmd.lower(), '') self.env.log.debug("Function Handler: %s" % funcname) if funcname: for tkt_id in ticket_re.findall(tkts): if (branch == "master") or branch.startswith("fixes/"): tickets.setdefault(tkt_id, []).append(getattr(self, funcname)) # disable this stuff for now, it causes duplicates on merges # proper implementation of this will require tracking commit hashes # else: # tickets.setdefault(tkt_id, []).append(self._cmdRefs) for tkt_id, cmds in tickets.iteritems(): try: db = self.env.get_db_cnx() ticket = Ticket(self.env, int(tkt_id), db) for cmd in cmds: cmd(ticket) # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 ticket.save_changes(author, msg, timestamp, db, cnum + 1) db.commit() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=timestamp) except Exception, e: import traceback traceback.print_exc(file=sys.stderr)
def test_can_modify_ticket_if_captcha_was_entered_correctly(self): ticket = self.add_ticket() self.grant_permission('anonymous', 'TICKET_CHGPROP') response = self.post_ticket_modification(ticket, keywords='foobar', fake_captcha='open sesame') self.assert_equals(303, response.code()) self.assert_equals('foobar', Ticket(self.env, ticket.id)['keywords'])
def updateTicket(self, id, ticket, notification): """ """ try: tkt = Ticket(self.env, id, self.db) except TracError, detail: print "Cannot create Trac ticket : %s" % (detail) return
def test_delete_milestone_retarget_tickets(self): cursor = self.db.cursor() cursor.execute("INSERT INTO milestone (name) VALUES ('Test')") cursor.close() tkt1 = Ticket(self.env) tkt1.populate({'summary': 'Foo', 'milestone': 'Test'}) tkt1.insert() tkt2 = Ticket(self.env) tkt2.populate({'summary': 'Bar', 'milestone': 'Test'}) tkt2.insert() milestone = Milestone(self.env, 'Test') milestone.delete(retarget_to='Other') self.assertEqual('Other', Ticket(self.env, tkt1.id)['milestone']) self.assertEqual('Other', Ticket(self.env, tkt2.id)['milestone'])
def process_ticket(self, req): """process a request to /hours/<ticket number>""" # get the ticket path = req.path_info.rstrip('/') ticket_id = int(path.split('/')[-1]) # matches a ticket number ticket = Ticket(self.env, ticket_id) if req.method == 'POST': if 'addhours' in req.args: return self.do_ticket_change(req, ticket) if 'edithours' in req.args: return self.edit_ticket_hours(req, ticket) # XXX abstract date stuff as this is used multiple places now = datetime.now() months = [(i, calendar.month_name[i], i == now.month) for i in range(1, 13)] years = range(now.year, now.year - 10, -1) days = [(i, i == now.day) for i in range(1, 32)] time_records = self.get_ticket_hours(ticket.id) time_records.sort(key=lambda x: x['time_started'], reverse=True) # add additional data for the template total = 0 for record in time_records: record['date_started'] = self.format_date(record['time_started']) record['hours_worked'], record[ 'minutes_worked'] = self.format_hours_and_minutes( record['seconds_worked']) total += record['seconds_worked'] total = self.format_hours(total) data = { 'can_add_hours': req.perm.has_permission('TICKET_ADD_HOURS'), 'can_add_others_hours': req.perm.has_permission('TRAC_ADMIN'), 'days': days, 'months': months, 'years': years, 'users': get_all_users(self.env), 'total': total, 'ticket': ticket, 'time_records': time_records } # return the rss, if requested if req.args.get('format') == 'rss': return self.tickethours2rss(req, data) # add rss link rss_href = req.href(req.path_info, format='rss') add_link(req, 'alternate', rss_href, _('RSS Feed'), 'application/rss+xml', 'rss') add_ctxtnav(req, 'Back to Ticket #%s' % ticket_id, req.href.ticket(ticket_id)) return ('hours_ticket.html', data, 'text/html')
def ticket_created(self, ticket): """Called when a ticket is created.""" hours = convertfloat(ticket['hours']) # makes the hours a ticket change like all the other hours records if hours > 0: self.watch_hours(ticket) # clears the hours t = Ticket(self.env, ticket.id) t['hours'] = str(hours) t.save_changes(ticket['reporter'])
def __init__(self, project=options.project, author=AUTHOR, maxage=options.maxage, url=options.url): self.env = open_environment(project) db = self.env.get_db_cnx() cursor = db.cursor() if url is None: url = self.env.config.get('trac', 'base_url') self.env.href = Href(url) self.env.abs_href = Href(url) self.msg = MESSAGE % (maxage) self.now = int(time.time()) maxtime = int(time.time()) - (60 * 60 * 24 * maxage) cursor.execute("SELECT id FROM ticket t, ticket_custom c " \ "WHERE t.status <> %s " \ "AND t.changetime < %s " \ "AND t.id = c.ticket " \ "AND c.name = %s " \ "AND c.value = %s ", ('closed', maxtime, 'pending', '1')) rows = cursor.fetchall() for row in rows: id = row[0] try: ticket = Ticket(self.env, id, db) ticket['status'] = 'closed' ticket['pending'] = '0' # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 ticket.save_changes(author, self.msg, self.now, db, cnum + 1) db.commit() print 'Closing Ticket %s (%s)\n' % (id, ticket['summary']) tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=self.now) except Exception, e: import traceback traceback.print_exc(file=sys.stderr) print>>sys.stderr, 'Unexpected error while processing ticket ' \ 'ID %s: %s' % (id, e)
def test_update_milestone_update_tickets(self): cursor = self.db.cursor() cursor.execute("INSERT INTO milestone (name) VALUES ('Test')") cursor.close() tkt1 = Ticket(self.env) tkt1.populate({'summary': 'Foo', 'milestone': 'Test'}) tkt1.insert() tkt2 = Ticket(self.env) tkt2.populate({'summary': 'Bar', 'milestone': 'Test'}) tkt2.insert() milestone = Milestone(self.env, 'Test') milestone.name = 'Testing' milestone.update() self.assertEqual('Testing', Ticket(self.env, tkt1.id)['milestone']) self.assertEqual('Testing', Ticket(self.env, tkt2.id)['milestone'])
def invoke(self, message, warnings): """make a new ticket on receiving email""" # local warnings _warnings = [] # get the ticket reporter reporter = self.reporter(message) # get the description and attachments description, attachments = get_description_and_attachments(message) if description is None: description = '' description = description.strip() # get the ticket fields fields = self.fields(message, _warnings, reporter=reporter, description=description) # inset items from email ticket = Ticket(self.env) for key, value in fields.items(): ticket.values[key] = value # fill in default values for field in ticket.fields: name = field['name'] if name not in fields: option = 'ticket_field.%s' % name if self.env.config.has_option('mail', option): ticket.values[name] = self.env.config.get('mail', option) else: try: value = ticket.get_value_or_default(name) or '' except AttributeError: # BBB value = '' if value is not None: ticket.values[name] = value # create the ticket ticket.insert() # add attachments to the ticket add_attachments(self.env, ticket, attachments) # do whatever post-processing is necessary self.post_process(ticket) # add local warnings if _warnings: warning = """A ticket has been created but there is a problem:\n\n%s\n\nPlease edit your ticket by going here: %s""" % ( '\n\n'.join([' - %s' % warning for warning in _warnings ]), self.env.abs_href('ticket', ticket.id)) warnings.append(warning)
def __init__(self, project=options.project, author=options.user, rev=options.rev, url=options.url): self.env = open_environment(project) repos = self.env.get_repository() repos.sync() # Instead of bothering with the encoding, we'll use unicode data # as provided by the Trac versioncontrol API (#1310). try: chgset = repos.get_changeset(rev) except NoSuchChangeset: return # out of scope changesets are not cached self.author = chgset.author self.rev = rev self.msg = "(In [%s]) %s" % (rev, chgset.message) self.now = datetime.now(utc) cmd_groups = command_re.findall(self.msg) tickets = {} for cmd, tkts in cmd_groups: funcname = CommitHook._supported_cmds.get(cmd.lower(), '') if funcname: for tkt_id in ticket_re.findall(tkts): func = getattr(self, funcname) tickets.setdefault(tkt_id, []).append(func) for tkt_id, cmds in tickets.iteritems(): try: db = self.env.get_db_cnx() ticket = Ticket(self.env, int(tkt_id), db) for cmd in cmds: cmd(ticket) # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 ticket.save_changes(self.author, self.msg, self.now, db, cnum + 1) db.commit() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=self.now) except Exception, e: # import traceback # traceback.print_exc(file=sys.stderr) print>>sys.stderr, 'Unexpected error while processing ticket ' \ 'ID %s: %s' % (tkt_id, e)
def test_can_set_duplicate_resolution_even_if_relation_exists(self): t1 = self._insert_and_load_ticket("Foo") t2 = self._insert_and_load_ticket("Bar") self.relations_system.add(t2, t1, 'duplicateof') self.assertRaises(RequestDone, self.resolve_as_duplicate, t2, self.get_id(t1)) t2 = Ticket(self.env, t2.id) self.assertEqual(t2['status'], 'closed') self.assertEqual(t2['resolution'], 'duplicate')
def test_reject_comment_if_captcha_not_entered_at_all(self): ticket = self.add_ticket() self.grant_permission('anonymous', 'TICKET_APPEND') response = self.post_comment(ticket, 'foo') self.assert_equals(200, response.code()) self.assert_equals([self.fake_captcha_error()], response.trac_warnings()) self.assert_fake_captcha_is_visible(response) self.assert_number_of_comments_for_ticket( 0, Ticket(self.env, tkt_id=ticket.id))
def attachment_added(self, attachment): """Called when an attachment is added.""" if attachment.resource.parent.realm == 'ticket': try: filename, category = self.image_category(attachment) except TypeError: return if category == 'original': ticket = Ticket(self.env, attachment.resource.parent.id) self.create_sizes(ticket, attachment)
def test_can_reject_ticket_modification_if_captcha_not_entered_at_all( self): ticket = self.add_ticket() self.grant_permission('anonymous', 'TICKET_CHGPROP') response = self.post_ticket_modification(ticket, keywords='foobar') self.assert_equals(200, response.code()) self.assert_equals([self.fake_captcha_error()], response.trac_warnings()) self.assert_fake_captcha_is_visible(response) self.assert_equals('', Ticket(self.env, ticket.id)['keywords'] or '')
def process_request(self, req): req.perm.assert_permission('TICKET_CREATE') db = self.env.get_db_cnx() if req.method == 'POST' and not req.args.has_key('preview'): self._do_create(req, db) ticket = Ticket(self.env, db=db) ticket.populate(req.args) ticket.values.setdefault('reporter', util.get_reporter_id(req)) if ticket.values.has_key('description'): description = wiki_to_html(ticket['description'], self.env, req, db) req.hdf['newticket.description_preview'] = description req.hdf['title'] = 'New Ticket' req.hdf['newticket'] = dict( zip(ticket.values.keys(), [util.escape(value) for value in ticket.values.values()])) field_names = [ field['name'] for field in ticket.fields if not field.get('custom') ] if 'owner' in field_names: curr_idx = field_names.index('owner') if 'cc' in field_names: insert_idx = field_names.index('cc') else: insert_idx = len(field_names) if curr_idx < insert_idx: ticket.fields.insert(insert_idx, ticket.fields[curr_idx]) del ticket.fields[curr_idx] for field in ticket.fields: name = field['name'] del field['name'] if name in ('summary', 'reporter', 'description', 'type', 'status', 'resolution'): field['skip'] = True elif name == 'owner': field['label'] = 'Assign to' elif name == 'milestone': # Don't make completed milestones available for selection options = field['options'] for option in field['options']: milestone = Milestone(self.env, option, db=db) if milestone.is_completed: options.remove(option) field['options'] = options req.hdf['newticket.fields.' + name] = field add_stylesheet(req, 'common/css/ticket.css') return 'newticket.cs', None
def process(self, commit, status, enable_revmap, reponame): self.closestatus = status msg = commit['message'] self.env.log.debug("Processing Commit: %s", msg) note = "Changeset: [/changeset/%s %s]" % (commit['id'], commit['id']) url = "URL: %s" % commit['url'] msg = "%s \n * %s \n * %s" % (msg, note, url) author = commit['author']['name'] timestamp = datetime.now(utc) if int(enable_revmap): self.env.log.debug("adding commit %s to revmap", commit['id']) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO svn_revmap (svn_rev, git_hash, commit_msg) VALUES (0, %s, %s);", (commit['id'], commit['message'])) db.commit() cmd_groups = command_re.findall(msg) self.env.log.debug("Function Handlers: %s" % cmd_groups) tickets = {} for cmd, tkts in cmd_groups: funcname = self.__class__._supported_cmds.get(cmd.lower(), '') self.env.log.debug("Function Handler: %s" % funcname) if funcname: for tkt_id in ticket_re.findall(tkts): func = getattr(self, funcname) tickets.setdefault(tkt_id, []).append(func) for tkt_id, cmds in tickets.iteritems(): try: db = self.env.get_db_cnx() ticket = Ticket(self.env, int(tkt_id), db) for cmd in cmds: cmd(ticket) # determine sequence number... cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 ticket.save_changes(author, msg, timestamp, db, cnum + 1) db.commit() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=timestamp) except Exception, e: import traceback traceback.print_exc(file=sys.stderr)
def parse(self, fp): msg = email.message_from_file(fp) tkt = Ticket(self.env) tkt['status'] = 'new' tkt['reporter'] = msg['from'] tkt['summary'] = msg['subject'] for part in msg.walk(): if part.get_content_type() == 'text/plain': tkt['description'] = part.get_payload(decode=1).strip() if tkt['description']: tkt.insert()