~launchpad-pqm/launchpad/devel

8687.15.34 by Karl Fogel
Add license header blocks to .py, .zcml, and .pt files that don't have it
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
8786.1.2 by Tim Penhey
Write enough to get the tests passing.
3
4
"""Implementation for the IRevisionCache and IRevisionCollection."""
5
6
__metaclass__ = type
7
__all__ = [
8
    'GenericRevisionCollection',
9
    ]
10
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
11
from datetime import (
12
    datetime,
13
    timedelta,
14
    )
8786.1.10 by Tim Penhey
authoredBy works.
15
16
import pytz
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
17
from storm.expr import (
18
    Desc,
19
    Func,
20
    SQL,
21
    )
8786.1.2 by Tim Penhey
Write enough to get the tests passing.
22
from zope.component import getUtility
23
from zope.interface import implements
24
25
from canonical.launchpad.webapp.interfaces import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
26
    DEFAULT_FLAVOR,
27
    IStoreSelector,
28
    MAIN_STORE,
29
    )
8786.1.2 by Tim Penhey
Write enough to get the tests passing.
30
from lp.code.interfaces.revisioncache import IRevisionCollection
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
31
from lp.code.model.revision import (
32
    Revision,
33
    RevisionAuthor,
34
    RevisionCache,
35
    )
8786.1.8 by Tim Penhey
inDistribution works.#
36
from lp.registry.model.distroseries import DistroSeries
8786.1.6 by Tim Penhey
inProject working
37
from lp.registry.model.product import Product
8786.1.10 by Tim Penhey
authoredBy works.
38
from lp.registry.model.teammembership import TeamParticipation
8786.1.2 by Tim Penhey
Write enough to get the tests passing.
39
40
41
class GenericRevisionCollection:
42
    """See `IRevisionCollection`."""
43
44
    implements(IRevisionCollection)
45
46
    def __init__(self, store=None, filter_expressions=None):
47
        self._store = store
48
        if filter_expressions is None:
8786.1.16 by Tim Penhey
Add in authorCount.
49
            epoch = datetime.now(pytz.UTC) - timedelta(days=30)
50
            filter_expressions = [
51
                RevisionCache.revision_date >= epoch]
8786.1.2 by Tim Penhey
Write enough to get the tests passing.
52
        self._filter_expressions = filter_expressions
53
54
    @property
55
    def store(self):
56
        # Although you might think we could set the default value for store in
57
        # the constructor, we can't. The IStoreSelector utility is not
58
        # available at the time that the branchcollection.zcml is parsed,
59
        # which means we get an error if this code is in the constructor.
60
        if self._store is None:
61
            return getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
62
        else:
63
            return self._store
64
65
    def _filterBy(self, expressions):
66
        return self.__class__(
67
            self.store,
68
            self._filter_expressions + expressions)
69
70
    def count(self):
71
        """See `IRevisionCollection`."""
8786.1.16 by Tim Penhey
Add in authorCount.
72
        result_set = self.store.find(
73
            RevisionCache.revision_id, self._filter_expressions)
74
        result_set.config(distinct=True)
75
        return result_set.count()
76
77
    def authorCount(self):
78
        """See `IRevisionCollection`."""
8786.1.22 by Tim Penhey
New test for non-linked revision authors.
79
        # Revision authors that are linked to Launchpad people are only
8786.1.23 by Tim Penhey
Clean up the comment.
80
        # counted once even if the revision text that they use in the commit
8786.1.22 by Tim Penhey
New test for non-linked revision authors.
81
        # is different.
8786.1.16 by Tim Penhey
Add in authorCount.
82
        author = Func(
83
            'coalesce',
84
            RevisionAuthor.personID,
85
            SQL(0) - RevisionAuthor.id)
86
        expressions = [
87
            RevisionCache.revision_author == RevisionAuthor.id]
88
        expressions.extend(self._filter_expressions)
89
        result_set = self.store.find(author, expressions)
90
        result_set.config(distinct=True)
91
        return result_set.count()
8786.1.2 by Tim Penhey
Write enough to get the tests passing.
92
93
    def getRevisions(self):
94
        """See `IRevisionCollection`."""
8786.1.10 by Tim Penhey
authoredBy works.
95
        expressions = [
8786.1.16 by Tim Penhey
Add in authorCount.
96
            RevisionCache.revision == Revision.id]
8786.1.2 by Tim Penhey
Write enough to get the tests passing.
97
        expressions.extend(self._filter_expressions)
8786.1.3 by Tim Penhey
More tests pass.
98
        result_set = self.store.find(Revision, expressions)
99
        result_set.config(distinct=True)
8786.1.11 by Tim Penhey
date check works.
100
        result_set.order_by(Desc(Revision.revision_date))
8786.1.3 by Tim Penhey
More tests pass.
101
        return result_set
8786.1.4 by Tim Penhey
Public restriction tested.
102
103
    def public(self):
104
        """See `IRevisionCollection`."""
105
        return self._filterBy(
106
            [RevisionCache.private == False])
8786.1.5 by Tim Penhey
inProduct working.
107
108
    def inProduct(self, product):
109
        """See `IRevisionCollection`."""
110
        return self._filterBy(
111
            [RevisionCache.product == product])
8786.1.6 by Tim Penhey
inProject working
112
113
    def inProject(self, project):
114
        """See `IRevisionCollection`."""
115
        return self._filterBy(
116
            [RevisionCache.product == Product.id,
117
             Product.project == project])
8786.1.7 by Tim Penhey
inSourcePackage tested
118
119
    def inSourcePackage(self, package):
120
        """See `IRevisionCollection`."""
121
        return self._filterBy(
122
            [RevisionCache.distroseries == package.distroseries,
123
             RevisionCache.sourcepackagename == package.sourcepackagename])
8786.1.8 by Tim Penhey
inDistribution works.#
124
125
    def inDistribution(self, distribution):
126
        """See `IRevisionCollection`."""
127
        return self._filterBy(
128
            [DistroSeries.distribution == distribution,
129
             RevisionCache.distroseries == DistroSeries.id])
8786.1.9 by Tim Penhey
distroseries and distribution source packages are now filtered too.
130
131
    def inDistroSeries(self, distro_series):
132
        """See `IRevisionCollection`."""
133
        return self._filterBy(
134
            [RevisionCache.distroseries == distro_series])
135
136
    def inDistributionSourcePackage(self, distro_source_package):
8786.1.10 by Tim Penhey
authoredBy works.
137
        """See `IRevisionCollection`."""
8786.1.9 by Tim Penhey
distroseries and distribution source packages are now filtered too.
138
        distribution = distro_source_package.distribution
139
        sourcepackagename = distro_source_package.sourcepackagename
140
        return self._filterBy(
141
            [DistroSeries.distribution == distribution,
142
             RevisionCache.distroseries == DistroSeries.id,
143
             RevisionCache.sourcepackagename == sourcepackagename])
8786.1.10 by Tim Penhey
authoredBy works.
144
145
    def authoredBy(self, person):
146
        """See `IRevisionCollection`."""
147
        if person.is_team:
148
            query = [
149
                TeamParticipation.team == person,
150
                RevisionAuthor.personID == TeamParticipation.personID]
151
        else:
152
            query = [RevisionAuthor.person == person]
153
154
        query.append(RevisionCache.revision_author == RevisionAuthor.id)
155
        return self._filterBy(query)