You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by he...@apache.org on 2015/05/29 22:40:39 UTC
[17/45] allura git commit: [#7878] Used 2to3 to see what issues would
come up
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/model/stats.py
----------------------------------------------------------------------
diff --git a/model/stats.py b/model/stats.py
new file mode 100644
index 0000000..1668f45
--- /dev/null
+++ b/model/stats.py
@@ -0,0 +1,619 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
+# 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 datetime import datetime
+from tg import config
+from paste.deploy.converters import asbool
+
+from ming import schema as S
+from ming.orm import Mapper
+from ming.orm import FieldProperty
+from ming.orm.declarative import MappedClass
+from datetime import timedelta
+import difflib
+
+from allura.model.session import main_orm_session
+from functools import reduce
+
+
+class Stats(MappedClass):
+
+ class __mongometa__:
+ name = 'basestats'
+ session = main_orm_session
+ unique_indexes = ['_id']
+
+ _id = FieldProperty(S.ObjectId)
+
+ visible = FieldProperty(bool, if_missing=True)
+ registration_date = FieldProperty(datetime)
+ general = FieldProperty([dict(
+ category=S.ObjectId,
+ messages=[dict(
+ messagetype=str,
+ created=int,
+ modified=int)],
+ tickets=dict(
+ solved=int,
+ assigned=int,
+ revoked=int,
+ totsolvingtime=int),
+ commits=[dict(
+ lines=int,
+ number=int,
+ language=S.ObjectId)])])
+
+ lastmonth = FieldProperty(dict(
+ messages=[dict(
+ datetime=datetime,
+ created=bool,
+ categories=[S.ObjectId],
+ messagetype=str)],
+ assignedtickets=[dict(
+ datetime=datetime,
+ categories=[S.ObjectId])],
+ revokedtickets=[dict(
+ datetime=datetime,
+ categories=[S.ObjectId])],
+ solvedtickets=[dict(
+ datetime=datetime,
+ categories=[S.ObjectId],
+ solvingtime=int)],
+ commits=[dict(
+ datetime=datetime,
+ categories=[S.ObjectId],
+ programming_languages=[S.ObjectId],
+ lines=int)]))
+
+ @property
+ def start_date(self):
+ """Date from which stats should be calculated.
+
+ The user may have registered before stats were collected,
+ making calculations based on registration date unfair."""
+ min_date = config.get('userstats.start_date', '0001-1-1')
+ return max(datetime.strptime(min_date, '%Y-%m-%d'), self.registration_date)
+
+ def getCodeContribution(self):
+ days = (datetime.today() - self.start_date).days
+ if not days:
+ days = 1
+ for val in self['general']:
+ if val['category'] is None:
+ for commits in val['commits']:
+ if commits['language'] is None:
+ if days > 30:
+ return round(float(commits.lines) / days * 30, 2)
+ else:
+ return float(commits.lines)
+ return 0
+
+ def getDiscussionContribution(self):
+ days = (datetime.today() - self.start_date).days
+ if not days:
+ days = 1
+ for val in self['general']:
+ if val['category'] is None:
+ for artifact in val['messages']:
+ if artifact['messagetype'] is None:
+ tot = artifact.created + artifact.modified
+ if days > 30:
+ return round(float(tot) / days * 30, 2)
+ else:
+ return float(tot)
+ return 0
+
+ def getTicketsContribution(self):
+ for val in self['general']:
+ if val['category'] is None:
+ tickets = val['tickets']
+ if tickets.assigned == 0:
+ return 0
+ return round(float(tickets.solved) / tickets.assigned, 2)
+ return 0
+
+ def getCommits(self, category=None):
+ i = getElementIndex(self.general, category=category)
+ if i is None:
+ return dict(number=0, lines=0)
+ cat = self.general[i]
+ j = getElementIndex(cat.commits, language=None)
+ if j is None:
+ return dict(number=0, lines=0)
+ return dict(
+ number=cat.commits[j]['number'],
+ lines=cat.commits[j]['lines'])
+
+ def getArtifacts(self, category=None, art_type=None):
+ i = getElementIndex(self.general, category=category)
+ if i is None:
+ return dict(created=0, modified=0)
+ cat = self.general[i]
+ j = getElementIndex(cat.messages, messagetype=art_type)
+ if j is None:
+ return dict(created=0, modified=0)
+ return dict(created=cat.messages[j].created, modified=cat.messages[j].modified)
+
+ def getTickets(self, category=None):
+ i = getElementIndex(self.general, category=category)
+ if i is None:
+ return dict(
+ assigned=0,
+ solved=0,
+ revoked=0,
+ averagesolvingtime=None)
+ if self.general[i].tickets.solved > 0:
+ tot = self.general[i].tickets.totsolvingtime
+ number = self.general[i].tickets.solved
+ average = tot / number
+ else:
+ average = None
+ return dict(
+ assigned=self.general[i].tickets.assigned,
+ solved=self.general[i].tickets.solved,
+ revoked=self.general[i].tickets.revoked,
+ averagesolvingtime=_convertTimeDiff(average))
+
+ def getCommitsByCategory(self):
+ from allura.model.project import TroveCategory
+
+ by_cat = {}
+ for entry in self.general:
+ cat = entry.category
+ i = getElementIndex(entry.commits, language=None)
+ if i is None:
+ n, lines = 0, 0
+ else:
+ n, lines = entry.commits[i].number, entry.commits[i].lines
+ if cat != None:
+ cat = TroveCategory.query.get(_id=cat)
+ by_cat[cat] = dict(number=n, lines=lines)
+ return by_cat
+
+ # For the moment, commit stats by language are not used, since each project
+ # can be linked to more than one programming language and we don't know how
+ # to which programming language should be credited a line of code modified
+ # within a project including two or more languages.
+ def getCommitsByLanguage(self):
+ i = getElementIndex(self.general, category=None)
+ if i is None:
+ return dict(number=0, lines=0)
+ return dict([(el.language, dict(lines=el.lines, number=el.number))
+ for el in self.general[i].commits])
+
+ def getArtifactsByCategory(self, detailed=False):
+ from allura.model.project import TroveCategory
+
+ by_cat = {}
+ for entry in self.general:
+ cat = entry.category
+ if cat != None:
+ cat = TroveCategory.query.get(_id=cat)
+ if detailed:
+ by_cat[cat] = entry.messages
+ else:
+ i = getElementIndex(entry.messages, messagetype=None)
+ if i is not None:
+ by_cat[cat] = entry.messages[i]
+ else:
+ by_cat[cat] = dict(created=0, modified=0)
+ return by_cat
+
+ def getArtifactsByType(self, category=None):
+ i = getElementIndex(self.general, category=category)
+ if i is None:
+ return {}
+ entry = self.general[i].messages
+ by_type = dict([(el.messagetype, dict(created=el.created,
+ modified=el.modified))
+ for el in entry])
+ return by_type
+
+ def getTicketsByCategory(self):
+ from allura.model.project import TroveCategory
+
+ by_cat = {}
+ for entry in self.general:
+ cat = entry.category
+ if cat != None:
+ cat = TroveCategory.query.get(_id=cat)
+ a, s = entry.tickets.assigned, entry.tickets.solved
+ r, time = entry.tickets.solved, entry.tickets.totsolvingtime
+ if s:
+ average = time / s
+ else:
+ average = None
+ by_cat[cat] = dict(
+ assigned=a,
+ solved=s,
+ revoked=r,
+ averagesolvingtime=_convertTimeDiff(average))
+ return by_cat
+
+ def getLastMonthCommits(self, category=None):
+ self.checkOldArtifacts()
+ lineslist = [el.lines for el in self.lastmonth.commits
+ if category in el.categories + [None]]
+ return dict(number=len(lineslist), lines=sum(lineslist))
+
+ def getLastMonthCommitsByCategory(self):
+ from allura.model.project import TroveCategory
+
+ self.checkOldArtifacts()
+ seen = set()
+ catlist = [el.category for el in self.general
+ if el.category not in seen and not seen.add(el.category)]
+
+ by_cat = {}
+ for cat in catlist:
+ lineslist = [el.lines for el in self.lastmonth.commits
+ if cat in el.categories + [None]]
+ n = len(lineslist)
+ lines = sum(lineslist)
+ if cat != None:
+ cat = TroveCategory.query.get(_id=cat)
+ by_cat[cat] = dict(number=n, lines=lines)
+ return by_cat
+
+ def getLastMonthCommitsByLanguage(self):
+ from allura.model.project import TroveCategory
+
+ self.checkOldArtifacts()
+ seen = set()
+ langlist = [el.language for el in self.general
+ if el.language not in seen and not seen.add(el.language)]
+
+ by_lang = {}
+ for lang in langlist:
+ lineslist = [el.lines for el in self.lastmonth.commits
+ if lang in el.programming_languages + [None]]
+ n = len(lineslist)
+ lines = sum(lineslist)
+ if lang != None:
+ lang = TroveCategory.query.get(_id=lang)
+ by_lang[lang] = dict(number=n, lines=lines)
+ return by_lang
+
+ def getLastMonthArtifacts(self, category=None, art_type=None):
+ self.checkOldArtifacts()
+ cre, mod = reduce(
+ addtuple,
+ [(int(el.created), 1 - int(el.created))
+ for el in self.lastmonth.messages
+ if (category is None or category in el.categories) and
+ (el.messagetype == art_type or art_type is None)],
+ (0, 0))
+ return dict(created=cre, modified=mod)
+
+ def getLastMonthArtifactsByType(self, category=None):
+ self.checkOldArtifacts()
+ seen = set()
+ types = [el.messagetype for el in self.lastmonth.messages
+ if el.messagetype not in seen and not seen.add(el.messagetype)]
+
+ by_type = {}
+ for t in types:
+ cre, mod = reduce(
+ addtuple,
+ [(int(el.created), 1 - int(el.created))
+ for el in self.lastmonth.messages
+ if el.messagetype == t and
+ category in [None] + el.categories],
+ (0, 0))
+ by_type[t] = dict(created=cre, modified=mod)
+ return by_type
+
+ def getLastMonthArtifactsByCategory(self):
+ from allura.model.project import TroveCategory
+
+ self.checkOldArtifacts()
+ seen = set()
+ catlist = [el.category for el in self.general
+ if el.category not in seen and not seen.add(el.category)]
+
+ by_cat = {}
+ for cat in catlist:
+ cre, mod = reduce(
+ addtuple,
+ [(int(el.created), 1 - int(el.created))
+ for el in self.lastmonth.messages
+ if cat in el.categories + [None]], (0, 0))
+ if cat != None:
+ cat = TroveCategory.query.get(_id=cat)
+ by_cat[cat] = dict(created=cre, modified=mod)
+ return by_cat
+
+ def getLastMonthTickets(self, category=None):
+ from allura.model.project import TroveCategory
+
+ self.checkOldArtifacts()
+ a = len([el for el in self.lastmonth.assignedtickets
+ if category in el.categories + [None]])
+ r = len([el for el in self.lastmonth.revokedtickets
+ if category in el.categories + [None]])
+ s, time = reduce(
+ addtuple,
+ [(1, el.solvingtime)
+ for el in self.lastmonth.solvedtickets
+ if category in el.categories + [None]],
+ (0, 0))
+ if category != None:
+ category = TroveCategory.query.get(_id=category)
+ if s > 0:
+ time = time / s
+ else:
+ time = None
+ return dict(
+ assigned=a,
+ revoked=r,
+ solved=s,
+ averagesolvingtime=_convertTimeDiff(time))
+
+ def getLastMonthTicketsByCategory(self):
+ from allura.model.project import TroveCategory
+
+ self.checkOldArtifacts()
+ seen = set()
+ catlist = [el.category for el in self.general
+ if el.category not in seen and not seen.add(el.category)]
+ by_cat = {}
+ for cat in catlist:
+ a = len([el for el in self.lastmonth.assignedtickets
+ if cat in el.categories + [None]])
+ r = len([el for el in self.lastmonth.revokedtickets
+ if cat in el.categories + [None]])
+ s, time = reduce(addtuple, [(1, el.solvingtime)
+ for el in self.lastmonth.solvedtickets
+ if cat in el.categories + [None]], (0, 0))
+ if cat != None:
+ cat = TroveCategory.query.get(_id=cat)
+ if s > 0:
+ time = time / s
+ else:
+ time = None
+ by_cat[cat] = dict(
+ assigned=a,
+ revoked=r,
+ solved=s,
+ averagesolvingtime=_convertTimeDiff(time))
+ return by_cat
+
+ def checkOldArtifacts(self):
+ now = datetime.utcnow()
+ for m in self.lastmonth.messages:
+ if now - m.datetime > timedelta(30):
+ self.lastmonth.messages.remove(m)
+ for t in self.lastmonth.assignedtickets:
+ if now - t.datetime > timedelta(30):
+ self.lastmonth.assignedtickets.remove(t)
+ for t in self.lastmonth.revokedtickets:
+ if now - t.datetime > timedelta(30):
+ self.lastmonth.revokedtickets.remove(t)
+ for t in self.lastmonth.solvedtickets:
+ if now - t.datetime > timedelta(30):
+ self.lastmonth.solvedtickets.remove(t)
+ for c in self.lastmonth.commits:
+ if now - c.datetime > timedelta(30):
+ self.lastmonth.commits.remove(c)
+
+ def addNewArtifact(self, art_type, art_datetime, project):
+ self._updateArtifactsStats(art_type, art_datetime, project, "created")
+
+ def addModifiedArtifact(self, art_type, art_datetime, project):
+ self._updateArtifactsStats(art_type, art_datetime, project, "modified")
+
+ def addAssignedTicket(self, ticket_datetime, project):
+ topics = [t for t in project.trove_topic if t]
+ self._updateTicketsStats(topics, 'assigned')
+ self.lastmonth.assignedtickets.append(
+ dict(datetime=ticket_datetime, categories=topics))
+
+ def addRevokedTicket(self, ticket_datetime, project):
+ topics = [t for t in project.trove_topic if t]
+ self._updateTicketsStats(topics, 'revoked')
+ self.lastmonth.revokedtickets.append(
+ dict(datetime=ticket_datetime, categories=topics))
+ self.checkOldArtifacts()
+
+ def addClosedTicket(self, open_datetime, close_datetime, project):
+ topics = [t for t in project.trove_topic if t]
+ s_time = int((close_datetime - open_datetime).total_seconds())
+ self._updateTicketsStats(topics, 'solved', s_time=s_time)
+ self.lastmonth.solvedtickets.append(dict(
+ datetime=close_datetime,
+ categories=topics,
+ solvingtime=s_time))
+ self.checkOldArtifacts()
+
+ def addCommit(self, newcommit, commit_datetime, project):
+ def _computeLines(newblob, oldblob=None):
+ if oldblob:
+ listold = list(oldblob)
+ else:
+ listold = []
+ if newblob:
+ listnew = list(newblob)
+ else:
+ listnew = []
+
+ if oldblob is None:
+ lines = len(listnew)
+ elif newblob and newblob.has_html_view:
+ diff = difflib.unified_diff(
+ listold, listnew,
+ ('old' + oldblob.path()).encode('utf-8'),
+ ('new' + newblob.path()).encode('utf-8'))
+ lines = len(
+ [l for l in diff if len(l) > 0 and l[0] == '+']) - 1
+ else:
+ lines = 0
+ return lines
+
+ def _addCommitData(stats, topics, languages, lines):
+ lt = topics + [None]
+ ll = languages + [None]
+ for t in lt:
+ i = getElementIndex(stats.general, category=t)
+ if i is None:
+ newstats = dict(
+ category=t,
+ commits=[],
+ messages=[],
+ tickets=dict(
+ assigned=0,
+ solved=0,
+ revoked=0,
+ totsolvingtime=0))
+ stats.general.append(newstats)
+ i = getElementIndex(stats.general, category=t)
+ for lang in ll:
+ j = getElementIndex(
+ stats.general[i]['commits'], language=lang)
+ if j is None:
+ stats.general[i]['commits'].append(dict(
+ language=lang, lines=lines, number=1))
+ else:
+ stats.general[i]['commits'][j].lines += lines
+ stats.general[i]['commits'][j].number += 1
+
+ topics = [t for t in project.trove_topic if t]
+ languages = [l for l in project.trove_language if l]
+
+ d = newcommit.diffs
+ if len(newcommit.parent_ids) > 0:
+ oldcommit = newcommit.repo.commit(newcommit.parent_ids[0])
+
+ totlines = 0
+ if asbool(config.get('userstats.count_lines_of_code', True)):
+ for changed in d.changed:
+ newblob = newcommit.tree.get_blob_by_path(changed)
+ oldblob = oldcommit.tree.get_blob_by_path(changed)
+ totlines += _computeLines(newblob, oldblob)
+
+ for copied in d.copied:
+ newblob = newcommit.tree.get_blob_by_path(copied['new'])
+ oldblob = oldcommit.tree.get_blob_by_path(copied['old'])
+ totlines += _computeLines(newblob, oldblob)
+
+ for added in d.added:
+ newblob = newcommit.tree.get_blob_by_path(added)
+ totlines += _computeLines(newblob)
+
+ _addCommitData(self, topics, languages, totlines)
+
+ self.lastmonth.commits.append(dict(
+ datetime=commit_datetime,
+ categories=topics,
+ programming_languages=languages,
+ lines=totlines))
+ self.checkOldArtifacts()
+
+ def _updateArtifactsStats(self, art_type, art_datetime, project, action):
+ if action not in ['created', 'modified']:
+ return
+ topics = [t for t in project.trove_topic if t]
+ lt = [None] + topics
+ for mtype in [None, art_type]:
+ for t in lt:
+ i = getElementIndex(self.general, category=t)
+ if i is None:
+ msg = dict(
+ category=t,
+ commits=[],
+ tickets=dict(
+ solved=0,
+ assigned=0,
+ revoked=0,
+ totsolvingtime=0),
+ messages=[])
+ self.general.append(msg)
+ i = getElementIndex(self.general, category=t)
+ j = getElementIndex(
+ self.general[i]['messages'], messagetype=mtype)
+ if j is None:
+ entry = dict(messagetype=mtype, created=0, modified=0)
+ entry[action] += 1
+ self.general[i]['messages'].append(entry)
+ else:
+ self.general[i]['messages'][j][action] += 1
+
+ self.lastmonth.messages.append(dict(
+ datetime=art_datetime,
+ created=(action == 'created'),
+ categories=topics,
+ messagetype=art_type))
+ self.checkOldArtifacts()
+
+ def _updateTicketsStats(self, topics, action, s_time=None):
+ if action not in ['solved', 'assigned', 'revoked']:
+ return
+ lt = topics + [None]
+ for t in lt:
+ i = getElementIndex(self.general, category=t)
+ if i is None:
+ stats = dict(
+ category=t,
+ commits=[],
+ tickets=dict(
+ solved=0,
+ assigned=0,
+ revoked=0,
+ totsolvingtime=0),
+ messages=[])
+ self.general.append(stats)
+ i = getElementIndex(self.general, category=t)
+ self.general[i]['tickets'][action] += 1
+ if action == 'solved':
+ self.general[i]['tickets']['totsolvingtime'] += s_time
+
+
+def getElementIndex(el_list, **kw):
+ for i in range(len(el_list)):
+ for k in kw:
+ if el_list[i].get(k) != kw[k]:
+ break
+ else:
+ return i
+ return None
+
+
+def addtuple(l1, l2):
+ a, b = l1
+ x, y = l2
+ return (a + x, b + y)
+
+
+def _convertTimeDiff(int_seconds):
+ if int_seconds is None:
+ return None
+ diff = timedelta(seconds=int_seconds)
+ days, seconds = diff.days, diff.seconds
+ hours = seconds / 3600
+ seconds = seconds % 3600
+ minutes = seconds / 60
+ seconds = seconds % 60
+ return dict(
+ days=days,
+ hours=hours,
+ minutes=minutes,
+ seconds=seconds)
+
+Mapper.compile_all()
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/model/timeline.py
----------------------------------------------------------------------
diff --git a/model/timeline.py b/model/timeline.py
new file mode 100644
index 0000000..dca627c
--- /dev/null
+++ b/model/timeline.py
@@ -0,0 +1,150 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
+# 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.
+
+import bson
+import logging
+
+from ming.odm import Mapper
+from pylons import tmpl_context as c
+
+from activitystream import ActivityDirector
+from activitystream.base import NodeBase, ActivityObjectBase
+from activitystream.managers import Aggregator as BaseAggregator
+
+from allura.lib import security
+from allura.tasks.activity_tasks import create_timelines
+
+log = logging.getLogger(__name__)
+
+
+class Director(ActivityDirector):
+
+ """Overrides the default ActivityDirector to kick off background
+ timeline aggregations after an activity is created.
+
+ """
+
+ def create_activity(self, actor, verb, obj, target=None,
+ related_nodes=None, tags=None):
+ if c.project and c.project.notifications_disabled:
+ return
+
+ from allura.model.project import Project
+ super(Director, self).create_activity(actor, verb, obj,
+ target=target,
+ related_nodes=related_nodes,
+ tags=tags)
+ # aggregate actor and follower's timelines
+ if actor.node_id:
+ create_timelines.post(actor.node_id)
+ # aggregate project and follower's timelines
+ for node in [obj, target] + (related_nodes or []):
+ if isinstance(node, Project):
+ create_timelines.post(node.node_id)
+
+
+class Aggregator(BaseAggregator):
+ pass
+
+
+class ActivityNode(NodeBase):
+
+ @property
+ def node_id(self):
+ return "%s:%s" % (self.__class__.__name__, self._id)
+
+
+class ActivityObject(ActivityObjectBase):
+ '''
+ Allura's base activity class.
+ '''
+
+ @property
+ def activity_name(self):
+ """Override this for each Artifact type."""
+ return "%s %s" % (self.__mongometa__.name.capitalize(), self._id)
+
+ @property
+ def activity_url(self):
+ return self.url()
+
+ @property
+ def activity_extras(self):
+ """Return a BSON-serializable dict of extra stuff to store on the
+ activity.
+ """
+ return {"allura_id": self.allura_id}
+
+ @property
+ def allura_id(self):
+ """Return a string which uniquely identifies this object and which can
+ be used to retrieve the object from mongo.
+ """
+ return "%s:%s" % (self.__class__.__name__, self._id)
+
+ def has_activity_access(self, perm, user, activity):
+ """Return True if user has perm access to this object, otherwise
+ return False.
+ """
+ if self.project is None or self.deleted:
+ return False
+ return security.has_access(self, perm, user, self.project)
+
+
+class TransientActor(NodeBase, ActivityObjectBase):
+ """An activity actor which is not a persistent Node in the network.
+
+ """
+ def __init__(self, activity_name):
+ NodeBase.__init__(self)
+ ActivityObjectBase.__init__(self)
+ self.activity_name = activity_name
+
+
+def get_activity_object(activity_object_dict):
+ """Given a BSON-serialized activity object (e.g. activity.obj dict in a
+ timeline), return the corresponding :class:`ActivityObject`.
+
+ """
+ extras_dict = activity_object_dict.activity_extras
+ if not extras_dict:
+ return None
+ allura_id = extras_dict.get('allura_id')
+ if not allura_id:
+ return None
+ classname, _id = allura_id.split(':', 1)
+ cls = Mapper.by_classname(classname).mapped_class
+ try:
+ _id = bson.ObjectId(_id)
+ except bson.errors.InvalidId:
+ pass
+ return cls.query.get(_id=_id)
+
+
+def perm_check(user):
+ """
+ Return a function that returns True if ``user`` has 'read' access to a given activity,
+ otherwise returns False.
+ """
+ def _perm_check(activity):
+ obj = get_activity_object(activity.obj)
+ return obj is None or obj.has_activity_access('read', user, activity)
+ return _perm_check
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/model/types.py
----------------------------------------------------------------------
diff --git a/model/types.py b/model/types.py
new file mode 100644
index 0000000..e630096
--- /dev/null
+++ b/model/types.py
@@ -0,0 +1,118 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
+# 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 ming.base import Object
+from ming import schema as S
+
+EVERYONE, ALL_PERMISSIONS = None, '*'
+
+
+class MarkdownCache(S.Object):
+
+ def __init__(self, **kw):
+ super(MarkdownCache, self).__init__(
+ fields=dict(
+ md5=S.String(),
+ fix7528=S.Bool,
+ html=S.String(),
+ render_time=S.Float()),
+ **kw)
+
+
+class ACE(S.Object):
+ '''
+ Access Control Entry
+
+ :var access: either ``ACE.ALLOW`` or ``ACE.DENY``
+ :var str reason: optional, user-entered text
+ :var role_id: _id for a :class:`~allura.model.auth.ProjectRole`
+ :var str permission: e.g. 'read', 'create', etc
+ '''
+
+ ALLOW, DENY = 'ALLOW', 'DENY'
+
+ def __init__(self, permissions, **kwargs):
+ if permissions is None:
+ permission = S.String()
+ else:
+ permission = S.OneOf('*', *permissions)
+ super(ACE, self).__init__(
+ fields=dict(
+ access=S.OneOf(self.ALLOW, self.DENY),
+ reason=S.String(),
+ role_id=S.ObjectId(),
+ permission=permission),
+ **kwargs)
+
+ @classmethod
+ def allow(cls, role_id, permission, reason=None):
+ return Object(
+ access=cls.ALLOW,
+ reason=reason,
+ role_id=role_id,
+ permission=permission)
+
+ @classmethod
+ def deny(cls, role_id, permission, reason=None):
+ ace = Object(
+ access=cls.DENY,
+ reason=reason,
+ role_id=role_id,
+ permission=permission)
+ return ace
+
+ @classmethod
+ def match(cls, ace, role_id, permission):
+ return (
+ ace.role_id in (role_id, EVERYONE)
+ and ace.permission in (permission, ALL_PERMISSIONS))
+
+
+class ACL(S.Array):
+ '''
+ Access Control List. Is an array of :class:`ACE`
+ '''
+
+ def __init__(self, permissions=None, **kwargs):
+ super(ACL, self).__init__(
+ field_type=ACE(permissions), **kwargs)
+
+ @classmethod
+ def contains(cls, ace, acl):
+ """Test membership of ace in acl ignoring ace.reason field.
+
+ Return actual ACE with reason filled if ace is found in acl, None otherwise
+
+ e.g. `ACL.contains(ace, acl)` will return `{role_id=ObjectId(...), permission='read', access='DENY', reason='Spammer'}`
+ with following vars:
+
+ ace = M.ACE.deny(role_id, 'read') # reason = None
+ acl = [{role_id=ObjectId(...), permission='read', access='DENY', reason='Spammer'}]
+ """
+ def clear_reason(ace):
+ return Object(access=ace.access, role_id=ace.role_id, permission=ace.permission)
+
+ ace_without_reason = clear_reason(ace)
+ for a in acl:
+ if clear_reason(a) == ace_without_reason:
+ return a
+
+DENY_ALL = ACE.deny(EVERYONE, ALL_PERMISSIONS)
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/model/webhook.py
----------------------------------------------------------------------
diff --git a/model/webhook.py b/model/webhook.py
new file mode 100644
index 0000000..213d5c9
--- /dev/null
+++ b/model/webhook.py
@@ -0,0 +1,76 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
+# 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.
+
+import datetime as dt
+import json
+
+from ming.odm import FieldProperty, session
+from paste.deploy.converters import asint
+from tg import config
+
+from allura.model import Artifact
+from allura.lib import helpers as h
+
+
+class Webhook(Artifact):
+ class __mongometa__:
+ name = 'webhook'
+ unique_indexes = [('app_config_id', 'type', 'hook_url')]
+
+ type = FieldProperty(str)
+ hook_url = FieldProperty(str)
+ secret = FieldProperty(str)
+ last_sent = FieldProperty(dt.datetime, if_missing=None)
+
+ def url(self):
+ app = self.app_config.load()
+ app = app(self.app_config.project, self.app_config)
+ return '{}webhooks/{}/{}'.format(app.admin_url, self.type, self._id)
+
+ def enforce_limit(self):
+ '''Returns False if limit is reached, otherwise True'''
+ if self.last_sent is None:
+ return True
+ now = dt.datetime.utcnow()
+ config_type = self.type.replace('-', '_')
+ limit = asint(config.get('webhook.%s.limit' % config_type, 30))
+ if (now - self.last_sent) > dt.timedelta(seconds=limit):
+ return True
+ return False
+
+ def update_limit(self):
+ self.last_sent = dt.datetime.utcnow()
+ session(self).flush(self)
+
+ @classmethod
+ def max_hooks(self, type, tool_name):
+ type = type.replace('-', '_')
+ limits = json.loads(config.get('webhook.%s.max_hooks' % type, '{}'))
+ return limits.get(tool_name.lower(), 3)
+
+ def __json__(self):
+ return {
+ '_id': str(self._id),
+ 'url': h.absurl('/rest' + self.url()),
+ 'type': str(self.type),
+ 'hook_url': str(self.hook_url),
+ 'mod_date': self.mod_date,
+ }
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/rat-excludes.txt
----------------------------------------------------------------------
diff --git a/rat-excludes.txt b/rat-excludes.txt
index 4e3b800..6be4d29 100644
--- a/rat-excludes.txt
+++ b/rat-excludes.txt
@@ -30,7 +30,6 @@ Allura/allura/public/nf/js/jquery.viewport.js
Allura/allura/public/nf/css/blueprint/
Allura/allura/public/nf/js/sylvester.js
Allura/allura/public/nf/js/modernizr.js
-Allura/allura/public/nf/js/react.min.js
Allura/allura/tests/data/genshi_hello_tmpl
Allura/allura/tests/data/test_mime/text_file.txt
AlluraTest/jslint/
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/ApacheAccessHandler.py
----------------------------------------------------------------------
diff --git a/scripts/ApacheAccessHandler.py b/scripts/ApacheAccessHandler.py
index 1af3714..3264c8c 100644
--- a/scripts/ApacheAccessHandler.py
+++ b/scripts/ApacheAccessHandler.py
@@ -43,6 +43,10 @@ Here is a quick example for your apache settings (assuming ProxyPass)
</Location>
"""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
from mod_python import apache
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/__init__.py
----------------------------------------------------------------------
diff --git a/scripts/__init__.py b/scripts/__init__.py
new file mode 100644
index 0000000..91068b1
--- /dev/null
+++ b/scripts/__init__.py
@@ -0,0 +1,22 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
+# 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 .scripttask import ScriptTask
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/add_user_to_group.py
----------------------------------------------------------------------
diff --git a/scripts/add_user_to_group.py b/scripts/add_user_to_group.py
index aa2fe1e..65888fa 100644
--- a/scripts/add_user_to_group.py
+++ b/scripts/add_user_to_group.py
@@ -35,6 +35,10 @@ Example:
$ paster script production.ini ../scripts/add_user_to_group.py -- admin1 Admin --nbhd=/berlios/
"""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
from allura import model as M
from ming.orm import ThreadLocalORMSession
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/allura_import.py
----------------------------------------------------------------------
diff --git a/scripts/allura_import.py b/scripts/allura_import.py
index d4e51fd..a0fefa7 100644
--- a/scripts/allura_import.py
+++ b/scripts/allura_import.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
@@ -40,7 +44,7 @@ def main():
if type(user_map) is not type({}):
raise ValueError
for k, v in user_map.iteritems():
- print k, v
+ print(k, v)
if not isinstance(k, basestring) or not isinstance(v, basestring):
raise ValueError
except ValueError:
@@ -71,10 +75,10 @@ def import_forum(cli, project, tool, user_map, doc_txt, validate=True,
)
if validate:
url += '/validate_import'
- print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))
+ print(cli.call(url, doc=doc_txt, user_map=json.dumps(user_map)))
else:
url += '/perform_import'
- print cli.call(url, doc=doc_txt, user_map=json.dumps(user_map))
+ print(cli.call(url, doc=doc_txt, user_map=json.dumps(user_map)))
def parse_options():
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/changelog.py
----------------------------------------------------------------------
diff --git a/scripts/changelog.py b/scripts/changelog.py
index 8f49e94..c41f83f 100755
--- a/scripts/changelog.py
+++ b/scripts/changelog.py
@@ -17,6 +17,10 @@
# specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import sys
import re
import git
@@ -61,12 +65,12 @@ def get_ticket_summaries(tickets):
def print_changelog(version, summaries):
- print 'Version {version} ({date})\n'.format(**{
+ print('Version {version} ({date})\n'.format(**{
'version': version,
'date': datetime.utcnow().strftime('%B %Y'),
- })
+ }))
for ticket in sorted(summaries.keys()):
- print " * [#{0}] {1}".format(ticket, summaries[ticket].encode('utf-8'))
+ print(" * [#{0}] {1}".format(ticket, summaries[ticket].encode('utf-8')))
if __name__ == '__main__':
main()
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/create-allura-sitemap.py
----------------------------------------------------------------------
diff --git a/scripts/create-allura-sitemap.py b/scripts/create-allura-sitemap.py
index f39b2a6..1124a16 100644
--- a/scripts/create-allura-sitemap.py
+++ b/scripts/create-allura-sitemap.py
@@ -27,6 +27,10 @@ things that would make it faster, if we need/want to.
2. Use multiprocessing to distribute the offsets to n subprocesses.
"""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import os
import sys
@@ -84,7 +88,7 @@ def main(options):
sys.exit('Error: %s directory already exists.' % output_path)
try:
os.mkdir(output_path)
- except OSError, e:
+ except OSError as e:
sys.exit("Error: Couldn't create %s:\n%s" % (output_path, e))
now = datetime.utcnow().date()
@@ -115,9 +119,9 @@ def main(options):
locs.append({'url': url,
'date': p.last_updated.strftime("%Y-%m-%d")})
- except Exception, e:
- print "Error creating sitemap for project '%s': %s" %\
- (p.shortname, e)
+ except Exception as e:
+ print("Error creating sitemap for project '%s': %s" %\
+ (p.shortname, e))
creds.clear()
if len(locs) >= options.urls_per_file:
write_sitemap(locs[:options.urls_per_file], file_count)
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/create-moved-tickets.py
----------------------------------------------------------------------
diff --git a/scripts/create-moved-tickets.py b/scripts/create-moved-tickets.py
index 04ce906..2d6bd04 100644
--- a/scripts/create-moved-tickets.py
+++ b/scripts/create-moved-tickets.py
@@ -22,6 +22,10 @@ This is for making redirects for tickets that we move from SourceForge
to Apache, but could be generalized pretty easily to work for making
any type of redirect (change SF/Apache specifics to commandline arguments)
'''
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import argparse
import pymongo
@@ -52,8 +56,8 @@ nbhd = main_db.neighborhood.find_one({'url_prefix': '/%s/' % opts.n})
project = main_db.project.find_one({'neighborhood_id': nbhd['_id'], 'shortname': opts.p})
tool = project_data.config.find_one({'project_id': project['_id'], 'options.mount_point': opts.t})
-print "Tool id: %s" % tool['_id']
-print 'Setting app_config_id to: %s for tickets: %s' % ('moved-to-apache', ticket_nums)
+print("Tool id: %s" % tool['_id'])
+print('Setting app_config_id to: %s for tickets: %s' % ('moved-to-apache', ticket_nums))
if not opts.dry_run:
project_data.ticket.update({
@@ -61,7 +65,7 @@ if not opts.dry_run:
'ticket_num': {'$in': ticket_nums}
}, {'$set': {'app_config_id': 'moved-to-apache'}}, multi=True)
-print 'Creating MovingTickets for tickets: %s' % ticket_nums
+print('Creating MovingTickets for tickets: %s' % ticket_nums)
if not opts.dry_run:
for num in ticket_nums:
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/create_deleted_comments.py
----------------------------------------------------------------------
diff --git a/scripts/create_deleted_comments.py b/scripts/create_deleted_comments.py
new file mode 100644
index 0000000..033fbd3
--- /dev/null
+++ b/scripts/create_deleted_comments.py
@@ -0,0 +1,114 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
+# 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.
+
+import sys
+import argparse
+import logging
+
+from ming.odm import session
+from pylons import tmpl_context as c
+
+from allura.scripts import ScriptTask
+from allura import model as M
+from allura.lib.utils import chunked_find
+from forgediscussion.model import ForumPost
+
+
+log = logging.getLogger(__name__)
+
+
+class CreateDeletedComments(ScriptTask):
+
+ @classmethod
+ def execute(cls, options):
+ models = [M.Post, ForumPost]
+ app_config_id = cls.get_tool_id(options.tool)
+ # Find all posts that have parent_id, but does not have actual parent
+ # and create fake parent for them
+ for model in models:
+ q = {'parent_id': {'$ne': None},
+ 'app_config_id': app_config_id}
+ for chunk in chunked_find(model, q):
+ for post in chunk:
+ if not post.parent:
+ log.info('Creating deleted parent for %s %s',
+ model.__mongometa__.name, post._id)
+ c.project = post.app_config.project
+ slug = post.slug.rsplit('/', 1)[0]
+ full_slug = post.full_slug.rsplit('/', 1)[0]
+ author = c.project.admins()[0]
+ deleted_post = model(
+ _id=post.parent_id,
+ deleted=True,
+ text="Automatically created in place of deleted post",
+ app_id=post.app_id,
+ app_config_id=post.app_config_id,
+ discussion_id=post.discussion_id,
+ thread_id=post.thread_id,
+ author_id=author._id,
+ slug=slug,
+ full_slug=full_slug,
+ )
+ if options.dry_run:
+ session(deleted_post).expunge(deleted_post)
+ else:
+ session(deleted_post).flush(deleted_post)
+
+ @classmethod
+ def get_tool_id(cls, tool):
+ _n, _p, _mount = tool.split('/')
+ n = M.Neighborhood.query.get(url_prefix='/{}/'.format(_n))
+ if not n:
+ log.error('Can not find neighborhood %s', _n)
+ sys.exit(1)
+ p = M.Project.query.get(neighborhood_id=n._id, shortname=_p)
+ if not p:
+ log.error('Can not find project %s', _p)
+ sys.exit(1)
+ t = p.app_instance(_mount)
+ if not t:
+ log.error('Can not find tool with mount point %s', _mount)
+ sys.exit(1)
+ return t.config._id
+
+ @classmethod
+ def parser(cls):
+ parser = argparse.ArgumentParser(
+ description='Create comments marked as deleted in place of '
+ 'actually deleted parent comments (ticket:#1731)'
+ )
+ parser.add_argument(
+ '--dry-run',
+ action='store_true',
+ dest='dry_run',
+ default=False,
+ help='Show comments that will be created, but do not actually '
+ 'create anything',
+ )
+ parser.add_argument(
+ '-t', '--tool',
+ required=True,
+ help='Create comments only in specified tool, e.g. p/test/wiki')
+ return parser
+
+
+if __name__ == '__main__':
+ CreateDeletedComments.main()
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/fix-wiki-page-names.py
----------------------------------------------------------------------
diff --git a/scripts/fix-wiki-page-names.py b/scripts/fix-wiki-page-names.py
index b53e708..4731f7d 100644
--- a/scripts/fix-wiki-page-names.py
+++ b/scripts/fix-wiki-page-names.py
@@ -16,6 +16,10 @@
# under the License.
"""Rename page/title to page-title"""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import sys
import logging
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/import_trove_categories.py
----------------------------------------------------------------------
diff --git a/scripts/import_trove_categories.py b/scripts/import_trove_categories.py
index 123a56c..e884a73 100644
--- a/scripts/import_trove_categories.py
+++ b/scripts/import_trove_categories.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/000-fix-tracker-fields.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/000-fix-tracker-fields.py b/scripts/migrations/000-fix-tracker-fields.py
index 5d2b6b1..1159442 100644
--- a/scripts/migrations/000-fix-tracker-fields.py
+++ b/scripts/migrations/000-fix-tracker-fields.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/001-restore-labels.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/001-restore-labels.py b/scripts/migrations/001-restore-labels.py
index ef68c09..59b787f 100644
--- a/scripts/migrations/001-restore-labels.py
+++ b/scripts/migrations/001-restore-labels.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/002-fix-tracker-thread-subjects.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/002-fix-tracker-thread-subjects.py b/scripts/migrations/002-fix-tracker-thread-subjects.py
index 81861a0..f65502b 100644
--- a/scripts/migrations/002-fix-tracker-thread-subjects.py
+++ b/scripts/migrations/002-fix-tracker-thread-subjects.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/003-migrate_project_roles.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/003-migrate_project_roles.py b/scripts/migrations/003-migrate_project_roles.py
index 32bcc57..9edce70 100644
--- a/scripts/migrations/003-migrate_project_roles.py
+++ b/scripts/migrations/003-migrate_project_roles.py
@@ -17,6 +17,10 @@
'''Merge all the OldProjectRole collections in into a ProjectRole collection.
'''
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import logging
from ming.orm import session, state
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/004-make-attachments-polymorphic.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/004-make-attachments-polymorphic.py b/scripts/migrations/004-make-attachments-polymorphic.py
index e6133ec..7d2ad3f 100644
--- a/scripts/migrations/004-make-attachments-polymorphic.py
+++ b/scripts/migrations/004-make-attachments-polymorphic.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/005-remove_duplicate_ticket_notifications.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/005-remove_duplicate_ticket_notifications.py b/scripts/migrations/005-remove_duplicate_ticket_notifications.py
index 716c604..6d49f96 100644
--- a/scripts/migrations/005-remove_duplicate_ticket_notifications.py
+++ b/scripts/migrations/005-remove_duplicate_ticket_notifications.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
@@ -34,16 +38,16 @@ log = logging.getLogger(__name__)
def trim_subs(subs, test):
prime = False
- print "Found %d '%s' subs with for user '%s'" % (len(subs), subs[0].artifact_title, str(subs[0].user_id))
+ print("Found %d '%s' subs with for user '%s'" % (len(subs), subs[0].artifact_title, str(subs[0].user_id)))
for sub in subs:
if sub.artifact_url and not prime:
prime = True
- print " Keeping good subscription with a URL of '%s'" % sub.artifact_url
+ print(" Keeping good subscription with a URL of '%s'" % sub.artifact_url)
else:
if not sub.artifact_url:
- print " Found subscription with no artifact URL, deleting."
+ print(" Found subscription with no artifact URL, deleting.")
else:
- print " Subscription has URL, but is a duplicate, deleting."
+ print(" Subscription has URL, but is a duplicate, deleting.")
if not test:
sub.delete()
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/006-migrate-artifact-refs.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/006-migrate-artifact-refs.py b/scripts/migrations/006-migrate-artifact-refs.py
index aeae677..e2f8f82 100644
--- a/scripts/migrations/006-migrate-artifact-refs.py
+++ b/scripts/migrations/006-migrate-artifact-refs.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/007-update-acls.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/007-update-acls.py b/scripts/migrations/007-update-acls.py
index 0f97ee1..04eabaf 100644
--- a/scripts/migrations/007-update-acls.py
+++ b/scripts/migrations/007-update-acls.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
@@ -77,8 +81,8 @@ def main():
log.info('====================================')
log.info('Update neighborhood ACLs')
for n in q_neighborhoods:
- p = c_project.find(dict(
- neighborhood_id=n['_id'], shortname='--init--')).next()
+ p = next(c_project.find(dict(
+ neighborhood_id=n['_id'], shortname='--init--')))
update_neighborhood_acl(n, p)
if not options.test:
c_neighborhood.save(n)
@@ -149,7 +153,7 @@ def update_neighborhood_acl(neighborhood_doc, init_doc):
new_acl = list(init_doc['acl'])
assert acl['read'] == [None] # nbhd should be public
for uid in acl['admin'] + acl['moderate']:
- u = c_user.find(dict(_id=uid)).next()
+ u = next(c_user.find(dict(_id=uid)))
if options.test:
log.info('... grant nbhd admin to: %s', u['username'])
continue
@@ -227,7 +231,7 @@ def _format_role(rid):
if role['name']:
return role['name']
if role['user_id']:
- u = c_user.find(_id=role['user_id']).next()
+ u = next(c_user.find(_id=role['user_id']))
return u['username']
break
return '--invalid--'
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/008-remove-forumpost-subject.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/008-remove-forumpost-subject.py b/scripts/migrations/008-remove-forumpost-subject.py
index af344d5..874fa75 100644
--- a/scripts/migrations/008-remove-forumpost-subject.py
+++ b/scripts/migrations/008-remove-forumpost-subject.py
@@ -18,6 +18,10 @@
"""
Remove the subject FieldProperty from all ForumPost objects. [#2071]
"""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import logging
import sys
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/009-set_landing_page.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/009-set_landing_page.py b/scripts/migrations/009-set_landing_page.py
index 65ca7a1..9f490b4 100644
--- a/scripts/migrations/009-set_landing_page.py
+++ b/scripts/migrations/009-set_landing_page.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/010-fix-home-permissions.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/010-fix-home-permissions.py b/scripts/migrations/010-fix-home-permissions.py
index 4506a17..26be5f3 100644
--- a/scripts/migrations/010-fix-home-permissions.py
+++ b/scripts/migrations/010-fix-home-permissions.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/011-fix-subroles.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/011-fix-subroles.py b/scripts/migrations/011-fix-subroles.py
index cb63c6b..19b6ea3 100644
--- a/scripts/migrations/011-fix-subroles.py
+++ b/scripts/migrations/011-fix-subroles.py
@@ -26,6 +26,10 @@ For project.users:
* user.project_role().roles, if it contains Developer, should not contain
Member
"""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import sys
import logging
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/012-uninstall-home.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/012-uninstall-home.py b/scripts/migrations/012-uninstall-home.py
index c59fdb2..8447295 100644
--- a/scripts/migrations/012-uninstall-home.py
+++ b/scripts/migrations/012-uninstall-home.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/013-update-ordinals.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/013-update-ordinals.py b/scripts/migrations/013-update-ordinals.py
index f26f112..8724347 100644
--- a/scripts/migrations/013-update-ordinals.py
+++ b/scripts/migrations/013-update-ordinals.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py b/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py
index 8c4abd9..5b75d35 100644
--- a/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py
+++ b/scripts/migrations/015-add-neighborhood_id-to-blog-posts.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/018-add-svn-checkout-url.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/018-add-svn-checkout-url.py b/scripts/migrations/018-add-svn-checkout-url.py
index 2a5469c..078fd47 100644
--- a/scripts/migrations/018-add-svn-checkout-url.py
+++ b/scripts/migrations/018-add-svn-checkout-url.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/020-remove-wiki-title-slashes.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/020-remove-wiki-title-slashes.py b/scripts/migrations/020-remove-wiki-title-slashes.py
index 34db4ce..43c9e53 100644
--- a/scripts/migrations/020-remove-wiki-title-slashes.py
+++ b/scripts/migrations/020-remove-wiki-title-slashes.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
@@ -29,10 +33,10 @@ log = logging.getLogger(__name__)
def main():
c.project = None
pages = WM.Page.query.find({'title': {'$regex': '\/'}}).all()
- print 'Found %s wiki titles containing "/"...' % len(pages)
+ print('Found %s wiki titles containing "/"...' % len(pages))
for page in pages:
page.title = page.title.replace('/', '-')
- print 'Updated: %s' % page.title
+ print('Updated: %s' % page.title)
ThreadLocalORMSession.flush_all()
if __name__ == '__main__':
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/022-change-anon-display-name.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/022-change-anon-display-name.py b/scripts/migrations/022-change-anon-display-name.py
index dbe9911..95ae267 100644
--- a/scripts/migrations/022-change-anon-display-name.py
+++ b/scripts/migrations/022-change-anon-display-name.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/024-migrate-custom-profile-text.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/024-migrate-custom-profile-text.py b/scripts/migrations/024-migrate-custom-profile-text.py
index 18a82da..19db2d5 100644
--- a/scripts/migrations/024-migrate-custom-profile-text.py
+++ b/scripts/migrations/024-migrate-custom-profile-text.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/025-add-is-nbhd-project.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/025-add-is-nbhd-project.py b/scripts/migrations/025-add-is-nbhd-project.py
index ca3fc77..9e92878 100644
--- a/scripts/migrations/025-add-is-nbhd-project.py
+++ b/scripts/migrations/025-add-is-nbhd-project.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/026-install-activity-tool.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/026-install-activity-tool.py b/scripts/migrations/026-install-activity-tool.py
index c7eb39f..f25b807 100644
--- a/scripts/migrations/026-install-activity-tool.py
+++ b/scripts/migrations/026-install-activity-tool.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/027-change-ticket-write-permissions.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/027-change-ticket-write-permissions.py b/scripts/migrations/027-change-ticket-write-permissions.py
index 3c6877a..9c5e42c 100644
--- a/scripts/migrations/027-change-ticket-write-permissions.py
+++ b/scripts/migrations/027-change-ticket-write-permissions.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/028-remove-svn-trees.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/028-remove-svn-trees.py b/scripts/migrations/028-remove-svn-trees.py
index 79e82aa..019325b 100644
--- a/scripts/migrations/028-remove-svn-trees.py
+++ b/scripts/migrations/028-remove-svn-trees.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
@@ -33,16 +37,16 @@ def kill_tree(repo, commit_id, path, tree):
tid = repo._tree_oid(commit_id, path + '/' + tree_rec.name)
child_tree = M.repository.Tree.query.get(_id=tid)
if child_tree:
- print ' Found {0}'.format((path + '/' + tree_rec.name).encode('utf8'))
+ print(' Found {0}'.format((path + '/' + tree_rec.name).encode('utf8')))
kill_tree(repo, commit_id, path + '/' + tree_rec.name, child_tree)
else:
- print ' Missing {0}'.format((path + '/' + tree_rec.name).encode('utf8'))
+ print(' Missing {0}'.format((path + '/' + tree_rec.name).encode('utf8')))
def main():
for chunk in utils.chunked_find(SM.Repository):
for r in chunk:
- print 'Processing {0}'.format(r)
+ print('Processing {0}'.format(r))
all_commit_ids = r._impl.all_commit_ids()
if all_commit_ids:
for commit in M.repository.Commit.query.find({'_id': {'$in': all_commit_ids}}):
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/029-set-mailbox-queue_empty.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/029-set-mailbox-queue_empty.py b/scripts/migrations/029-set-mailbox-queue_empty.py
index c2075b7..b18793f 100644
--- a/scripts/migrations/029-set-mailbox-queue_empty.py
+++ b/scripts/migrations/029-set-mailbox-queue_empty.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/migrations/031-set-user-pending-to-false.py
----------------------------------------------------------------------
diff --git a/scripts/migrations/031-set-user-pending-to-false.py b/scripts/migrations/031-set-user-pending-to-false.py
index 02d35d9..7f58ca7 100644
--- a/scripts/migrations/031-set-user-pending-to-false.py
+++ b/scripts/migrations/031-set-user-pending-to-false.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
@@ -28,7 +32,7 @@ log = logging.getLogger(__name__)
def main():
for chunk in utils.chunked_find(M.User):
for user in chunk:
- print 'Processing {0}'.format(user.username)
+ print('Processing {0}'.format(user.username))
user.pending = False
# Ming doesn't mark document for update, since pending is False
# by default, even if field is missing from mongo
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/new_ticket.py
----------------------------------------------------------------------
diff --git a/scripts/new_ticket.py b/scripts/new_ticket.py
index 9b23328..5c6970f 100755
--- a/scripts/new_ticket.py
+++ b/scripts/new_ticket.py
@@ -16,6 +16,10 @@
# specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import sys
import argparse
import requests
@@ -36,10 +40,10 @@ def get_opts():
opts = get_opts()
access_token = raw_input('Access (bearer) token: ')
summary = raw_input('Summary: ')
-print 'Description (C-d to end):'
-print '-----------------------------------------------'
+print('Description (C-d to end):')
+print('-----------------------------------------------')
description = sys.stdin.read()
-print '-----------------------------------------------'
+print('-----------------------------------------------')
r = requests.post(opts.url, params={
'access_token': access_token,
@@ -47,7 +51,7 @@ r = requests.post(opts.url, params={
'ticket_form.description': description,
})
if r.status_code == 200:
- print 'Ticket created at: %s' % r.url
+ print('Ticket created at: %s' % r.url)
pprint(r.json())
else:
- print 'Error [%s]:\n%s' % (r.status_code, r.text)
+ print('Error [%s]:\n%s' % (r.status_code, r.text))
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/open_relay.py
----------------------------------------------------------------------
diff --git a/scripts/open_relay.py b/scripts/open_relay.py
index ba21862..bbf1833 100644
--- a/scripts/open_relay.py
+++ b/scripts/open_relay.py
@@ -17,6 +17,10 @@
# specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import logging
import os
import smtpd
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/perf/benchmark-scm.py
----------------------------------------------------------------------
diff --git a/scripts/perf/benchmark-scm.py b/scripts/perf/benchmark-scm.py
index be9b93a..de39e2c 100755
--- a/scripts/perf/benchmark-scm.py
+++ b/scripts/perf/benchmark-scm.py
@@ -18,6 +18,10 @@
# under the License.
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import os
import sys
import argparse
@@ -71,9 +75,9 @@ def main(opts):
impl(repo, cid, path, names, opts.repo_path)
end = datetime.now()
total += (end - start).total_seconds()
- print
- print 'Total time: %s' % total
- print 'Average time per run: %s' % (total / opts.count)
+ print()
+ print('Total time: %s' % total)
+ print('Average time per run: %s' % (total / opts.count))
def impl_git_tree(repo, cid, path, names, *args):
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/perf/call_count.py
----------------------------------------------------------------------
diff --git a/scripts/perf/call_count.py b/scripts/perf/call_count.py
index 671e6f2..f67be7a 100755
--- a/scripts/perf/call_count.py
+++ b/scripts/perf/call_count.py
@@ -17,6 +17,10 @@
# specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import argparse
import json
import logging
@@ -68,7 +72,7 @@ def main(args):
counts = count_page(test, url, verbose=args.verbose,
debug_html=args.debug_html)
- print json.dumps(counts)
+ print(json.dumps(counts))
write_csv(counts, args.id, args.data_file)
test.tearDown()
@@ -116,17 +120,17 @@ def count_page(test, url, verbose=False, debug_html=False):
with LogCapture('stats') as stats, LogCapture('timermiddleware') as calls:
resp = test.app.get(url, extra_environ=dict(username='*anonymous'))
- print url, resp.status
+ print(url, resp.status)
if debug_html:
debug_filename = 'call-{}.html'.format(''.join([random.choice(string.ascii_letters + string.digits)
for n in xrange(10)]))
with open(debug_filename, 'w') as out:
out.write(resp.body)
- print debug_filename
+ print(debug_filename)
if verbose:
for r in calls.records:
- print r.getMessage()
+ print(r.getMessage())
assert len(stats.records) == 1
timings = json.loads(stats.records[0].getMessage())
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/perf/generate-projects.py
----------------------------------------------------------------------
diff --git a/scripts/perf/generate-projects.py b/scripts/perf/generate-projects.py
index 0374969..16fa5ea 100644
--- a/scripts/perf/generate-projects.py
+++ b/scripts/perf/generate-projects.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
@@ -28,10 +32,10 @@ def main(start, cnt):
name = 'gen-proj-{}'.format(i)
project = n.register_project(name, admin)
if (i-start) > 0 and (i-start) % 100 == 0:
- print 'Created {} projects'.format(i-start)
- print 'Flushing...'
+ print('Created {} projects'.format(i-start))
+ print('Flushing...')
ThreadLocalORMSession.flush_all()
- print 'Done'
+ print('Done')
if __name__ == '__main__':
import sys
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/perf/md_perf.py
----------------------------------------------------------------------
diff --git a/scripts/perf/md_perf.py b/scripts/perf/md_perf.py
index e8d0f70..d92af2b 100644
--- a/scripts/perf/md_perf.py
+++ b/scripts/perf/md_perf.py
@@ -44,6 +44,10 @@ user 0m12.749s
sys 0m1.112s
"""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import argparse
import cProfile
@@ -85,24 +89,24 @@ def main(opts):
def render(artifact, md, opts):
start = begin = time.time()
- print "%4s %20s %10s %s" % ('', 'Conversion Time (s)', 'Text Size', 'Post._id')
+ print("%4s %20s %10s %s" % ('', 'Conversion Time (s)', 'Text Size', 'Post._id'))
for i, p in enumerate(artifact.discussion_thread.posts):
text = DUMMYTEXT or p.text
if opts.n and i + 1 not in opts.n:
- print 'Skipping post %s' % str(i + 1)
+ print('Skipping post %s' % str(i + 1))
continue
if opts.profile:
- print 'Profiling post %s' % str(i + 1)
+ print('Profiling post %s' % str(i + 1))
cProfile.runctx('output = md.convert(text)', globals(), locals())
else:
output = md.convert(text)
elapsed = time.time() - start
- print "%4s %1.18f %10s %s" % (i + 1, elapsed, len(text), p._id)
+ print("%4s %1.18f %10s %s" % (i + 1, elapsed, len(text), p._id))
if opts.output:
- print 'Input:', text[:min(300, len(text))]
- print 'Output:', output[:min(MAX_OUTPUT, len(output))]
+ print('Input:', text[:min(300, len(text))])
+ print('Output:', output[:min(MAX_OUTPUT, len(output))])
start = time.time()
- print "Total time:", start - begin
+ print("Total time:", start - begin)
return output
@@ -128,4 +132,4 @@ if __name__ == '__main__':
if opts.compare:
opts.re2 = not opts.re2
out2 = main(opts)
- print 're/re2 outputs match: ', out1 == out2
+ print('re/re2 outputs match: ', out1 == out2)
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/perf/sstress.py
----------------------------------------------------------------------
diff --git a/scripts/perf/sstress.py b/scripts/perf/sstress.py
index 3f1a1b1..26bcbce 100644
--- a/scripts/perf/sstress.py
+++ b/scripts/perf/sstress.py
@@ -20,6 +20,10 @@
'''
sstress - an SMTP stress testing tool
'''
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import smtplib
import threading
@@ -43,8 +47,8 @@ def main():
t.join()
end = time.time()
elapsed = end - begin
- print '%d requests completed in %f seconds' % (N, elapsed)
- print '%f requests/second' % (N / elapsed)
+ print('%d requests completed in %f seconds' % (N, elapsed))
+ print('%f requests/second' % (N / elapsed))
def stress():
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/perf/test_git_lcd.py
----------------------------------------------------------------------
diff --git a/scripts/perf/test_git_lcd.py b/scripts/perf/test_git_lcd.py
index 8d75e54..01a1831 100644
--- a/scripts/perf/test_git_lcd.py
+++ b/scripts/perf/test_git_lcd.py
@@ -17,6 +17,10 @@
# specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
import sys
import os
from glob import glob
@@ -42,11 +46,11 @@ def main(repo_dir, sub_dir='', commit=None):
commit = Mock(_id=commit or git.head)
paths = glob(os.path.join(repo_dir, sub_dir, '*'))
paths = [path.replace(repo_dir + '/', '', 1) for path in paths]
- print "Timing LCDs for %s at %s" % (paths, commit._id)
+ print("Timing LCDs for %s at %s" % (paths, commit._id))
with benchmark() as timer:
result = git.last_commit_ids(commit, paths)
pprint(result)
- print "Took %f seconds" % timer['result']
+ print("Took %f seconds" % timer['result'])
if __name__ == '__main__':
main(*sys.argv[1:])
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/prep-scm-sandbox.py
----------------------------------------------------------------------
diff --git a/scripts/prep-scm-sandbox.py b/scripts/prep-scm-sandbox.py
index 414280f..883d4a9 100644
--- a/scripts/prep-scm-sandbox.py
+++ b/scripts/prep-scm-sandbox.py
@@ -1,3 +1,7 @@
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
# 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
@@ -41,26 +45,26 @@ def main():
sb_host=sb_host,
sb=sb,
veid='%d0%.2d' % (sb_host, sb))
- for sb_host in 5, 6, 7, 9
+ for sb_host in (5, 6, 7, 9)
for sb in range(99)]
new_lines = '\n'.join(new_lines)
found_star = False
with open(SSH_CONFIG, 'w') as fp:
for line in lines:
if not found_star and line.startswith('Host *'):
- print >> fp, new_lines
+ print(new_lines, file=fp)
found_star = True
- print >> fp, line.rstrip()
+ print(line.rstrip(), file=fp)
if not found_star:
- print >> fp, new_lines
+ print(new_lines, file=fp)
os.system("ssh-keygen -t rsa -b 2048 -N '' -f %s" % KEYFILE)
# Generate ldif
pubkey = open(KEYFILE + '.pub').read()
with open(LDIF_FILE, 'w') as fp:
for user in USERS:
- print >> fp, LDIF_TMPL.substitute(
- user=user, pubkey=pubkey)
+ print(LDIF_TMPL.substitute(
+ user=user, pubkey=pubkey), file=fp)
# Update LDAP
assert 0 == os.system('/usr/local/sbin/ldaptool modify -v -f %s' %
http://git-wip-us.apache.org/repos/asf/allura/blob/d52f8e2a/scripts/prepare-allura-tickets-for-import.py
----------------------------------------------------------------------
diff --git a/scripts/prepare-allura-tickets-for-import.py b/scripts/prepare-allura-tickets-for-import.py
index dc6a695..743277b 100644
--- a/scripts/prepare-allura-tickets-for-import.py
+++ b/scripts/prepare-allura-tickets-for-import.py
@@ -16,6 +16,10 @@
# specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from __future__ import unicode_literals
from itertools import tee, izip, chain
import json
import git