OLD | NEW |
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 10 matching lines...) Expand all Loading... |
21 package is represented by a PackageVersion model. | 21 package is represented by a PackageVersion model. |
22 | 22 |
23 Whenever a new PackageVersion for a Package is added or modified, you must | 23 Whenever a new PackageVersion for a Package is added or modified, you must |
24 call invalidate_cache() to ensure any stale cached description of the | 24 call invalidate_cache() to ensure any stale cached description of the |
25 package is discarded. | 25 package is discarded. |
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 uploaderEmails = db.StringListProperty(validator=models.validate_not_empty) |
32 """The users who are allowed to upload new versions of the package. | |
33 | |
34 When this is set, invalidate_cache() must be called.""" | |
35 | |
36 uploaderEmails = db.StringListProperty() | |
37 """The user emails who are allowed to upload new versions of the package. | 32 """The user emails who are allowed to upload new versions of the package. |
38 | 33 |
39 When this is set, invalidate_cache() must be called.""" | 34 When this is set, invalidate_cache() must be called.""" |
40 | 35 |
41 name = db.StringProperty(required=True) | 36 name = db.StringProperty(required=True) |
42 """The name of the package.""" | 37 """The name of the package.""" |
43 | 38 |
44 created = db.DateTimeProperty(auto_now_add=True) | 39 created = db.DateTimeProperty(auto_now_add=True) |
45 """When the package was created.""" | 40 """When the package was created.""" |
46 | 41 |
47 downloads = db.IntegerProperty(required=True, default=0) | 42 downloads = db.IntegerProperty(required=True, default=0) |
48 """The number of times any version of this package has been downloaded.""" | 43 """The number of times any version of this package has been downloaded.""" |
49 | 44 |
50 # This should only reference a PackageVersion, but cyclic imports aren't | 45 # This should only reference a PackageVersion, but cyclic imports aren't |
51 # allowed so we can't import PackageVersion here. | 46 # allowed so we can't import PackageVersion here. |
52 latest_version = db.ReferenceProperty() | 47 latest_version = db.ReferenceProperty() |
53 """The most recent non-prerelease version of this package. | 48 """The most recent non-prerelease version of this package. |
54 | 49 |
55 When this is set, invalidate_cache() must be called.""" | 50 When this is set, invalidate_cache() must be called.""" |
56 | 51 |
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 | |
66 @property | 52 @property |
67 def description(self): | 53 def description(self): |
68 """The short description of the package.""" | 54 """The short description of the package.""" |
69 if self.latest_version is None: return None | 55 if self.latest_version is None: return None |
70 return self.latest_version.pubspec.get('description') | 56 return self.latest_version.pubspec.get('description') |
71 | 57 |
72 _MAX_DESCRIPTION_CHARS = 200 | 58 _MAX_DESCRIPTION_CHARS = 200 |
73 | 59 |
74 @property | 60 @property |
75 def ellipsized_description(self): | 61 def ellipsized_description(self): |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 """Determine whether a package with the given name exists.""" | 152 """Determine whether a package with the given name exists.""" |
167 return cls.get_by_key_name(name) is not None | 153 return cls.get_by_key_name(name) is not None |
168 | 154 |
169 def has_version(self, version): | 155 def has_version(self, version): |
170 """Determine whether this package has a given version uploaded.""" | 156 """Determine whether this package has a given version uploaded.""" |
171 from package_version import PackageVersion | 157 from package_version import PackageVersion |
172 version = PackageVersion.get_by_name_and_version( | 158 version = PackageVersion.get_by_name_and_version( |
173 self.name, str(version)) | 159 self.name, str(version)) |
174 return version is not None | 160 return version is not None |
175 | 161 |
176 def has_uploader(self, uploader): | 162 def has_uploader_email(self, uploaderEmail): |
177 """Determine whether the given user is an uploader for this package. | 163 """Determine whether the given user is an uploader for this package. |
178 | 164 |
179 This compares users via case-insensitive email comparison. | 165 This compares users via case-insensitive email comparison. |
180 | 166 |
181 Although admins have uploader privileges for all packages, this will not | 167 Although admins have uploader privileges for all packages, this will not |
182 return True for admins. | 168 return True for admins. |
183 """ | 169 """ |
184 return uploader.email().lower() in \ | 170 return uploaderEmail.lower() in \ |
185 [email.lower() for email in self.uploaderEmails] | 171 [email.lower() for email in self.uploaderEmails] |
186 | 172 |
187 @property | 173 @property |
188 def url(self): | 174 def url(self): |
189 """The API URL for this package.""" | 175 """The API URL for this package.""" |
190 return models.url( | 176 return models.url( |
191 controller='api.packages', action='show', id=self.name) | 177 controller='api.packages', action='show', id=self.name) |
192 | 178 |
193 def as_dict(self, full=False): | 179 def as_dict(self, full=False): |
194 """Returns the dictionary representation of this package. | 180 """Returns the dictionary representation of this package. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 description of the package changes. This isn't often since most package | 224 description of the package changes. This isn't often since most package |
239 data is immutable, but when the uploader list changes or new versions | 225 data is immutable, but when the uploader list changes or new versions |
240 of the package are uploaded, the data will change. | 226 of the package are uploaded, the data will change. |
241 """ | 227 """ |
242 memcache.delete(self._package_json_cache_key) | 228 memcache.delete(self._package_json_cache_key) |
243 | 229 |
244 @property | 230 @property |
245 def _package_json_cache_key(self): | 231 def _package_json_cache_key(self): |
246 """The memcache key for the cached JSON for this package.""" | 232 """The memcache key for the cached JSON for this package.""" |
247 return 'package_json_' + self.name | 233 return 'package_json_' + self.name |
OLD | NEW |