| 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 copy |    5 import copy | 
|    6 import json |    6 import json | 
|    7 import tarfile |    7 import tarfile | 
|    8  |    8  | 
|    9 from google.appengine.api import memcache |    9 from google.appengine.api import memcache | 
|   10 from google.appengine.ext import db |   10 from google.appengine.ext import db | 
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   65     """When this package version was created.""" |   65     """When this package version was created.""" | 
|   66  |   66  | 
|   67     downloads = db.IntegerProperty(required=True, default=0) |   67     downloads = db.IntegerProperty(required=True, default=0) | 
|   68     """The number of times this package version has been downloaded.""" |   68     """The number of times this package version has been downloaded.""" | 
|   69  |   69  | 
|   70     sort_order = db.IntegerProperty(default=-1) |   70     sort_order = db.IntegerProperty(default=-1) | 
|   71     """The sort order for this version. |   71     """The sort order for this version. | 
|   72  |   72  | 
|   73     Lower numbers indicate earlier versions.""" |   73     Lower numbers indicate earlier versions.""" | 
|   74  |   74  | 
|   75     uploader = db.UserProperty(required=True) |   75     uploaderEmail = db.StringProperty(required=True) | 
|   76     """The user who uploaded this package version.""" |  | 
|   77  |  | 
|   78     uploaderEmail = db.StringProperty() |  | 
|   79     """The user email who uploaded this package version.""" |   76     """The user email who uploaded this package version.""" | 
|   80  |   77  | 
|   81     def temp_synchronize_uploader_to_uploaderemail_and_pickles(self): |  | 
|   82       """ Will synchronize properties. |  | 
|   83  |  | 
|   84       uploader/readme/changelog -> uploaderEmail/readmeString/changelogString |  | 
|   85       """ |  | 
|   86       if self.uploader is None: |  | 
|   87         self.uploaderEmail = None |  | 
|   88       else: |  | 
|   89         self.uploaderEmail = self.uploader.email() |  | 
|   90  |  | 
|   91       if self.readme: |  | 
|   92         self.readmeFilename = self.readme.filename |  | 
|   93         self.readmeContent = db.Text(self.readme.text) |  | 
|   94  |  | 
|   95       if self.changelog: |  | 
|   96         self.changelogFilename = self.changelog.filename |  | 
|   97         self.changelogContent = db.Text(self.changelog.text) |  | 
|   98  |  | 
|   99     @property |   78     @property | 
|  100     def readme_obj(self): |   79     def readme_obj(self): | 
|  101       if self.readmeFilename: |   80       if self.readmeFilename: | 
|  102         return Readme(self.readmeContent, self.readmeFilename) |   81         return Readme(self.readmeContent, self.readmeFilename) | 
|  103       else: |   82       else: | 
|  104         return None |   83         return None | 
|  105  |   84  | 
|  106     @property |   85     @property | 
|  107     def changelog_obj(self): |   86     def changelog_obj(self): | 
|  108       if self.readmeFilename: |   87       if self.changelogFilename: | 
|  109         return Readme(self.changelogContent, self.changelogFilename) |   88         return Readme(self.changelogContent, self.changelogFilename) | 
|  110       else: |   89       else: | 
|  111         return None |   90         return None | 
|  112  |   91  | 
|  113     @classmethod |   92     @classmethod | 
|  114     def new(cls, **kwargs): |   93     def new(cls, **kwargs): | 
|  115         """Construct a new package version. |   94         """Construct a new package version. | 
|  116  |   95  | 
|  117         Unlike __init__, this infers some properties from others. In particular: |   96         Unlike __init__, this infers some properties from others. In particular: | 
|  118  |   97  | 
|  119         - The version is inferred from the pubspec. |   98         - The version is inferred from the pubspec. | 
|  120         - The key name is set to the version. |   99         - The key name is set to the version. | 
|  121         - The parent entity is set to the package. |  100         - The parent entity is set to the package. | 
|  122         """ |  101         """ | 
|  123  |  102  | 
|  124         if 'pubspec' in kwargs and 'version' not in kwargs: |  103         if 'pubspec' in kwargs and 'version' not in kwargs: | 
|  125             kwargs['version'] = kwargs['pubspec'].required('version') |  104             kwargs['version'] = kwargs['pubspec'].required('version') | 
|  126  |  105  | 
|  127         if 'version' in kwargs and \ |  106         if 'version' in kwargs and \ | 
|  128                 not isinstance(kwargs['version'], SemanticVersion): |  107                 not isinstance(kwargs['version'], SemanticVersion): | 
|  129             kwargs['version'] = SemanticVersion(kwargs['version']) |  108             kwargs['version'] = SemanticVersion(kwargs['version']) | 
|  130  |  109  | 
 |  110         if 'readme' in kwargs and kwargs['readme']: | 
 |  111             kwargs['readmeFilename'] = kwargs['readme'].filename | 
 |  112             kwargs['readmeContent'] = kwargs['readme'].text | 
 |  113             del kwargs['readme'] | 
 |  114  | 
 |  115         if 'changelog' in kwargs and kwargs['changelog']: | 
 |  116             kwargs['changelogFilename'] = kwargs['changelog'].filename | 
 |  117             kwargs['changelogContent'] = kwargs['changelog'].text | 
 |  118             del kwargs['changelog'] | 
 |  119  | 
