def __init__(self, app=None): self.app = app if app is not None: self.init_app(app) if app is not None and app.has_static_folder: self.library = Library(app.name, app.static_folder) get_library_registry().add(self.library) else: self.library = None self.resources = {}
def Fanstatic(app, publisher_signature=fanstatic.DEFAULT_SIGNATURE, **config): """Fanstatic WSGI framework component. :param app: The WSGI app to wrap with Fanstatic. :param publisher_signature: Optional argument to define the signature of the publisher in a URL. The default is ``fanstatic``. :param ``**config``: Optional keyword arguments. These are passed to :py:class:`NeededInclusions` when it is constructed. """ # Wrap the app inside the injector middleware, inside the # delegator middleware. injector = Injector( app, publisher_signature=publisher_signature, **config) publisher = Publisher(get_library_registry()) return Delegator( injector, publisher, publisher_signature=publisher_signature)
def test_library_registry(): set_auto_register_library(False) library_registry = get_library_registry() library_registry.load_items_from_entry_points() # Skip this test if the test fixtures has not been installed. pytest.importorskip('mypackage') # the 'foo' library has been placed here by the test buildout # fixtures/MyPackage by the entry point mechanism assert compat.dict_keys(library_registry) == ['foo'] # this is a real library, not an entry point assert isinstance(library_registry['foo'], Library) with pytest.raises(KeyError): library_registry['bar'] bar = Library('bar', '') library_registry.add(bar) assert library_registry['bar'] is bar assert sorted(compat.dict_keys(library_registry)) == ['bar', 'foo'] baz = Library('baz', '') library_registry[baz.name] = baz assert library_registry['baz'] is baz assert sorted(compat.iterkeys(library_registry)) == ['bar', 'baz', 'foo'] # MyPackage has been installed in development mode: assert library_registry['foo'].version is None
def replace_fanstatic_resource(config, to_remove, to_inject): """ Use this to remove 'to_remove' from fanstatic, and replace all it's dependencies with 'to_inject'. Example usage: Use a custom built twitter bootstrap css-file instead. from fanstatic import Resource from js.bootstrap import bootstrap_css #The default one my_custom = Resource(mylib, 'custom_bootstrap.css') def includeme(config): config.replace_fanstatic_resource(bootstrap_css, my_custom) """ from fanstatic import get_library_registry from fanstatic import Resource for item in (to_remove, to_inject): assert isinstance(item, Resource), "Must be a fanstatic.Resource instance" for lib in get_library_registry().values(): for resource in lib.known_resources.values(): if to_remove in resource.depends: resource.depends.remove(to_remove) resource.depends.add(to_inject) if to_remove != resource and to_remove in resource.resources: resource.resources.remove(to_remove) resource.resources.add(to_inject)
def __init__(self, handler, registry): self.handler = handler self.registry = registry self.config = filter_settings(registry.settings) self.publisher = Publisher(fanstatic.get_library_registry()) self.publisher_signature = self.config.get('publisher_signature', 'fanstatic') self.use_application_uri = self.config.get('use_application_uri') if self.config.get('use_thread_local'): self.needed_factory = fanstatic.init_needed self.del_needed = fanstatic.del_needed else: self.needed_factory = NeededResources self.del_needed = lambda: None self.prefix = '%s/%s/' % ( self.config.get('base_url', '').rstrip('/'), self.publisher_signature) injector_name = self.config.pop('injector', 'topbottom') injector_factory = fanstatic.registry.InjectorRegistry.instance().get(injector_name) self.injector = injector_factory(self.config) # override the class with one that gives warnings fanstatic.core.DummyNeededResources = DummyWarningNeededResources
def test_library_registry(): # Skip this test if the test fixtures has not been installed. pytest.importorskip('mypackage') library_registry = get_library_registry() # the 'foo' library has been placed here by the test buildout # fixtures/MyPackage by the entry point mechanism assert compat.dict_keys(library_registry) == ['foo'] # this is a real library, not an entry point assert isinstance(library_registry['foo'], Library) with pytest.raises(KeyError): library_registry['bar'] bar = Library('bar', '') library_registry.add(bar) assert library_registry['bar'] is bar assert sorted(compat.dict_keys(library_registry)) == ['bar', 'foo'] baz = Library('baz', '') library_registry[baz.name] = baz assert library_registry['baz'] is baz assert sorted(compat.iterkeys(library_registry)) == ['bar', 'baz', 'foo'] # MyPackage has been installed in development mode: assert library_registry['foo'].version is None
def __init__(self, handler, config): self.use_application_uri = asbool( config.pop('fanstatic.use_application_uri', False)) self.config = fanstatic_config(config) self.handler = handler self.publisher = Publisher(fanstatic.get_library_registry()) self.publisher_signature = self.config.get('publisher_signature') self.trigger = '/%s/' % self.publisher_signature
def __init__(self, app): self.publisher = Publisher(get_library_registry()) app.before_request(self.before_request) options = app.config.get("FANSTATIC_OPTIONS", {}) publisher_signature = options.get("publisher_signature", DEFAULT_SIGNATURE) app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {"/%s" % publisher_signature: self.publisher}) self.resource_sets = {}
def action_setup(_context): """Publish all fanstatic library entry points as resources. """ for library in fanstatic.get_library_registry().values(): factory = create_factory(library) adapts = (IBrowserRequest,) provides = Interface _context.action( discriminator = ('adapter', adapts, provides, library.name), callable = component.provideAdapter, args = (factory, adapts, provides, library.name))
def __call__(self): library = fanstatic.get_library_registry() publisher = fanstatic.Publisher(library) # skip first element in url before we # send it to original fanstatic publisher self.request.path_info_pop() response = publisher(self.request) self.request.response.status = response.status self.request.response.headerlist = response.headerlist self.request.response.app_iter = response.app_iter
def test_sort_registered_inclusion_renderers_in_order(): from fanstatic import get_library_registry foo = Library('foo', '') def render_unknown(url): return '<unknown href="%s"/>' % url register_inclusion_renderer('.later', render_unknown, 50) register_inclusion_renderer('.sooner', render_unknown, 5) register_inclusion_renderer('.between', render_unknown, 25) a = Resource(foo, 'nothing.later') b = Resource(foo, 'something.js') c = Resource(foo, 'something.css') d = Resource(foo, 'something.ico') e = Resource(foo, 'nothing.sooner') f = Resource(foo, 'nothing.between') get_library_registry().prepare() assert sort_resources([a, b, c, d]) == [c, b, d, a] assert sort_resources([a, b, c, d, e]) == [e, c, b, d, a] assert sort_resources([a, b, c, d, e, f]) == [e, c, b, f, d, a]
def __init__(self, handler, config): self.use_application_uri = asbool(config.pop("fanstatic.use_application_uri", False)) self.config = fanstatic_config(config) self.handler = handler self.publisher = Publisher(fanstatic.get_library_registry()) self.publisher_signature = self.config.get("publisher_signature") self.trigger = "/%s/" % self.publisher_signature injector_name = self.config.pop("injector") self.injector = None registry = fanstatic.registry if hasattr(registry, "InjectorRegistry"): injector_factory = registry.InjectorRegistry.instance().get(injector_name) self.injector = injector_factory(self.config)
def test_serf(): from fanstatic import get_library_registry lib_reg = get_library_registry() lib_reg.load_items_from_entry_points() pytest.importorskip('mypackage') # also test serf config d = {'resource': 'py:mypackage.style'} serf = make_serf({}, **d) serf = Fanstatic(serf, versioning=False) request = webob.Request.blank('/') response = request.get_response(serf) assert response.body == b'''\
def __init__(self, handler, config): self.use_application_uri = asbool( config.pop('fanstatic.use_application_uri', False)) self.config = fanstatic_config(config) self.handler = handler self.publisher = Publisher(fanstatic.get_library_registry()) self.publisher_signature = self.config.get('publisher_signature') self.trigger = '/%s/' % self.publisher_signature injector_name = self.config.pop('injector') self.injector = None registry = fanstatic.registry if hasattr(registry, 'InjectorRegistry'): injector_factory = registry.InjectorRegistry.instance().get( injector_name) self.injector = injector_factory(self.config)
def __init__(self, app): self.publisher = Publisher(get_library_registry()) app.before_request(self.before_request) teardown_request = getattr(app, 'teardown_request', app.after_request) teardown_request(self.teardown_request) options = app.config.get('FANSTATIC_OPTIONS', {}) publisher_signature = options.get('publisher_signature', DEFAULT_SIGNATURE) app.wsgi_app = DispatcherMiddleware(app.wsgi_app, { '/%s' % publisher_signature: self.publisher, }) self.resource_sets = {}
def __init__(self, handler, config): self.use_application_uri = asbool( config.pop('fanstatic.use_application_uri', False)) self.config = fanstatic_config(config) self.handler = handler self.publisher = Publisher(fanstatic.get_library_registry()) self.publisher_signature = self.config.get('publisher_signature') self.trigger = '/%s/' % self.publisher_signature injector_name = self.config.pop('injector', 'topbottom') injector_factory = fanstatic.registry.InjectorRegistry.instance().get(injector_name) if injector_factory is None: raise fanstatic.ConfigurationError( 'No injector found for name %s' % injector_name) self.injector = injector_factory(self.config)
def __init__(self, app): self.publisher = Publisher(get_library_registry()) app.before_request(self.before_request) teardown_request = getattr(app, 'teardown_request', app.after_request) teardown_request(self.teardown_request) options = app.config.get('FANSTATIC_OPTIONS', {}) publisher_signature = options.get('publisher_signature', DEFAULT_SIGNATURE) app.wsgi_app = DispatcherMiddleware( app.wsgi_app, { '/%s' % publisher_signature: self.publisher, }) self.resource_sets = {}
def test_do_add_library_after_register(): set_auto_register_library(False) library_registry = get_library_registry() bar = Library('bar', '') assert 'bar' not in library_registry library_registry.add(bar) assert 'bar' in library_registry library_registry.prepare() foo = Library('foo', '') with pytest.raises(ValueError): library_registry.add(foo)
def get_fanstatic_library(module_info, name=None, path=None): """Return the fanstatic library associated to the given module. """ if name is None: name = module_info.package_dotted_name if path is None: path = 'static' registry = fanstatic.get_library_registry() if name in registry: library = registry[name] else: library = fanstatic.Library( name, 'static', version=get_package_version(module_info)) # Fix the correct path library.path = module_info.getResourcePath(path) # Register the new library to fanstatic registry.add(library) return library
def test_console_script_collects_resources_from_package( monkeypatch, libraries): from fanstatic import get_library_registry lib_reg = get_library_registry() lib_reg.load_items_from_entry_points() mypackage = pytest.importorskip('mypackage') lib = Library('other', '') a = Resource(lib, 'a.js') lib_reg.add(lib) def log_compile(self, force=False): calls.append((self, force)) calls = [] monkeypatch.setattr(Resource, 'compile', log_compile) fanstatic.compiler._compile_resources('mypackage') assert len(calls) == 1 assert calls[0] == (mypackage.style, True)
def create_resource(path, lib_name, count, inline=False, supersedes=None): ''' create the fanstatic Resource ''' renderer = None kw = {} if not inline: # resource_name is name of the file without the .js/.css rel_path, filename = os.path.split(path) filename = os.path.join(rel_path, filename) path_min = min_path(os.path.join(resource_path, filename)) if os.path.exists(path_min): kw['minified'] = min_path(filename) if filename.endswith('.js'): renderer = core.render_js if path not in force_top: kw['bottom'] = True if filename.endswith('.css'): renderer = core.render_css core.set_resource_file_existence_checking(True) else: # This doesn't exist so stop fanstatic checking the filesystem if path not in force_top: kw['bottom'] = True core.set_resource_file_existence_checking(False) dependencies = [] if path in depends: for dependency in depends[path]: dependencies.append(get_resource(name, dependency)) if depend_base: dependencies.append(getattr(module, 'base/main')) if dependencies: kw['depends'] = dependencies if path in dont_bundle: kw['dont_bundle'] = True # IE conditionals condition = None other_browsers = False if path in IE_conditionals: other_browsers = ('others' in IE_conditionals[path]) condition = IE_conditionals[path][0] if inline or condition: kw['renderer'] = fanstatic_extensions.CkanCustomRenderer( condition=condition, script=inline, renderer=renderer, other_browsers=other_browsers) if supersedes: superseded_library, superseded_resource_path = supersedes for _library in get_library_registry().values(): if _library.name == superseded_library: kw['supersedes'] = [_library.known_resources[superseded_resource_path]] break resource = Resource(library, path, **kw) # Add our customised ordering if path in custom_render_order: resource.order = custom_render_order[path] resource.custom_order = count # Update the attributes of the minified version of the resource to # that of the parents as fanstatic does not pass these on. update_attributes = ['custom_order', 'order', 'bottom', 'depends', 'dont_bundle', 'renderer'] if 'minified' in resource.modes: min_res = resource.modes['minified'] for attribute in update_attributes: setattr(min_res, attribute, getattr(resource, attribute)) # add the resource to this module fanstatic_name = '%s/%s' % (lib_name, path) setattr(module, fanstatic_name, resource) return resource
def command(): args = docopt(__doc__, version='fanstat 1.2') if len(sys.argv) == 1: sys.exit(__doc__) if args["list"]: print "\nInstalled Python packages with Fanstatic libraries:\n" for ep in pkg_resources.iter_entry_points(group='fanstatic.libraries'): #print ep.name, ep.load() print ep.module_name if args["libs"]: print "\nResource libraries:\n" for k, v in get_library_registry().items(): print k, v.rootpath if args["cont"]: print "\nResources:\n" for k, v in get_library_registry().items(): print k, v.rootpath for r in v.known_resources: print r if args["html"]: print "\nHTML for inclusion on web page:" libnames = args["<lib>"] eps = [ ep for ep in pkg_resources.iter_entry_points( group='fanstatic.libraries') ] if libnames: selected = [ep for ep in eps if ep.name in libnames] else: selected = eps # generate list of <script> and <link> tags links = {"css": {}, "js": {}} for ep in selected: name = ep.name links["css"][name] = [] links["js"][name] = [] lib = ep.load() #module = ep.module_name, #root = lib.rootpath if args["--full"]: resources = [ r for r in lib.known_resources if ".min." not in r ] else: resources = [ r for r in lib.known_resources if ".min." in r or ".css" in r ] for res in resources: safename = name.replace("|", "_") if res.endswith(".js"): prefix = args["--prefix"] or "" link = '<script type="text/javascript" src="%s"></script>' % ( prefix + safename + "/" + res) links["js"][name].append(link) if res.endswith(".css"): prefix = args["--prefix"] or "" link = '<link type="text/css" href="%s" rel="stylesheet"/>' % ( prefix + safename + "/" + res) links["css"][name].append(link) # print CSS link tags if links["css"]: print "\n<!-- CSS styles -->" for libname in libnames: if links["css"][libname]: print "\n".join(links["css"][libname]) # print JS link tags if links["js"]: print "\n<!-- JavaScript scripts -->" for libname in libnames: if links["js"][libname]: print "\n".join(links["js"][libname]) if args["crossbar"]: print "\nCrossbar resources configuration:\n" paths = {} for ep in pkg_resources.iter_entry_points(group='fanstatic.libraries'): name = args["--prefix"] + ep.name if args["--prefix"] else ep.name lib = ep.load() paths[name.replace("|", "_")] = { "type": "static", "package": ep.module_name, "resource": lib.rootpath } print json.dumps(paths, indent=3, separators=(',', ': '))
def command(): args = docopt(__doc__, version='fanstat 1.2') if len(sys.argv) == 1: sys.exit(__doc__) if args["list"]: print "\nInstalled Python packages with Fanstatic libraries:\n" for ep in pkg_resources.iter_entry_points(group='fanstatic.libraries'): #print ep.name, ep.load() print ep.module_name if args["libs"]: print "\nResource libraries:\n" for k,v in get_library_registry().items(): print k, v.rootpath if args["cont"]: print "\nResources:\n" for k,v in get_library_registry().items(): print k, v.rootpath for r in v.known_resources: print r if args["html"]: print "\nHTML for inclusion on web page:" libnames = args["<lib>"] eps = [ep for ep in pkg_resources.iter_entry_points(group='fanstatic.libraries')] if libnames: selected = [ep for ep in eps if ep.name in libnames] else: selected = eps # generate list of <script> and <link> tags links = {"css":{}, "js":{}} for ep in selected: name = ep.name links["css"][name] = [] links["js"][name] = [] lib = ep.load() #module = ep.module_name, #root = lib.rootpath if args["--full"]: resources = [r for r in lib.known_resources if ".min." not in r] else: resources = [r for r in lib.known_resources if ".min." in r or ".css" in r] for res in resources: safename = name.replace("|","_") if res.endswith(".js"): prefix = args["--prefix"] or "" link = '<script type="text/javascript" src="%s"></script>' % (prefix + safename + "/" + res) links["js"][name].append(link) if res.endswith(".css"): prefix = args["--prefix"] or "" link = '<link type="text/css" href="%s" rel="stylesheet"/>' % (prefix + safename + "/" + res) links["css"][name].append(link) # print CSS link tags if links["css"]: print "\n<!-- CSS styles -->" for libname in libnames: if links["css"][libname]: print "\n".join(links["css"][libname]) # print JS link tags if links["js"]: print "\n<!-- JavaScript scripts -->" for libname in libnames: if links["js"][libname]: print "\n".join(links["js"][libname]) if args["crossbar"]: print "\nCrossbar resources configuration:\n" paths = {} for ep in pkg_resources.iter_entry_points(group='fanstatic.libraries'): name = args["--prefix"] + ep.name if args["--prefix"] else ep.name lib = ep.load() paths[name.replace("|","_")] = { "type":"static", "package": ep.module_name, "resource": lib.rootpath } print json.dumps(paths, indent=3, separators=(',', ': '))
def create_library(name, path, depend_base=True): ''' Creates a fanstatic library `name` with the contents of a directory `path` using resource.config if found.''' def get_resource(lib_name, resource_name): ''' Attempt to get the resource from the current lib or if not try assume it is a fully qualified resource name. ''' try: res = getattr(module, '%s/%s' % (lib_name, resource_name)) except AttributeError: res = getattr(module, '%s' % resource_name) return res def create_resource(path, lib_name, count, inline=False): ''' create the fanstatic Resource ''' renderer = None kw = {} if not inline: # resource_name is name of the file without the .js/.css rel_path, filename = os.path.split(path) filename = os.path.join(rel_path, filename) path_min = min_path(os.path.join(resource_path, filename)) if os.path.exists(path_min): kw['minified'] = min_path(filename) if filename.endswith('.js'): renderer = core.render_js if path not in force_top: kw['bottom'] = True if filename.endswith('.css'): renderer = core.render_css core.set_resource_file_existence_checking(True) else: # This doesn't exist so stop fanstatic checking the filesystem if path not in force_top: kw['bottom'] = True core.set_resource_file_existence_checking(False) dependencies = [] if path in depends: for dependency in depends[path]: dependencies.append(get_resource(name, dependency)) if depend_base: dependencies.append(getattr(module, 'base/main')) if dependencies: kw['depends'] = dependencies if path in dont_bundle: kw['dont_bundle'] = True # IE conditionals condition = None other_browsers = False if path in IE_conditionals: other_browsers = ('others' in IE_conditionals[path]) condition = IE_conditionals[path][0] if inline or condition: kw['renderer'] = fanstatic_extensions.CkanCustomRenderer( condition=condition, script=inline, renderer=renderer, other_browsers=other_browsers) resource = Resource(library, path, **kw) # Add our customised ordering if path in custom_render_order: resource.order = custom_render_order[path] resource.custom_order = count # Update the attributes of the minified version of the resource to # that of the parents as fanstatic does not pass these on. update_attributes = ['custom_order', 'order', 'bottom', 'depends', 'dont_bundle', 'renderer'] if 'minified' in resource.modes: min_res = resource.modes['minified'] for attribute in update_attributes: setattr(min_res, attribute, getattr(resource, attribute)) # add the resource to this module fanstatic_name = '%s/%s' % (lib_name, path) setattr(module, fanstatic_name, resource) return resource resource_path = os.path.join(os.path.dirname(__file__), path) library = Library(name, path) module = sys.modules[__name__] # config options order = [] dont_bundle = [] force_top = [] depends = {} groups = {} IE_conditionals = {} custom_render_order = {} inline_scripts = {} # parse the resource.config file if it exists config_path = os.path.join(resource_path, 'resource.config') if os.path.exists(config_path): config = ConfigParser.RawConfigParser() config.read(config_path) if config.has_option('main', 'order'): order = config.get('main', 'order').split() if config.has_option('main', 'dont_bundle'): dont_bundle = config.get('main', 'dont_bundle').split() if config.has_option('main', 'force_top'): force_top = config.get('main', 'force_top').split() if config.has_section('depends'): items = config.items('depends') depends = dict((n, v.split()) for (n, v) in items) if config.has_section('groups'): items = config.items('groups') groups = dict((n, v.split()) for (n, v) in items) if config.has_section('custom render order'): items = config.items('custom render order') custom_render_order = dict((n, int(v)) for (n, v) in items) if config.has_section('inline scripts'): items = config.items('inline scripts') inline_scripts = dict((n, v) for (n, v) in items) if config.has_section('IE conditional'): items = config.items('IE conditional') for (n, v) in items: files = v.split() for f in files: if f not in IE_conditionals: IE_conditionals[f] = [] IE_conditionals[f].append(n) # add dependencies for resources in groups for group in groups: if group in depends: for resource in groups[group]: if resource not in depends: depends[resource] = [] for dep in depends[group]: if dep not in depends[resource]: depends[resource].append(dep) # process each .js/.css file found resource_list = [] for dirname, dirnames, filenames in os.walk(resource_path): for f in filenames: rel_path = dirname[len(path):] if rel_path: rel_path = rel_path[1:] filepath = os.path.join(rel_path, f) filename_only, extension = os.path.splitext(f) if extension in ('.css', '.js') and ( not filename_only.endswith('.min')): resource_list.append(filepath) # if groups are defined make sure the order supplied there is honored for group in groups: for resource in groups[group]: if resource not in order: # make sure any dependencies are met when we get to creating # the resource if resource in depends: for dep in depends[resource]: if dep not in order: order.append(dep) order.append(resource) # add inline scripts for inline in inline_scripts: resource_list.append(inline) if inline not in custom_render_order: custom_render_order[inline] = 20 # order resource_list so that resources are created in the correct order for resource_name in reversed(order): if resource_name in resource_list: resource_list.remove(resource_name) resource_list.insert(0, resource_name) # create the resources and keep them ordered as we define them. count = 0 for resource_name in resource_list: if resource_name in inline_scripts: inline = inline_scripts[resource_name].strip() else: inline = None create_resource(resource_name, name, count, inline=inline) count += 1 # add groups for group_name in groups: members = [] for member in groups[group_name]: fanstatic_name = '%s/%s' % (name, member) members.append(getattr(module, fanstatic_name)) group = Group(members) fanstatic_name = '%s/%s' % (name, group_name) setattr(module, fanstatic_name, group) # finally add the library to this module setattr(module, name, library) # add to fanstatic registry = get_library_registry() registry.add(library)
def pytest_runtest_setup(item): set_resource_file_existence_checking(False) set_auto_register_library(True) # Reset the registry before each test. get_library_registry().clear() thread_local_needed_data.__dict__.pop(NEEDED, None)
def make_publisher(app, global_config, publisher_signature=fanstatic.DEFAULT_SIGNATURE): publisher = Publisher(fanstatic.get_library_registry()) return Delegator(app, publisher, publisher_signature=publisher_signature)
def __init__(self, handler, registry): self.config = fanstatic_config(registry.settings) self.handler = handler self.publisher = Publisher(fanstatic.get_library_registry()) self.publisher_signature = self.config.get('publisher_signature') self.trigger = '/%s/' % self.publisher_signature
def resource_exists(self, filename): library = fanstatic.get_library_registry()[self.resource_library] return os.path.exists(os.path.join(library.path, filename))
def make_publisher(global_config): registry = fanstatic.get_library_registry() return Publisher(registry)
def create_library(name, path, depend_base=True): ''' Creates a fanstatic library `name` with the contents of a directory `path` using resource.config if found.''' def get_resource(lib_name, resource_name): ''' Attempt to get the resource from the current lib or if not try assume it is a fully qualified resource name. ''' try: res = getattr(module, '%s/%s' % (lib_name, resource_name)) except AttributeError: res = getattr(module, '%s' % resource_name) return res def create_resource(path, lib_name, count, inline=False): ''' create the fanstatic Resource ''' renderer = None kw = {} if not inline: # resource_name is name of the file without the .js/.css rel_path, filename = os.path.split(path) filename = os.path.join(rel_path, filename) path_min = min_path(os.path.join(resource_path, filename)) if os.path.exists(path_min): kw['minified'] = min_path(filename) if filename.endswith('.js'): renderer = core.render_js if path not in force_top: kw['bottom'] = True if filename.endswith('.css'): renderer = core.render_css core.set_resource_file_existence_checking(True) else: # This doesn't exist so stop fanstatic checking the filesystem if path not in force_top: kw['bottom'] = True core.set_resource_file_existence_checking(False) dependencies = [] if path in depends: for dependency in depends[path]: dependencies.append(get_resource(name, dependency)) if depend_base: dependencies.append(getattr(module, 'base/main')) if dependencies: kw['depends'] = dependencies if path in dont_bundle: kw['dont_bundle'] = True # IE conditionals condition = None other_browsers = False if path in IE_conditionals: other_browsers = ('others' in IE_conditionals[path]) condition = IE_conditionals[path][0] if inline or condition: kw['renderer'] = fanstatic_extensions.CkanCustomRenderer( condition=condition, script=inline, renderer=renderer, other_browsers=other_browsers) resource = Resource(library, path, **kw) # Add our customised ordering if path in custom_render_order: resource.order = custom_render_order[path] resource.custom_order = count # Update the attributes of the minified version of the resource to # that of the parents as fanstatic does not pass these on. update_attributes = [ 'custom_order', 'order', 'bottom', 'depends', 'dont_bundle', 'renderer' ] if 'minified' in resource.modes: min_res = resource.modes['minified'] for attribute in update_attributes: setattr(min_res, attribute, getattr(resource, attribute)) # add the resource to this module fanstatic_name = '%s/%s' % (lib_name, path) #log.debug('create resource %s' % fanstatic_name) setattr(module, fanstatic_name, resource) return resource resource_path = os.path.join(os.path.dirname(__file__), path) library = Library(name, path) module = sys.modules[__name__] # config options order = [] dont_bundle = [] force_top = [] depends = {} groups = {} IE_conditionals = {} custom_render_order = {} inline_scripts = {} # parse the resource.config file if it exists config_path = os.path.join(resource_path, 'resource.config') if os.path.exists(config_path): config = ConfigParser.RawConfigParser() config.read(config_path) if config.has_option('main', 'order'): order = config.get('main', 'order').split() if config.has_option('main', 'dont_bundle'): dont_bundle = config.get('main', 'dont_bundle').split() if config.has_option('main', 'force_top'): force_top = config.get('main', 'force_top').split() if config.has_section('depends'): items = config.items('depends') depends = dict((n, v.split()) for (n, v) in items) if config.has_section('groups'): items = config.items('groups') groups = dict((n, v.split()) for (n, v) in items) if config.has_section('custom render order'): items = config.items('custom render order') custom_render_order = dict((n, int(v)) for (n, v) in items) if config.has_section('inline scripts'): items = config.items('inline scripts') inline_scripts = dict((n, v) for (n, v) in items) if config.has_section('IE conditional'): items = config.items('IE conditional') for (n, v) in items: files = v.split() for f in files: if f not in IE_conditionals: IE_conditionals[f] = [] IE_conditionals[f].append(n) # add dependencies for resources in groups for group in groups: if group in depends: for resource in groups[group]: if resource not in depends: depends[resource] = [] for dep in depends[group]: if dep not in depends[resource]: depends[resource].append(dep) # process each .js/.css file found resource_list = [] for dirname, dirnames, filenames in os.walk(resource_path): for f in filenames: rel_path = dirname[len(path):] if rel_path: rel_path = rel_path[1:] filepath = os.path.join(rel_path, f) filename_only, extension = os.path.splitext(f) if extension in ('.css', '.js') and (not filename_only.endswith('.min')): resource_list.append(filepath) # if groups are defined make sure the order supplied there is honored for group in groups: for resource in groups[group]: if resource not in order: # make sure any dependencies are met when we get to creating # the resource if resource in depends: for dep in depends[resource]: if dep not in order: order.append(dep) order.append(resource) # add inline scripts for inline in inline_scripts: resource_list.append(inline) if inline not in custom_render_order: custom_render_order[inline] = 20 # order resource_list so that resources are created in the correct order for resource_name in reversed(order): if resource_name in resource_list: resource_list.remove(resource_name) resource_list.insert(0, resource_name) # create the resources and keep them ordered as we define them. count = 0 for resource_name in resource_list: if resource_name in inline_scripts: inline = inline_scripts[resource_name].strip() else: inline = None create_resource(resource_name, name, count, inline=inline) count += 1 # add groups for group_name in groups: members = [] for member in groups[group_name]: fanstatic_name = '%s/%s' % (name, member) members.append(getattr(module, fanstatic_name)) group = Group(members) fanstatic_name = '%s/%s' % (name, group_name) setattr(module, fanstatic_name, group) # finally add the library to this module setattr(module, name, library) # add to fanstatic registry = get_library_registry() registry.add(library)