def _check_expired(self): """Checks each ExtensionManager for expired extension state. When the list of extensions on an ExtensionManager changes, or when the configuration of an extension changes, any other threads/processes holding onto extensions and configuration will go stale. This function will check each of those to see if they need to re-load their state. This is meant to be called before every HTTP request. """ for extension_manager in get_extension_managers(): # We're going to check the expiration, and then only lock if it's # expired. Following that, we'll check again. # # We do this in order to prevent locking unnecessarily, which could # impact performance or cause a problem if a thread is stuck. # # We're checking the expiration twice to prevent every blocked # thread from making its own attempt to reload the extensions once # the first thread holding the lock finishes the reload. if extension_manager.is_expired(): with self._lock: # Check again, since another thread may have already # reloaded. if extension_manager.is_expired(): extension_manager.load(full_reload=True)
def find(self, path, all=False): """Finds the real path to a static file, given a static path. The path must start with "ext/<extension_id>/". The files within will map to files within the extension's "static" directory. """ parts = path.split('/', 2) if len(parts) < 3 or parts[0] != 'ext': return [] extension_id, path = parts[1:] for extension_manager in get_extension_managers(): extension = extension_manager.get_enabled_extension(extension_id) if extension: match = self._find_in_extension(extension, path) if match: # The static file support allows for the same name # across many locations, but as we involve extension IDs, # we know we'll only have one. if all: return [match] else: return match break return []
def _get_extension_bundles(extension_manager_key, context, bundle_attr, renderer): """Returns media bundles that can be rendered on the current page. This will look through all enabled extensions and find any with static media bundles that should be included on the current page, as indicated by the context. All bundles marked "default" will be included, as will any with an ``apply_to`` field containing a URL name matching the current page. """ request = context['request'] if not getattr(request, 'resolver_match', None): return requested_url_name = request.resolver_match.url_name for manager in get_extension_managers(): if manager.key != extension_manager_key: continue for extension in manager.get_enabled_extensions(): bundles = getattr(extension, bundle_attr, {}) for bundle_name, bundle in six.iteritems(bundles): if (bundle_name == 'default' or requested_url_name in bundle.get('apply_to', [])): yield renderer(context, extension, bundle_name) break
def init_js_extensions(context, extension_manager_key): """Initializes all JavaScript extensions. Each extension's required JavaScript files will be loaded in the page, and their JavaScript-side Extension subclasses will be instantiated. """ url_name = context['request'].resolver_match.url_name for manager in get_extension_managers(): if manager.key == extension_manager_key: js_extensions = [] for extension in manager.get_enabled_extensions(): for js_extension_cls in extension.js_extensions: js_extension = js_extension_cls(extension) if js_extension.applies_to(url_name): js_extensions.append(js_extension) return { 'url_name': url_name, 'js_extensions': js_extensions, } return {}
def _get_extension_bundles(extension_manager_key, context, bundle_attr, default_bundles, renderer): """Yield media bundles that can be rendered on the current page. This will look through all enabled extensions and find any with static media bundles that should be included on the current page, as indicated by the context. All bundles marked "default" will be included, as will any with an ``apply_to`` field containing a URL name matching the current page. If a bundle has an ``include_bundles`` key, the referenced bundles will also be outputted. Note that this does not check for duplicates, and is not recursive. Args: extension_manager_key (unicode): The key for the extension manager for these bundles. context (django.template.Context): The template context. bundle_attr (unicode): The attribute name for the bundle on the extension class. default_bundles (unicode): A string containing a comma-separated list of bundles to always include. renderer (callable): The renderer function to call for each applicable bundle. Yields: tuple of (unicode or django.utils.safetext.SafeString): The HTML used to include the bundled content. """ request = context['request'] if not getattr(request, 'resolver_match', None): return requested_url_name = request.resolver_match.url_name default_bundles = set(default_bundles.split(',')) for manager in get_extension_managers(): if manager.key != extension_manager_key: continue for extension in manager.get_enabled_extensions(): bundles = getattr(extension, bundle_attr, {}) for bundle_name, bundle in six.iteritems(bundles): if (bundle_name in default_bundles or requested_url_name in bundle.get('apply_to', [])): for include_bundle in bundle.get('include_bundles', []): yield renderer(context, extension, include_bundle) yield (renderer(context, extension, bundle_name), ) break
def _get_extension_bundles(extension_manager_key, context, bundle_attr, default_bundles, renderer): """Yield media bundles that can be rendered on the current page. This will look through all enabled extensions and find any with static media bundles that should be included on the current page, as indicated by the context. All bundles marked "default" will be included, as will any with an ``apply_to`` field containing a URL name matching the current page. If a bundle has an ``include_bundles`` key, the referenced bundles will also be outputted. Note that this does not check for duplicates, and is not recursive. Args: extension_manager_key (unicode): The key for the extension manager for these bundles. context (django.template.Context): The template context. bundle_attr (unicode): The attribute name for the bundle on the extension class. default_bundles (unicode): A string containing a comma-separated list of bundles to always include. renderer (callable): The renderer function to call for each applicable bundle. Yields: django.utils.safetext.SafeString: The HTML used to include the bundled content. """ request = context['request'] if not getattr(request, 'resolver_match', None): return requested_url_name = request.resolver_match.url_name default_bundles = set(default_bundles.split(',')) for manager in get_extension_managers(): if manager.key != extension_manager_key: continue for extension in manager.get_enabled_extensions(): bundles = getattr(extension, bundle_attr, {}) for bundle_name, bundle in six.iteritems(bundles): if (bundle_name in default_bundles or requested_url_name in bundle.get('apply_to', [])): for include_bundle in bundle.get('include_bundles', []): yield renderer(context, extension, include_bundle) yield renderer(context, extension, bundle_name) break
def list(self, ignore_patterns): """Lists static files within all enabled extensions.""" for extension_manager in get_extension_managers(): for extension in extension_manager.get_enabled_extensions(): storage = self._get_storage(extension) if storage and storage.exists(''): for path in get_files(storage, ignore_patterns): yield path, storage
def load_extensions_js(context, extension_manager_key): """Loads all default JavaScript bundles from all enabled extensions.""" for manager in get_extension_managers(): if manager.key == extension_manager_key: return ''.join([ _render_js_bundle(context, extension, 'default') for extension in manager.get_enabled_extensions() if 'default' in extension.js_bundles ]) return ''
def get_extension_manager(self): """Return the extension manager used for the tests. Subclasses may want to override this to pick a specific extension manager, if the project uses more than one. The default behavior is to return the first registered extension manager. Returns: djblets.extensions.manager.ExtensionManager: The extension manager used for tests. """ return get_extension_managers()[0]
def _check_expired(self): """Checks each ExtensionManager for expired extension state. When the list of extensions on an ExtensionManager changes, or when the configuration of an extension changes, any other threads/processes holding onto extensions and configuration will go stale. This function will check each of those to see if they need to re-load their state. This is meant to be called before every HTTP request. """ for extension_manager in get_extension_managers(): if extension_manager.is_expired(): extension_manager.load(full_reload=True)
def load_template_source(template_name, template_dirs=None): """Loads templates from enabled extensions.""" if manager: resource = "templates/" + template_name for extmgr in get_extension_managers(): for ext in extmgr.get_enabled_extensions(): package = ext.info.app_name try: return (manager.resource_string(package, resource), 'extension:%s:%s ' % (package, resource)) except Exception: pass raise TemplateDoesNotExist(template_name)
def init_js_extensions(context, extension_manager_key): """Initializes all JavaScript extensions. Each extension's required JavaScript files will be loaded in the page, and their JavaScript-side Extension subclasses will be instantiated. """ for manager in get_extension_managers(): if manager.key == extension_manager_key: return { 'extensions': [ extension for extension in manager.get_enabled_extensions() if extension.js_model_class ], } return {}
def init_js_extensions(context, extension_manager_key): """Initializes all JavaScript extensions. Each extension's required JavaScript files will be loaded in the page, and their JavaScript-side Extension subclasses will be instantiated. """ request = context['request'] url_name = request.resolver_match.url_name for manager in get_extension_managers(): if manager.key == extension_manager_key: js_extensions = [] for extension in manager.get_enabled_extensions(): for js_extension_cls in extension.js_extensions: js_extension = js_extension_cls(extension) if js_extension.applies_to(url_name): js_extensions.append(js_extension) js_extension_items = [] for js_extension in js_extensions: arg_spec = inspect.getargspec(js_extension.get_model_data) if arg_spec.keywords is None: warnings.warn( '%s.get_model_data will need to take keyword ' 'arguments. The old function signature is deprecated.' % js_extension_cls.__name__) model_data = js_extension.get_model_data() else: model_data = js_extension.get_model_data(request=request) js_extension_items.append({ 'js_extension': js_extension, 'model_data': model_data, }) return { 'url_name': url_name, 'js_extension_items': js_extension_items, } return {}
def _middleware_funcs(self, func_name, reverse=False): """Generator yielding the given middleware function for all extensions. If an extension's middleware does not implement 'func_name', it is skipped. """ middleware = [] for mgr in get_extension_managers(): middleware.extend(mgr.middleware) if reverse: middleware.reverse() for m in middleware: f = getattr(m, func_name, None) if f: yield f
def handle(self, *args, **options): managers = get_extension_managers() force_install = options['force'] if options['extension_id']: extensions = [ self._find_extension(options['extension_id'], managers) ] else: extensions = chain( (extension, manager) for manager in managers for extension in manager.get_enabled_extensions()) for extension, manager in extensions: try: manager.install_extension_media(extension, force_install) except InstallExtensionError as e: raise CommandError('Could not install extension media: %s' % e)
def handle(self, *args, **options): managers = get_extension_managers() force_install = options['force'] if options['extension_id']: extensions = [self._find_extension(options['extension_id'], managers)] else: extensions = chain( (extension, manager) for manager in managers for extension in manager.get_enabled_extensions() ) for extension, manager in extensions: try: manager.install_extension_media(extension, force_install) except InstallExtensionError as e: raise CommandError('Could not install extension media: %s' % e)
def get_extension_class(self): """Retrieves the python object for the extensions class.""" if not hasattr(self, '_extension_class'): cls = None try: # Import the function here to avoid a mutual # dependency. from djblets.extensions.manager import get_extension_managers for manager in get_extension_managers(): try: cls = manager.get_installed_extension(self.class_name) break except InvalidExtensionError: continue except: return None self._extension_class = cls return self._extension_class
def __init__(self, *args, **kwargs): """Initialize the scope dictionary. This adds signal handlers to ensure the dictionary stays up to date when extensions are initialized and uninitialized. Args: *args (tuple): Positional arguments to pass to the parent class. **kwargs (dict): Keyword arguments to pass to the the parent class. """ super(ExtensionEnabledWebAPIScopeDictionary, self).__init__(*args, **kwargs) extension_enabled.connect(self._on_extension_enabled) extension_disabled.connect(self._on_extension_disabled) for manager in get_extension_managers(): for extension in manager.get_enabled_extensions(): self._on_extension_enabled(extension=extension)
def test_added_to_extension_managers(self): """Testing ExtensionManager registration""" self.manager = TestExtensionManager([], '') self.assertIn(self.manager, get_extension_managers())
def test_added_to_extension_managers(self): """Testing ExtensionManager registration""" self.assertIn(self.manager, get_extension_managers())