Skip to content

Commit 880ea0e

Browse files
committed
Add model for Subscription
1 parent f7f206e commit 880ea0e

1 file changed

Lines changed: 129 additions & 110 deletions

File tree

code_comments/subscription.py

Lines changed: 129 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -5,118 +5,137 @@
55
from code_comments.comments import Comments
66

77

8-
def create_subscription(env, user, role, type_, path, rev, repos=None,
9-
notify='always'):
8+
class Subscription(object):
109
"""
11-
Create a code comment subscription for a given user.
12-
13-
:param str user: The user to subscribe
14-
:param str role: The type of subscription: "author" or "commenter"
15-
:param str_ type: What the subscription is to e.g., "attachment"
16-
:param path: The path of the subscription
17-
:type path: str or None
18-
:param repos: The name of repository
19-
:type repos: str or None
20-
:param rev: The revision
21-
:type repos: int or None
22-
:param str notify: Whether the subscription issues a notification
23-
("always") or not ("never")
24-
:return: The id of the new subscription
25-
:rtype: int
10+
Representation of a code comment subscription.
2611
"""
27-
sub = {
28-
'user': user,
29-
'role': role,
30-
'type': type_,
31-
'path': path or '',
32-
'notify': notify,
33-
}
34-
35-
if type_ in ('changeset', 'browser'):
36-
_repo = RepositoryManager(env).get_repository(repos)
12+
id = 0
13+
user = ''
14+
role = ''
15+
type = ''
16+
path = ''
17+
rev = ''
18+
repos = ''
19+
notify = 'always'
20+
21+
def __init__(self, env, data=None):
22+
if isinstance(data, dict):
23+
self.__dict__ = data
24+
self.env = env
25+
26+
def insert(self, db=None):
27+
"""
28+
Insert a new subscription.
29+
"""
30+
@self.env.with_transaction(db)
31+
def do_insert(db):
32+
cursor = db.cursor()
33+
insert = ("INSERT INTO code_comments_subscriptions "
34+
"(user, role, type, path, repos, rev, notify) "
35+
"VALUES (%s, %s, %s, %s, %s, %s, %s)")
36+
values = (self.user, self.role, self.type, self.path, self.repos,
37+
self.rev, self.notify)
38+
cursor.execute(insert, values)
39+
self.id = db.get_last_id(cursor, 'code_comments_subscriptions')
40+
41+
@classmethod
42+
def _from_row(cls, env, row):
43+
"""
44+
Creates a subscription from a list (representing a database row).
45+
"""
3746
try:
38-
sub['repos'] = _repo.reponame
39-
if rev:
40-
sub['rev'] = _repo.db_rev(rev)
41-
else:
42-
sub['rev'] = 'any' # wildcard
43-
finally:
44-
_repo.close()
45-
else:
46-
sub['repos'] = ''
47-
sub['rev'] = ''
48-
49-
@env.with_transaction()
50-
def insert_subscription(db):
51-
cursor = db.cursor()
52-
select = ("SELECT id FROM code_comments_subscriptions WHERE "
53-
"user = '{user}' AND type = '{type}' AND "
54-
"path = '{path}' AND repos = '{repos}' AND "
55-
"rev = '{rev}' AND notify = '{notify}'").format(**sub)
56-
cursor.execute(select)
57-
subs = cursor.fetchall()
58-
if len(subs) > 0:
59-
# There shouldn't really ever be more than one result
47+
subscription = cls(env)
48+
subscription.id = row[0]
49+
subscription.user = row[1]
50+
subscription.role = row[2]
51+
subscription.type = row[3]
52+
subscription.path = row[4]
53+
subscription.repos = row[5]
54+
subscription.rev = row[6]
55+
subscription.notify = row[7]
56+
return subscription
57+
except IndexError:
58+
# Invalid row
59+
return None
60+
61+
@classmethod
62+
def _from_dict(cls, env, dict_):
63+
"""
64+
Creates a subscription from a dict.
65+
"""
66+
cursor = env.get_read_db().cursor()
67+
select = ("SELECT * FROM code_comments_subscriptions WHERE "
68+
"user=%s AND type=%s AND path=%s AND "
69+
"repos=%s AND rev=%s AND notify=%s"
70+
)
71+
values = (dict_['user'], dict_['type'], dict_['path'], dict_['repos'],
72+
dict_['rev'], dict_['notify'])
73+
cursor.execute(select, values)
74+
row = cursor.fetchone()
75+
if row:
6076
env.log.debug(
61-
'Subscription for {type} already exists'.format(**sub))
62-
return subs[0]
77+
'Subscription for {type} already exists'.format(**dict_))
78+
return cls._from_row(env, row)
6379
else:
64-
fields = ', '.join(sub.keys())
65-
values_template = ', '.join(['%s'] * len(sub))
66-
insert = ("INSERT INTO code_comments_subscriptions "
67-
"({0}) VALUES ({1})").format(fields, values_template)
68-
cursor.execute(insert, sub.values())
6980
env.log.debug(
70-
'Subscription for {type} created'.format(**sub))
71-
return db.get_last_id(cursor, 'code_comments_subscriptions')
72-
73-
74-
def create_subscription_from_changeset(env, changeset):
75-
sub = {
76-
'user': changeset.author,
77-
'role': 'author',
78-
'type_': 'changeset',
79-
'path': None,
80-
'repos': changeset.repos.reponame,
81-
'rev': changeset.rev,
82-
'notify': 'always',
83-
}
84-
create_subscription(env, **sub)
85-
86-
87-
def create_subscription_from_comment(env, comment):
88-
sub = {
89-
'user': comment.author,
90-
'role': 'commenter',
91-
'type_': comment.type,
92-
'notify': 'always'
93-
}
94-
95-
# Munge attachments
96-
if comment.type == 'attachment':
97-
sub['path'] = comment.path.split(':')[1]
98-
sub['repos'] = None,
99-
sub['rev'] = None
100-
101-
# Munge changesets and browser
102-
if comment.type in ('changeset', 'browser'):
103-
if comment.type == 'browser':
104-
sub['path'] = comment.path
105-
else:
106-
sub['path'] = None
107-
repo = RepositoryManager(env).get_repository(None)
108-
try:
109-
sub['repos'] = repo.reponame
81+
'Subscription for {type} created'.format(**dict_))
82+
subscription = cls(env, dict_)
83+
subscription.insert()
84+
return subscription
85+
86+
@classmethod
87+
def from_changeset(cls, env, changeset):
88+
"""
89+
Creates a subscription from a Changeset object.
90+
"""
91+
sub = {
92+
'user': changeset.author,
93+
'role': 'author',
94+
'type': 'changeset',
95+
'path': '',
96+
'repos': changeset.repos.reponame,
97+
'rev': changeset.rev,
98+
'notify': 'always',
99+
}
100+
return cls._from_dict(env, sub)
101+
102+
@classmethod
103+
def from_comment(cls, env, comment):
104+
"""
105+
Creates a subscription from a Comment object.
106+
"""
107+
sub = {
108+
'user': comment.author,
109+
'role': 'commenter',
110+
'type': comment.type,
111+
'notify': 'always'
112+
}
113+
114+
# Munge attachments
115+
if comment.type == 'attachment':
116+
sub['path'] = comment.path.split(':')[1]
117+
sub['repos'] = ''
118+
sub['rev'] = ''
119+
120+
# Munge changesets and browser
121+
if comment.type in ('changeset', 'browser'):
122+
if comment.type == 'browser':
123+
sub['path'] = comment.path
124+
else:
125+
sub['path'] = ''
126+
repo = RepositoryManager(env).get_repository(None)
110127
try:
111-
_cs = repo.get_changeset(comment.revision)
112-
sub['rev'] = _cs.rev
113-
except NoSuchChangeset:
114-
# Invalid changeset
115-
return None
116-
finally:
117-
repo.close()
128+
sub['repos'] = repo.reponame
129+
try:
130+
_cs = repo.get_changeset(comment.revision)
131+
sub['rev'] = _cs.rev
132+
except NoSuchChangeset:
133+
# Invalid changeset
134+
return None
135+
finally:
136+
repo.close()
118137

