Esempio n. 1
0
 def _create(resource, error=None, metadata=None, body_stream=None):
     self = ResourceRevision()
     self.resource = resource
     self.error = error
     self.metadata = metadata
     # (self._id computed below)
     self.has_body = body_stream is not None
     
     project = self.project
     
     # Need to do this first to get the database ID
     def fg_task():
         RR = ResourceRevision
         
         c = project._db.cursor()
         c.execute('insert into resource_revision (resource_id, error, metadata) values (?, ?, ?)', (resource._id, RR._encode_error(error), RR._encode_metadata(metadata)))
         project._db.commit()
         self._id = c.lastrowid
     fg_call_and_wait(fg_task)
     
     if body_stream:
         try:
             body_filepath = os.path.join(project.path, Project._RESOURCE_REVISION_DIRNAME, str(self._id))
             with open(body_filepath, 'wb') as body_file:
                 shutil.copyfileobj(body_stream, body_file)
         except:
             # Rollback database commit
             def fg_task():
                 c = project._db.cursor()
                 c.execute('delete from resource_revision where id=?', (self._id,))
                 project._db.commit()
             fg_call_and_wait(fg_task)
             raise
     
     return self
Esempio n. 2
0
 def __call__(self):
     # If the resource is already up-to-date, return its default revision
     def fg_task():
         if self._resource.up_to_date():
             return self._resource.default_revision()
         else:
             return None
     body_revision = fg_call_and_wait(fg_task)
     if body_revision is not None:
         return body_revision
     
     # TODO: Report errors (embedded in the ResourceRevision) using the completion subtitle.
     #       Need to add support for this behavior to Task.
     try:
         from crystal.download import download_resource_revision
         body_revision = download_resource_revision(self._resource, self)
         
         # Automatically parse the body's links and create associated resources
         self.subtitle = 'Parsing links...'
         r = self._resource
         links = body_revision.links()
         urls = [urlparse.urljoin(r.url, link.relative_url) for link in links]
         
         self.subtitle = 'Recording links...'
         def fg_task():
             # PERF: This is taking 1-2 sec to execute on THEM's Review List page.
             #       Need to look at optimizing this to avoid blocking the UI.
             for url in urls:
                 Resource(r.project, url)
         fg_call_and_wait(fg_task)
         
         return body_revision
     finally:
         self.subtitle = 'Waiting before performing next request...'
         sleep(_DELAY_BETWEEN_DOWNLOADS)
Esempio n. 3
0
 def do_GET(self):
     request_host = self.request_host
     request_url = 'http://%s%s' % (request_host, self.path)
     
     scheme_rest_match = _SCHEME_REST_RE.match(self.path)
     if not scheme_rest_match:
         path_parts = urlparse.urlparse(self.path)
         if path_parts.path == '/':
             query_params = urlparse.parse_qs(path_parts.query)
         else:
             query_params = {}
         
         self.send_welcome_page(query_params)
         return
     (scheme, rest) = scheme_rest_match.groups()
     archive_url = '%s://%s' % (scheme, rest)
     
     # TODO: Normalize archive url by stripping fragment (and maybe also {params, query}).
     #       This should probably be implemented in a static method on Resource,
     #       as this functionality should also be used by the Resource constructor.
     resource = self.project.get_resource(archive_url)
     if not resource:
         self.send_resource_not_in_archive(archive_url)
         return
     
     revision = fg_call_and_wait(resource.default_revision)
     if not revision:
         self.send_resource_not_in_archive(archive_url)
         return
     
     self.send_revision(revision)
Esempio n. 4
0
 def bg_task():
     while True:
         def fg_task():
             return (task.try_get_next_task_unit(), task.complete)
         (unit, task_complete) = fg_call_and_wait(fg_task)
         
         if unit is None:
             if task_complete:
                 break
             else:
                 sleep(_ROOT_TASK_POLL_INTERVAL)
                 continue
         unit()  # Run unit directly on this bg thread