Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/207#discussion_r150775602
  
    --- Diff: aria/parser/consumption/presentation.py ---
    @@ -86,52 +73,193 @@ def dump(self):
                 self.context.presentation.presenter._dump(self.context)
     
         def _handle_exception(self, e):
    -        if isinstance(e, AlreadyReadException):
    +        if isinstance(e, _Skip):
                 return
             super(Read, self)._handle_exception(e)
     
    -    def _present(self, location, origin_location, presenter_class, 
executor):
    +    def _present_all(self):
    +        location = self.context.presentation.location
    +
    +        if location is None:
    +            self.context.validation.report('Read consumer: missing 
location')
    +            return
    +
    +        executor = self.context.presentation.create_executor()
    +        try:
    +            # This call may recursively submit tasks to the executor if 
there are imports
    +            main = self._present(location, None, None, executor)
    +
    +            # Wait for all tasks to complete
    +            executor.drain()
    +
    +            # Handle exceptions
    +            for e in executor.exceptions:
    +                self._handle_exception(e)
    +
    +            results = executor.returns or []
    +        finally:
    +            executor.close()
    +
    +        results.insert(0, main)
    +
    +        return main, results
    +
    +    def _present(self, location, origin_canonical_location, 
origin_presenter_class, executor):
             # Link the context to this thread
             self.context.set_thread_local()
     
    -        raw = self._read(location, origin_location)
    +        # Canonicalize the location
    +        if self.context.reading.reader is None:
    +            loader, canonical_location = self._create_loader(location, 
origin_canonical_location)
    +        else:
    +            # If a reader is specified in the context then we skip loading
    +            loader = None
    +            canonical_location = location
    +
    +        # Skip self imports
    +        if canonical_location == origin_canonical_location:
    +            raise _Skip()
    +
    +        if self.context.presentation.cache:
    +            # Is the presentation in the global cache?
    +            try:
    +                presentation = PRESENTATION_CACHE[canonical_location]
    +                return _Result(presentation, canonical_location, 
origin_canonical_location)
    +            except KeyError:
    +                pass
    +
    +        try:
    +            # Is the presentation in the local cache?
    +            presentation = self._cache[canonical_location]
    +            return _Result(presentation, canonical_location, 
origin_canonical_location)
    +        except KeyError:
    +            pass
    +
    +        # Create and cache new presentation
    +        presentation = self._create_presentation(canonical_location, 
loader, origin_presenter_class)
    +        self._cache[canonical_location] = presentation
     
    +        # Submit imports to executor
    +        if hasattr(presentation, '_get_import_locations'):
    +            import_locations = 
presentation._get_import_locations(self.context)
    +            if import_locations:
    +                for import_location in import_locations:
    +                    import_location = UriLocation(import_location)
    +                    executor.submit(self._present, import_location, 
canonical_location,
    +                                    presentation.__class__, executor)
    +
    +        return _Result(presentation, canonical_location, 
origin_canonical_location)
    +
    +    def _create_loader(self, location, origin_canonical_location):
    +        loader = 
self.context.loading.loader_source.get_loader(self.context.loading, location,
    +                                                               
origin_canonical_location)
    +
    +        canonical_location = None
    +
    +        if origin_canonical_location is not None:
    +            cache_key = (origin_canonical_location, location)
    +            try:
    +                canonical_location = CANONICAL_LOCATION_CACHE[cache_key]
    +                return loader, canonical_location
    +            except KeyError:
    +                pass
    +        else:
    +            cache_key = None
    +
    +        canonical_location = loader.get_canonical_location()
    +
    +        # Because retrieving the canonical location can be costly, we will 
try to cache it
    +        if cache_key is not None:
    +            CANONICAL_LOCATION_CACHE[cache_key] = canonical_location
    +
    +        return loader, canonical_location
    +
    +    def _create_presentation(self, canonical_location, loader, 
default_presenter_class):
    +        # The reader we specified in the context will override
    +        reader = self.context.reading.reader
    +
    +        if reader is None:
    +            # Read raw data from loader
    +            reader = 
self.context.reading.reader_source.get_reader(self.context.reading,
    +                                                                   
canonical_location, loader)
    +
    +        raw = reader.read()
    +
    +        # Wrap raw data in presenter class
             if self.context.presentation.presenter_class is not None:
    -            # The presenter class we specified in the context overrides 
everything
    +            # The presenter class we specified in the context will override
                 presenter_class = self.context.presentation.presenter_class
             else:
                 try:
                     presenter_class = 
self.context.presentation.presenter_source.get_presenter(raw)
                 except PresenterNotFoundError:
    -                if presenter_class is None:
    +                if default_presenter_class is None:
                         raise
    -            # We'll use the presenter class we were given (from the 
presenter that imported us)
    -            if presenter_class is None:
    -                raise PresenterNotFoundError('presenter not found')
    +                else:
    +                    presenter_class = default_presenter_class
    +
    +        if presenter_class is None:
    +            raise PresenterNotFoundError(u'presenter not found: 
{0}'.format(canonical_location))
     
             presentation = presenter_class(raw=raw)
     
    -        if presentation is not None and hasattr(presentation, 
'_link_locators'):
    +        if hasattr(presentation, '_link_locators'):
                 presentation._link_locators()
     
    -        # Submit imports to executor
    -        if hasattr(presentation, '_get_import_locations'):
    -            import_locations = 
presentation._get_import_locations(self.context)
    -            if import_locations:
    -                for import_location in import_locations:
    -                    # The imports inherit the parent presenter class and 
use the current location as
    -                    # their origin location
    -                    import_location = UriLocation(import_location)
    -                    executor.submit(self._present, import_location, 
location, presenter_class,
    -                                    executor)
    -
             return presentation
     
    -    def _read(self, location, origin_location):
    -        if self.context.reading.reader is not None:
    -            return self.context.reading.reader.read()
    -        loader = 
self.context.loading.loader_source.get_loader(self.context.loading, location,
    -                                                               
origin_location)
    -        reader = 
self.context.reading.reader_source.get_reader(self.context.reading, location,
    -                                                               loader)
    -        return reader.read()
    +
    +class _Result(object):
    +    def __init__(self, presentation, canonical_location, 
origin_canonical_location):
    +        self.presentation = presentation
    +        self.canonical_location = canonical_location
    +        self.origin_canonical_location = origin_canonical_location
    +        self.merged = False
    +
    +    def get_imports(self, results):
    +        imports = []
    +
    +        def has_import(result):
    +            for i in imports:
    +                if i.canonical_location == result.canonical_location:
    +                    return True
    +            return False
    +
    +        for result in results:
    +            if result.origin_canonical_location == self.canonical_location:
    +                if not has_import(result):
    +                    imports.append(result)
    +        return imports
    +
    +    def merge(self, results, context):
    +        # Make sure to only merge each presentation once
    +        if self.merged:
    +            return
    +        self.merged = True
    +        for result in results:
    +            if result.presentation == self.presentation:
    +                result.merged = True
    +
    +        for result in self.get_imports(results):
    +            # Make sure import is merged
    +            result.merge(results, context)
    +
    +            # Validate import
    +            if hasattr(self.presentation, '_validate_import'):
    +                if not self.presentation._validate_import(context, 
result.presentation):
    +                    # _validate_import will report an issue if invalid
    +                    continue
    +
    +            # Merge import
    +            if hasattr(self.presentation, '_merge_import'):
    --- End diff --
    
    ditto


---

Reply via email to