You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2013/05/24 20:48:55 UTC
[11/15] git commit: [#5656] ticket:353 refactored bulk move tickets
[#5656] ticket:353 refactored bulk move tickets
Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/224499a9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/224499a9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/224499a9
Branch: refs/heads/master
Commit: 224499a93142cefe434b604602f27bdda2957fa0
Parents: f7e873b
Author: Yuriy Arhipov <yu...@yandex.ru>
Authored: Mon May 20 13:07:41 2013 +0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri May 24 18:42:27 2013 +0000
----------------------------------------------------------------------
Allura/allura/tasks/tracker_task.py | 25 +++++
.../forgetracker/data/mass_move_report.html | 20 ++++-
ForgeTracker/forgetracker/data/mass_report | 2 +-
ForgeTracker/forgetracker/model/ticket.py | 79 ++++++++++++++-
.../forgetracker/tests/functional/test_root.py | 16 ++--
ForgeTracker/forgetracker/tracker_main.py | 79 +--------------
6 files changed, 135 insertions(+), 86 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/224499a9/Allura/allura/tasks/tracker_task.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/tracker_task.py b/Allura/allura/tasks/tracker_task.py
new file mode 100644
index 0000000..0a37850
--- /dev/null
+++ b/Allura/allura/tasks/tracker_task.py
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+from allura.lib.decorators import task
+from pylons import tmpl_context as c
+
+
+@task
+def move_tickets(ticket_ids, destination_tracker_id):
+ c.app.globals.move_tickets(ticket_ids, destination_tracker_id)
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/224499a9/ForgeTracker/forgetracker/data/mass_move_report.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/data/mass_move_report.html b/ForgeTracker/forgetracker/data/mass_move_report.html
index 3ace7c6..1312f54 100644
--- a/ForgeTracker/forgetracker/data/mass_move_report.html
+++ b/ForgeTracker/forgetracker/data/mass_move_report.html
@@ -1,5 +1,23 @@
+{#
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+#}
Tickets were moved from [{{original_tracker}}] to [{{destination_tracker}}]
{% for t in tickets %}
-- [{{original_tracker}}:#{{t['original_num']}}] --> [{{destination_tracker}}:#{{t['destination_num']}}] {{t['summary']}}
+- {{original_tracker}}:#{{t['original_num']}} --> {{destination_tracker}}:#{{t['destination_num']}} {{t['summary']}}
{% endfor %}
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/224499a9/ForgeTracker/forgetracker/data/mass_report
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/data/mass_report b/ForgeTracker/forgetracker/data/mass_report
index 7e8e47d..70fe1f7 100644
--- a/ForgeTracker/forgetracker/data/mass_report
+++ b/ForgeTracker/forgetracker/data/mass_report
@@ -19,7 +19,7 @@
{{ data.header }}
{% for ticket, change_text in data.changes %}
-ticket: [{{ context.app.config.options.mount_point }}:#{{ ticket.ticket_num }}] {{ ticket.summary }}
+ticket: {{ context.app.config.options.mount_point }}:#{{ ticket.ticket_num }} {{ ticket.summary }}
{{ change_text }}
{% endfor %}
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/224499a9/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 75c8bca..3a6803d 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -20,6 +20,7 @@ import urllib
import json
import difflib
from datetime import datetime, timedelta
+from bson import ObjectId
import pymongo
from pymongo.errors import OperationFailure
@@ -33,7 +34,7 @@ from ming.orm import FieldProperty, ForeignIdProperty, RelationProperty
from ming.orm.declarative import MappedClass
from allura.model import (Artifact, VersionedArtifact, Snapshot,
- project_orm_session, BaseAttachment, VotableArtifact)
+ project_orm_session, BaseAttachment, VotableArtifact, AppConfig, Mailbox, User)
from allura.model import User, Feed, Thread, Notification, ProjectRole
from allura.model import ACE, ALL_PERMISSIONS, DENY_ALL
from allura.model.timeline import ActivityObject
@@ -42,6 +43,7 @@ from allura.lib import security
from allura.lib.search import search_artifact, SearchError
from allura.lib import utils
from allura.lib import helpers as h
+from allura.tasks import mail_tasks
from forgetracker.plugins import ImportIdConverter
@@ -225,6 +227,81 @@ class Globals(MappedClass):
return Ticket.query.find(dict(
app_config_id=c.app.config._id, deleted=True)).count() > 0
+ def move_tickets(self, ticket_ids, destination_tracker_id):
+ tracker = AppConfig.query.get(_id=destination_tracker_id)
+ tickets = Ticket.query.find(dict(
+ _id={'$in': [ObjectId(id) for id in ticket_ids]},
+ app_config_id=c.app.config._id)).all()
+ filtered = self.filtered_by_subscription({t._id: t for t in tickets})
+ original_ticket_nums = {t._id: t.ticket_num for t in tickets}
+ users = User.query.find({'_id': {'$in': filtered.keys()}}).all()
+ moved_tickets = {}
+ for ticket in tickets:
+ moved = ticket.move(tracker, notify=False)
+ moved_tickets[moved._id] = moved
+ mail = dict(
+ fromaddr = str(c.user.email_address_header()),
+ reply_to = str(c.user.email_address_header()),
+ subject = '%s:%s Mass ticket moving by %s' % (c.project.shortname,
+ c.app.config.options.mount_point,
+ c.user.display_name))
+ tmpl = g.jinja2_env.get_template('forgetracker:data/mass_move_report.html')
+
+ tmpl_context = {
+ 'original_tracker': '%s:%s' % (c.project.shortname,
+ c.app.config.options.mount_point),
+ 'destination_tracker': '%s:%s' % (tracker.project.shortname,
+ tracker.options.mount_point),
+ 'tickets': [],
+ }
+ for user in users:
+ tmpl_context['tickets'] = ({
+ 'original_num': original_ticket_nums[_id],
+ 'destination_num': moved_tickets[_id].ticket_num,
+ 'summary': moved_tickets[_id].summary
+ } for _id in filtered.get(user._id, []))
+ mail.update(dict(
+ message_id = h.gen_message_id(),
+ text = tmpl.render(tmpl_context),
+ destinations = [str(user._id)]))
+ mail_tasks.sendmail.post(**mail)
+
+ if c.app.config.options.get('TicketMonitoringType') == 'AllTicketChanges':
+ monitoring_email = c.app.config.options.get('TicketMonitoringEmail')
+ tmpl_context['tickets'] = ({
+ 'original_num': original_ticket_nums[_id],
+ 'destination_num': moved_tickets[_id].ticket_num,
+ 'summary': moved_tickets[_id].summary
+ } for _id in moved_tickets.keys())
+ mail.update(dict(
+ message_id = h.gen_message_id(),
+ text = tmpl.render(tmpl_context),
+ destinations = [monitoring_email]))
+ mail_tasks.sendmail.post(**mail)
+
+ def filtered_by_subscription(self, tickets, project_id=None, app_config_id=None):
+ p_id = project_id if project_id else c.project._id
+ ac_id = app_config_id if app_config_id else c.app.config._id
+ ticket_ids = tickets.keys()
+ users = Mailbox.query.find(dict(project_id=p_id, app_config_id=ac_id))
+ users = [u.user_id for u in users]
+ filtered = {}
+ for uid in users:
+ params = dict(
+ user_id=uid,
+ project_id=p_id,
+ app_config_id=ac_id)
+ if Mailbox.subscribed(**params):
+ filtered[uid] = set(ticket_ids) # subscribed to entire tool, will see all changes
+ continue
+ for t_id, ticket in tickets.iteritems():
+ params.update({'artifact': ticket})
+ if Mailbox.subscribed(**params):
+ if filtered.get(uid) is None:
+ filtered[uid] = set()
+ filtered[uid].add(t_id)
+ return filtered
+
class TicketHistory(Snapshot):
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/224499a9/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index da6544b..37b3399 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -28,12 +28,12 @@ from mock import patch
from nose.tools import assert_true, assert_false, assert_equal, assert_in
from nose.tools import assert_raises, assert_not_in
from formencode.variabledecode import variable_encode
+from pylons import tmpl_context as c
from alluratest.controller import TestController
from allura import model as M
from forgewiki import model as wm
from forgetracker import model as tm
-from forgetracker.tracker_main import filtered_by_subscription
from allura.lib.security import has_access
from allura.lib import helpers as h
@@ -1264,17 +1264,17 @@ class TestFunctionalController(TrackerTestController):
- **Milestone**: 2.0
'''
- first_ticket_changes = '''ticket: [bugs:#1] test first ticket
+ first_ticket_changes = '''ticket: bugs:#1 test first ticket
- **Owner**: Anonymous --> Test Admin
- **Status**: open --> accepted
'''
- second_ticket_changes = '''ticket: [bugs:#2] test second ticket
+ second_ticket_changes = '''ticket: bugs:#2 test second ticket
- **Owner**: Anonymous --> Test Admin
- **Milestone**: 1.0 --> 2.0
'''
- third_ticket_changes = '''ticket: [bugs:#3] test third ticket
+ third_ticket_changes = '''ticket: bugs:#3 test third ticket
- **Owner**: Anonymous --> Test Admin
- **Status**: unread --> accepted
@@ -1432,7 +1432,7 @@ class TestFunctionalController(TrackerTestController):
tickets[0]._id: tickets[0],
tickets[1]._id: tickets[1],
}
- filtered_changes = filtered_by_subscription(changes)
+ filtered_changes = c.app.globals.filtered_by_subscription(changes)
filtered_users = [uid for uid, data in filtered_changes.iteritems()]
assert_equal(sorted(filtered_users), sorted([u._id for u in users[:-1] + [admin]]))
ticket_ids = [t._id for t in tickets]
@@ -2280,6 +2280,8 @@ class TestBulkMove(TrackerTestController):
'__ticket_ids': [t._id for t in tickets],
'__search': '',
})
+ M.MonQTask.run_ready()
+ ThreadLocalORMSession.flush_all()
ac_id = tracker.config._id
original_ac_id = original_tracker.config._id
moved_tickets = tm.Ticket.query.find({'app_config_id': ac_id}).all()
@@ -2319,7 +2321,7 @@ class TestBulkMove(TrackerTestController):
emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
assert_equal(len(emails), 3)
for email in emails:
- assert_equal(email.kwargs.subject, '[test:bugs] Mass ticket moving by Test Admin')
+ assert_equal(email.kwargs.subject, 'test:bugs Mass ticket moving by Test Admin')
first_user_email = M.MonQTask.query.find({
'task_name': 'allura.tasks.mail_tasks.sendmail',
'kwargs.destinations': str(first_user._id)
@@ -2374,7 +2376,7 @@ class TestBulkMove(TrackerTestController):
emails = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).all()
assert_equal(len(emails), 2)
for email in emails:
- assert_equal(email.kwargs.subject, '[test:bugs] Mass ticket moving by Test Admin')
+ assert_equal(email.kwargs.subject, 'test:bugs Mass ticket moving by Test Admin')
admin_email = M.MonQTask.query.find({
'task_name': 'allura.tasks.mail_tasks.sendmail',
'kwargs.destinations': str(M.User.by_username('test-admin')._id)
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/224499a9/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 845d380..62469a9 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -62,7 +62,7 @@ from allura.controllers import AppDiscussionController, AppDiscussionRestControl
from allura.controllers import attachments as ac
from allura.controllers import BaseController
from allura.controllers.feed import FeedArgs, FeedController
-from allura.tasks import mail_tasks
+from allura.tasks import mail_tasks, tracker_task
# Local imports
from forgetracker import model as TM
@@ -824,55 +824,7 @@ class RootController(BaseController, FeedController):
_id={'$in': [ObjectId(id) for id in ticket_ids]},
app_config_id=c.app.config._id)).all()
- filtered = filtered_by_subscription({t._id: t for t in tickets})
- original_ticket_nums = {t._id: t.ticket_num for t in tickets}
- users = M.User.query.find({'_id': {'$in': filtered.keys()}}).all()
- moved_tickets = {}
- for ticket in tickets:
- moved = ticket.move(tracker, notify=False)
- moved_tickets[moved._id] = moved
-
- mail = dict(
- fromaddr = str(c.user._id),
- reply_to = str(c.user._id),
- subject = '[%s:%s] Mass ticket moving by %s' % (c.project.shortname,
- c.app.config.options.mount_point,
- c.user.display_name))
- tmpl = jinja2.Environment(
- loader=jinja2.PackageLoader('forgetracker', 'data'),
- auto_reload=asbool(config.get('auto_reload_templates', True))
- ).get_template('mass_move_report.html')
- tmpl_context = {
- 'original_tracker': '%s:%s' % (c.project.shortname,
- c.app.config.options.mount_point),
- 'destination_tracker': '%s:%s' % (tracker.project.shortname,
- tracker.options.mount_point),
- 'tickets': [],
- }
- for user in users:
- tmpl_context['tickets'] = ({
- 'original_num': original_ticket_nums[_id],
- 'destination_num': moved_tickets[_id].ticket_num,
- 'summary': moved_tickets[_id].summary
- } for _id in filtered.get(user._id, []))
- mail.update(dict(
- message_id = h.gen_message_id(),
- text = tmpl.render(tmpl_context),
- destinations = [str(user._id)]))
- mail_tasks.sendmail.post(**mail)
-
- if c.app.config.options.get('TicketMonitoringType') == 'AllTicketChanges':
- monitoring_email = c.app.config.options.get('TicketMonitoringEmail')
- tmpl_context['tickets'] = ({
- 'original_num': original_ticket_nums[_id],
- 'destination_num': moved_tickets[_id].ticket_num,
- 'summary': moved_tickets[_id].summary
- } for _id in moved_tickets.keys())
- mail.update(dict(
- message_id = h.gen_message_id(),
- text = tmpl.render(tmpl_context),
- destinations = [monitoring_email]))
- mail_tasks.sendmail.post(**mail)
+ tracker_task.move_tickets.post(ticket_ids, destination_tracker_id)
c.app.globals.invalidate_bin_counts()
ThreadLocalORMSession.flush_all()
@@ -948,7 +900,7 @@ class RootController(BaseController, FeedController):
ticket.discussion_thread.post(message, notify=False)
ticket.commit()
- filtered_changes = filtered_by_subscription(changed_tickets)
+ filtered_changes = c.app.globals.filtered_by_subscription(changed_tickets)
users = M.User.query.find({'_id': {'$in': filtered_changes.keys()}}).all()
def changes_iter(user):
for t_id in filtered_changes.get(user._id, []):
@@ -1312,31 +1264,6 @@ class changelog(object):
t.append((key, (orig_value, curr_value)))
return t
-
-def filtered_by_subscription(tickets, project_id=None, app_config_id=None):
- p_id = project_id if project_id else c.project._id
- ac_id = app_config_id if app_config_id else c.app.config._id
- ticket_ids = tickets.keys()
- users = M.Mailbox.query.find(dict(project_id=p_id, app_config_id=ac_id))
- users = [u.user_id for u in users]
- filtered = {}
- for uid in users:
- params = dict(
- user_id=uid,
- project_id=p_id,
- app_config_id=ac_id)
- if M.Mailbox.subscribed(**params):
- filtered[uid] = set(ticket_ids) # subscribed to entire tool, will see all changes
- continue
- for t_id, ticket in tickets.iteritems():
- params.update({'artifact': ticket})
- if M.Mailbox.subscribed(**params):
- if filtered.get(uid) is None:
- filtered[uid] = set()
- filtered[uid].add(t_id)
- return filtered
-
-
class TicketController(BaseController, FeedController):
def __init__(self, ticket_num=None):