|  131         if not 'key_name' in kwargs and not 'key' in kwargs: |  120         if not 'key_name' in kwargs and not 'key' in kwargs: | 
|  132             kwargs['key_name'] = str(kwargs['version'].canonical) |  121             kwargs['key_name'] = str(kwargs['version'].canonical) | 
|  133  |  122  | 
|  134         if not 'parent' in kwargs: |  123         if not 'parent' in kwargs: | 
|  135             kwargs['parent'] = kwargs['package'] |  124             kwargs['parent'] = kwargs['package'] | 
|  136  |  125  | 
|  137         version = cls(**kwargs) |  126         version = cls(**kwargs) | 
|  138         version._validate_fields_match_pubspec() |  127         version._validate_fields_match_pubspec() | 
|  139         return version |  128         return version | 
|  140  |  129  | 
|  141     # TODO(kustermann): When we have string emails, this needs to be changed |  | 
|  142     # to read uploaderEmails instead of uploaders. |  | 
|  143     @classmethod |  130     @classmethod | 
|  144     def from_archive(cls, file, uploader): |  131     def from_archive(cls, file, uploaderEmail): | 
|  145         """Load a package version from a .tar.gz archive. |  132         """Load a package version from a .tar.gz archive. | 
|  146  |  133  | 
|  147         If the package specified in the archive already exists, it will be |  134         If the package specified in the archive already exists, it will be | 
|  148         loaded and assigned as the package version's package. If it doesn't, a |  135         loaded and assigned as the package version's package. If it doesn't, a | 
|  149         new package will be created. |  136         new package will be created. | 
|  150  |  137  | 
|  151         Arguments: |  138         Arguments: | 
|  152           file: An open file object containing a .tar.gz archive. |  139           file: An open file object containing a .tar.gz archive. | 
|  153           uploader: The user who uploaded this package archive. |  140           uploaderEmail: The user email who uploaded this package archive. | 
|  154  |  141  | 
|  155         Returns: Both the Package object and the PackageVersion object. |  142         Returns: Both the Package object and the PackageVersion object. | 
|  156         """ |  143         """ | 
|  157         try: |  144         try: | 
|  158             tar = tarfile.open(mode="r:gz", fileobj=file) |  145             tar = tarfile.open(mode="r:gz", fileobj=file) | 
|  159             changelog = Readme.from_archive(tar, name='CHANGELOG') |  146             changelog = Readme.from_archive(tar, name='CHANGELOG') | 
|  160             readme = Readme.from_archive(tar) |  147             readme = Readme.from_archive(tar) | 
|  161             pubspec = Pubspec.from_archive(tar) |  148             pubspec = Pubspec.from_archive(tar) | 
|  162             name = pubspec.required('name') |  149             name = pubspec.required('name') | 
|  163             package = Package.get_by_key_name(name) |  150             package = Package.get_by_key_name(name) | 
|  164             if not package: |  151             if not package: | 
|  165                 assert uploader is not None |  152                 assert uploaderEmail is not None | 
|  166                 package = Package.new(name=name, uploaders=[uploader]) |  153                 package = Package.new(name=name, uploaderEmails=[uploaderEmail]) | 
|  167  |  154  | 
|  168             libraries = sorted(name[4:] for name in tar.getnames() |  155             libraries = sorted(name[4:] for name in tar.getnames() | 
|  169                                if name.startswith('lib/') and |  156                                if name.startswith('lib/') and | 
|  170                                    not name.startswith('lib/src/') and |  157                                    not name.startswith('lib/src/') and | 
|  171                                    name.endswith('.dart')) |  158                                    name.endswith('.dart')) | 
|  172  |  159  | 
|  173             return PackageVersion.new( |  160             return PackageVersion.new( | 
|  174                 package=package, changelog=changelog, readme=readme, |  161                 package=package, changelog=changelog, readme=readme, | 
|  175                 pubspec=pubspec, libraries=libraries, uploader=uploader) |  162                 pubspec=pubspec, libraries=libraries, | 
 |  163                 uploaderEmail=uploaderEmail) | 