119-
return create_subscription(env, **sub)
138+
return cls._from_dict(env, sub)
120139

121140

122141
class SubscriptionAdmin(Component):
@@ -143,13 +162,13 @@ def _do_seed(self):
143162
sub = {
144163
'user': attachment[3],
145164
'role': 'author',
146-
'type_': 'attachment',
165+
'type': 'attachment',
147166
'path': "/{0}/{1}/{2}".format(*attachment),
148-
'repos': None,
149-
'rev': None,
167+
'repos': '',
168+
'rev': '',
150169
'notify': 'always',
151170
}
152-
create_subscription(self.env, **sub)
171+
Subscription._from_dict(self.env, sub)
153172

154173
# Create a subscription for all existing revisions
155174
rm = RepositoryManager(self.env)
@@ -159,12 +178,12 @@ def _do_seed(self):
159178
while _rev:
160179
try:
161180
_cs = repo.get_changeset(_rev)
162-
create_subscription_from_changeset(self.env, _cs)
181+
Subscription.from_changeset(self.env, _cs)
163182
except NoSuchChangeset:
164183
pass
165184
_rev = repo.next_rev(_rev)
166185

167186
# Create a subscription for all existing comments
168187
comments = Comments(None, self.env).all()
169188
for comment in comments:
170-
create_subscription_from_comment(self.env, comment)
189+
Subscription.from_comment(self.env, comment)

0 commit comments

Comments
 (0)