Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: app/models/package.py

Issue 816693002: Add string versions of User/Pickled objects to datastore models (Closed) Base URL: https://github.com/dart-lang/pub-dartlang.git@master
Patch Set: Use db.Text(encoding="utf-8") Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « app/handlers/package_versions.py ('k') | app/models/package_version.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 # for details. All rights reserved. Use of this source code is governed by a 2 # for details. All rights reserved. Use of this source code is governed by a
3 # BSD-style license that can be found in the LICENSE file. 3 # BSD-style license that can be found in the LICENSE file.
4 4
5 import cgi 5 import cgi
6 import json 6 import json
7 import logging 7 import logging
8 8
9 from google.appengine.api import memcache 9 from google.appengine.api import memcache
10 from google.appengine.api import users 10 from google.appengine.api import users
(...skipping 15 matching lines...) Expand all
26 """ 26 """
27 27
28 MAX_SIZE = 10 * 2**20 # 10MB 28 MAX_SIZE = 10 * 2**20 # 10MB
29 """The maximum package size, in bytes.""" 29 """The maximum package size, in bytes."""
30 30
31 uploaders = db.ListProperty(users.User, validator=models.validate_not_empty) 31 uploaders = db.ListProperty(users.User, validator=models.validate_not_empty)
32 """The users who are allowed to upload new versions of the package. 32 """The users who are allowed to upload new versions of the package.
33 33
34 When this is set, invalidate_cache() must be called.""" 34 When this is set, invalidate_cache() must be called."""
35 35
36 uploaderEmails = db.StringListProperty()
37 """The user emails who are allowed to upload new versions of the package.
38
39 When this is set, invalidate_cache() must be called."""
40
36 name = db.StringProperty(required=True) 41 name = db.StringProperty(required=True)
37 """The name of the package.""" 42 """The name of the package."""
38 43
39 created = db.DateTimeProperty(auto_now_add=True) 44 created = db.DateTimeProperty(auto_now_add=True)
40 """When the package was created.""" 45 """When the package was created."""
41 46
42 downloads = db.IntegerProperty(required=True, default=0) 47 downloads = db.IntegerProperty(required=True, default=0)
43 """The number of times any version of this package has been downloaded.""" 48 """The number of times any version of this package has been downloaded."""
44 49
45 # This should only reference a PackageVersion, but cyclic imports aren't 50 # This should only reference a PackageVersion, but cyclic imports aren't
46 # allowed so we can't import PackageVersion here. 51 # allowed so we can't import PackageVersion here.
47 latest_version = db.ReferenceProperty() 52 latest_version = db.ReferenceProperty()
48 """The most recent non-prerelease version of this package. 53 """The most recent non-prerelease version of this package.
49 54
50 When this is set, invalidate_cache() must be called.""" 55 When this is set, invalidate_cache() must be called."""
51 56
57 def temp_synchronize_uploaders_to_uploaderemails(self):
58 """ Will synchronize self.uploaders -> self.uploaderEmails. """
59 if self.uploaders is None:
60 self.uploaderEmails = None
61 elif len(self.uploaders) == 0:
62 self.uploaderEmails = self.uploaders
63 else:
64 self.uploaderEmails = [uploader.email() for uploader in self.uploaders]
65
52 @property 66 @property
53 def description(self): 67 def description(self):
54 """The short description of the package.""" 68 """The short description of the package."""
55 if self.latest_version is None: return None 69 if self.latest_version is None: return None
56 return self.latest_version.pubspec.get('description') 70 return self.latest_version.pubspec.get('description')
57 71
58 _MAX_DESCRIPTION_CHARS = 200 72 _MAX_DESCRIPTION_CHARS = 200
59 73
60 @property 74 @property
61 def ellipsized_description(self): 75 def ellipsized_description(self):
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 cgi.escape(email), cgi.escape(author)) 121 cgi.escape(email), cgi.escape(author))
108 122
109 return '<br/>'.join(map(author_html, self.latest_version.pubspec.authors )) 123 return '<br/>'.join(map(author_html, self.latest_version.pubspec.authors ))
110 124
111 @property 125 @property
112 def uploaders_title(self): 126 def uploaders_title(self):
113 """The title for the uploaders list of the package.""" 127 """The title for the uploaders list of the package."""
114 return 'Uploader' if len(self.latest_version.pubspec.authors) == 1 \ 128 return 'Uploader' if len(self.latest_version.pubspec.authors) == 1 \
115 else 'Uploaders' 129 else 'Uploaders'
116 130
131 # TODO(kustermann): When we have string emails, this needs to be changed
132 # to read uploaderEmails instead of uploaders.
117 @property 133 @property
118 def uploaders_html(self): 134 def uploaders_html(self):
119 """Inline HTML for the uploaders of this package.""" 135 """Inline HTML for the uploaders of this package."""
120 return '<br/>'.join(cgi.escape(uploader.nickname()) 136 return '<br/>'.join(cgi.escape(uploader.nickname())
121 for uploader in self.uploaders) 137 for uploader in self.uploaders)
122 138
123 @property 139 @property
124 def short_updated(self): 140 def short_updated(self):
125 """The short updated time of the package.""" 141 """The short updated time of the package."""
126 return self.updated.strftime('%b %d, %Y') 142 return self.updated.strftime('%b %d, %Y')
(...skipping 25 matching lines...) Expand all
152 """Determine whether a package with the given name exists.""" 168 """Determine whether a package with the given name exists."""
153 return cls.get_by_key_name(name) is not None 169 return cls.get_by_key_name(name) is not None
154 170
155 def has_version(self, version): 171 def has_version(self, version):
156 """Determine whether this package has a given version uploaded.""" 172 """Determine whether this package has a given version uploaded."""
157 from package_version import PackageVersion 173 from package_version import PackageVersion
158 version = PackageVersion.get_by_name_and_version( 174 version = PackageVersion.get_by_name_and_version(
159 self.name, str(version)) 175 self.name, str(version))
160 return version is not None 176 return version is not None
161 177
178 # TODO(kustermann): When we have string emails, this needs to be changed
179 # to read uploaderEmails instead of uploaders.
162 def has_uploader(self, uploader): 180 def has_uploader(self, uploader):
163 """Determine whether the given user is an uploader for this package. 181 """Determine whether the given user is an uploader for this package.
164 182
165 This compares users via case-insensitive email comparison. 183 This compares users via case-insensitive email comparison.
166 184
167 Although admins have uploader privileges for all packages, this will not 185 Although admins have uploader privileges for all packages, this will not
168 return True for admins. 186 return True for admins.
169 """ 187 """
170 return uploader.email().lower() in \ 188 return uploader.email().lower() in \
171 [u.email().lower() for u in self.uploaders] 189 [u.email().lower() for u in self.uploaders]
172 190
173 @property 191 @property
174 def url(self): 192 def url(self):
175 """The API URL for this package.""" 193 """The API URL for this package."""
176 return models.url( 194 return models.url(
177 controller='api.packages', action='show', id=self.name) 195 controller='api.packages', action='show', id=self.name)
178 196
197 # TODO(kustermann): When we have string emails, this needs to be changed
198 # to read uploaderEmails instead of uploaders.
179 def as_dict(self, full=False): 199 def as_dict(self, full=False):
180 """Returns the dictionary representation of this package. 200 """Returns the dictionary representation of this package.
181 201
182 This is used to represent the package in API responses. Normally this 202 This is used to represent the package in API responses. Normally this
183 just includes URLs and some information about the latest version, but if 203 just includes URLs and some information about the latest version, but if
184 full is True, it will include all available information about the 204 full is True, it will include all available information about the
185 package. 205 package.
186 """ 206 """
187 207
188 value = { 208 value = {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 description of the package changes. This isn't often since most package 244 description of the package changes. This isn't often since most package
225 data is immutable, but when the uploader list changes or new versions 245 data is immutable, but when the uploader list changes or new versions
226 of the package are uploaded, the data will change. 246 of the package are uploaded, the data will change.
227 """ 247 """
228 memcache.delete(self._package_json_cache_key) 248 memcache.delete(self._package_json_cache_key)
229 249
230 @property 250 @property
231 def _package_json_cache_key(self): 251 def _package_json_cache_key(self):
232 """The memcache key for the cached JSON for this package.""" 252 """The memcache key for the cached JSON for this package."""
233 return 'package_json_' + self.name 253 return 'package_json_' + self.name
OLDNEW
« no previous file with comments | « app/handlers/package_versions.py ('k') | app/models/package_version.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698