|  176         except (tarfile.TarError, KeyError) as err: |  164         except (tarfile.TarError, KeyError) as err: | 
|  177             raise db.BadValueError( |  165             raise db.BadValueError( | 
|  178                 "Error parsing package archive: %s" % err) |  166                 "Error parsing package archive: %s" % err) | 
|  179  |  167  | 
|  180     @classmethod |  168     @classmethod | 
|  181     def get_by_name_and_version(cls, package_name, version): |  169     def get_by_name_and_version(cls, package_name, version): | 
|  182         """Looks up a package version by its package name and version.""" |  170         """Looks up a package version by its package name and version.""" | 
|  183         parent_key = db.Key.from_path('Package', package_name) |  171         parent_key = db.Key.from_path('Package', package_name) | 
|  184         return cls.get_by_key_name( |  172         return cls.get_by_key_name( | 
|  185             SemanticVersion(version).canonical, parent=parent_key) |  173             SemanticVersion(version).canonical, parent=parent_key) | 
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  296                 'Version "%s" in pubspec doesn\'t match version "%s"' % |  284                 'Version "%s" in pubspec doesn\'t match version "%s"' % | 
|  297                 (version_in_pubspec._key(), self.version._key())) |  285                 (version_in_pubspec._key(), self.version._key())) | 
|  298     @property |  286     @property | 
|  299     def url(self): |  287     def url(self): | 
|  300         """The API URL for this package version.""" |  288         """The API URL for this package version.""" | 
|  301         return models.url(controller='api.versions', |  289         return models.url(controller='api.versions', | 
|  302                           action='show', |  290                           action='show', | 
|  303                           package_id=self.package.name, |  291                           package_id=self.package.name, | 
|  304                           id=str(self.version)) |  292                           id=str(self.version)) | 
|  305  |  293  | 
|  306     # TODO(kustermann): When we have string emails, this needs to be changed |  | 
|  307     # to read uploaderEmails instead of uploaders. |  | 
|  308     def as_dict(self, full=False): |  294     def as_dict(self, full=False): | 
|  309         """Returns the dictionary representation of this package version. |  295         """Returns the dictionary representation of this package version. | 
|  310  |  296  | 
|  311         This is used to represent the package in API responses. Normally this |  297         This is used to represent the package in API responses. Normally this | 
|  312         just includes URLs and the pubspec, but if full is True, it will include |  298         just includes URLs and the pubspec, but if full is True, it will include | 
|  313         all available information about the package version. |  299         all available information about the package version. | 
|  314         """ |  300         """ | 
|  315  |  301  | 
|  316         value = { |  302         value = { | 
|  317             'version': str(self.version), |  303             'version': str(self.version), | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  330  |  316  | 
|  331         if full: |  317         if full: | 
|  332             value.update({ |  318             value.update({ | 
|  333                 'created': self.created.isoformat(), |  319                 'created': self.created.isoformat(), | 
|  334                 'downloads': self.downloads, |  320                 'downloads': self.downloads, | 
|  335                 'libraries': self.libraries, |  321                 'libraries': self.libraries, | 
|  336                 'uploader': self.uploaderEmail |  322                 'uploader': self.uploaderEmail | 
|  337             }) |  323             }) | 
|  338  |  324  | 
|  339         return value |  325         return value | 
| OLD | NEW |