def init(confdict): """ Initializes this module according to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`hosts` A list of Varnish hosts passed to :func:`parse_host_port <score.init.parse_host_port>` and :func:`parse_list <score.init.parse_list>`. :confkey:`soft` :faint:`[default=true]` Whether to purge :term:`soft <soft purge>` or :term:`hard <hard purge>`. :confkey:`timeout` :faint:`[default=5s]` The timeout for sending requests to a Varnish host passed to :func:`parse_time_interval <score.init.parse_time_interval>`. :confkey:`header.domain` :faint:`[default=X-Purge-Domain]` The name of the header used for purging a domain. :confkey:`header.path` :faint:`[default=X-Purge-Path]` The name of the header used for purging a path. :confkey:`header.soft` :faint:`[default=X-Purge-Soft]` The name of the header used for triggering a :term:`soft purge`. """ conf = dict(defaults.items()) conf.update(confdict) hosts = [parse_host_port(host) for host in parse_list(conf['hosts'])] soft = parse_bool(conf['soft']) timeout = parse_time_interval(conf['timeout']) header_mapping = extract_conf(conf, 'header.') return ConfiguredVarnishModule(hosts, soft, timeout, header_mapping)
def init(confdict, webassets, tpl, http): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`rootdir` :confdefault:`None` Denotes the root folder containing all css files. Will fall back to a sub-folder of the folder in :mod:`score.tpl`'s configuration, as described in :func:`score.tpl.init`. :confkey:`cachedir` :confdefault:`None` A dedicated cache folder for this module. It is generally sufficient to provide a ``cachedir`` for :mod:`score.tpl`, as this module will use a sub-folder of that by default. :confkey:`combine` :confdefault:`False` Whether css files should be delivered as a single file. If this value is `true` (as defined by :func:`score.init.parse_bool`), the default url will point to the combined css file. :confkey:`minify` :confdefault:`False` Whether css assets should be minified. :confkey:`group.*` Keys starting with ``group.*`` will register :term:`asset groups <asset group>`. The following configuration will create a :term:`virtual asset` called ``meal`` which has the combined content of the assets 'bacon.css' and 'spam.css':: group.meal = bacon.css spam.css Note that groups defined this way *must* reference real assets, i.e. at the point this value is interpreted, there are no virtual assets yet! If you need to add virtual assets to a group, you will need to create the asset group after all required virtual assets have been registered. """ conf = dict(defaults.items()) conf.update(confdict) if not conf['rootdir']: conf['rootdir'] = os.path.join(tpl.rootdir, 'css') conf['minify'] = parse_bool(conf['minify']) conf['combine'] = parse_bool(conf['combine']) if not conf['cachedir'] and tpl.cachedir: conf['cachedir'] = os.path.join(tpl.cachedir, 'css') if conf['cachedir']: init_cache_folder(conf, 'cachedir', autopurge=True) else: warnings.warn('No cachedir configured, SCSS rendering will not work.') cssconf = ConfiguredCssModule( webassets, tpl, http, conf['rootdir'], conf['cachedir'], conf['combine'], conf['minify']) for name, pathlist in extract_conf(conf, 'group.').items(): paths = parse_list(pathlist) _create_group(cssconf, webassets, name + '.css', paths) return cssconf
def init(confdict): """ Initializes this module acoording to the :ref:`SCORE module initialization guidelines <module_initialization>` with the following configuration keys: """ conf = defaults.copy() conf.update(confdict) servers = [] loop = asyncio.new_event_loop() server_names = [c.split('.')[0] for c in extract_conf(conf, 'server.')] for name in server_names: server_conf = extract_conf(conf, 'server.%s.' % name) name = server_conf.get('name', name) host, port = parse_host_port(server_conf['monitor']) servers.append( SocketConnector(name, loop, host, port)) return ConfiguredCruiseModule(loop, servers)
def init(confdict, webassets=None): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`rootdir` :faint:`[default=None]` Denotes the root folder containing all templates. When a new format is created via :meth:`.Renderer.register_format`, it will have a sub-folder of this folder as its default root (unless, of course, the `rootdir` parameter of that function is provided). If this value is omitted, all calls to :meth:`.Renderer.register_format` must provide a format-specific root folder. :confkey:`cachedir` :faint:`[default=None]` A cache folder that will be used to cache rendered templates. Will fall back to a sub-folder (called ``tpl``) of the cachedir in the *webassets*, if one was provided. Although this module will work without a cache folder, it is highly recommended that it is either initialized with a ``cachedir`` or a *webassets* with a valid ``cachedir``, even if the value points to the system's temporary folder. :confkey:`default_format` :faint:`[default=None]` The default format of files where the :term:`template format` could not be determined automatically. This must be the name of another, registered format. :confkey:`engine.*` All keys starting with ``engine.`` will be registered as engines. For example, if the key ``engine.php`` is provided, the engine will be instantiated via :func:`score.init.init_object` and registered for the extension ``php``. """ conf = dict(defaults.items()) conf.update(confdict) if not conf['cachedir'] and webassets and webassets.cachedir: conf['cachedir'] = os.path.join(webassets.cachedir, 'tpl') if conf['cachedir']: init_cache_folder(conf, 'cachedir', autopurge=True) if conf['rootdir']: if not os.path.isdir(conf['rootdir']): import score.tpl raise ConfigurationError(score.tpl, 'Given rootdir is not a folder') renderer = Renderer(conf['rootdir'], conf['cachedir'], conf['default_format']) extensions = set() for key in extract_conf(conf, 'engine.'): extensions.add(key.split('.', 1)[0]) for ext in extensions: engine = init_object(conf, 'engine.' + ext) renderer.register_engine(ext, engine) return ConfiguredTplModule(renderer, conf['rootdir'], conf['cachedir'], conf['default_format'])
def init(confdict, ctx=None): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`args.hosts` A list of hosts (as read by :func:`score.init.parse_list`) to pass to the :class:`Elasticsearch <elasticsearch.Elasticsearch>` constructor. :confkey:`args.*` Any other arguments to be passed to the :class:`Elasticsearch <elasticsearch.Elasticsearch>` constructor. :confkey:`index` :confdefault:`score` The index to use in all operations. :confkey:`keep_source` :confdefault:`False` Whether the `_source` field should be enabled. The default is `False`, since the canonical representation of objects should be in a database. :confkey:`ctx.member` :confdefault:`es` The name of the :term:`context member`, that should be registered with the configured :mod:`score.ctx` module (if there is one). The default value allows one to conveniently query the index: >>> response = ctx.es.client.search(body={"query": {"match_all": {}}}) >>> for hit in response['hits']['hits']: ... print(hit['_source']['title']) :confkey:`ctx.extensions` Additional extension classes for the context proxy. """ conf = defaults.copy() conf.update(confdict) connect_kwargs = parse_connect_conf(extract_conf(conf, 'args.')) if 'index' not in conf: conf['index'] = 'score' keep_source = parse_bool(conf['keep_source']) ctx_extensions = [DslExtension] for path in parse_list(conf['ctx.extensions']): class_ = parse_dotted_path(path) if not issubclass(class_, CtxProxy): raise InitializationError( 'score.es7', 'Ctx extensions classes must be sub-classes of CtxProxy') ctx_extensions.append(class_) es_conf = ConfiguredEs7Module(connect_kwargs, conf['index'], keep_source, ctx_extensions) if ctx and conf['ctx.member'] not in (None, 'None'): ctx.register(conf['ctx.member'], es_conf.get_ctx_proxy) return es_conf
def init(confdict): """ Initializes this module according to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`container` The cache container configuration. A container defines a name, a backend and optionally a generator and an expire. The configuration key for a container starts with ``container`` followed by the name and the configuration keys for the container. For example, the following configuration:: container.greeter.backend = score.kvcache.backend.FileCache container.greeter.backend.path = /tmp/greeter.sqlite3 container.greeter.generator = dotted.path.to.greeting_generator container.greeter.expire = 1m The Backend config will be passed to :func:`score.init.init_object`. Have a look at the configurable backend's constructor parameters for further information about the backend's configurable keys. To make life easier for a huge set of container configurations, we serve the possibility to configure backend aliases that will replace the container's backend config if the name matches. For example:: backend.example_filecache = score.kvcache.backend.FileCache backend.example_filecache.path = /tmp/filecache.sqlite3 container.greeter.backend = example_filecache container.greeter.generator = dotted.path.to.greeting_generator container.greeter.expire = 1m container.counter.backend = example_filecache container.counter.generator = dotted.path.to.counting_generator container.counter.expire = 30 seconds """ containers = {} for container_conf in extract_conf(confdict, 'container.'): if not container_conf.endswith('.backend'): continue backend_key = 'container.%s' % container_conf backend_val = confdict[backend_key] if backend_val in extract_conf(confdict, 'backend.'): alias_conf = extract_conf(confdict, 'backend.%s' % backend_val) for k, v in alias_conf.items(): confdict.update({'%s%s' % (backend_key, k): v}) container_name = container_conf[:-len('.backend')] backend = parse_object(confdict, backend_key) generator_key = 'container.%s.generator' % container_name generator = None if generator_key in confdict: generator = parse_dotted_path(confdict[generator_key]) expire_key = 'container.%s.expire' % container_name expire = None if expire_key in confdict: expire = parse_time_interval(confdict[expire_key]) containers[container_name] = CacheContainer(container_name, backend, generator=generator, expire=expire) return ConfiguredKvCacheModule(containers)
def init(confdict, db, ctx=None): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`args.hosts` A list of hosts (as read by :func:`score.init.parse_list`) to pass to the :class:`Elasticsearch <elasticsearch.Elasticsearch>` constructor. :confkey:`args.*` Any other arguments to be passed to the :class:`Elasticsearch <elasticsearch.Elasticsearch>` constructor. :confkey:`index` :confdefault:`score` The index to use in all operations. :confkey:`ctx.member` :confdefault:`es` The name of the :term:`context member`, that should be registered with the configured :mod:`score.ctx` module (if there is one). The default value allows one to conveniently query the index: >>> for knight in ctx.es.query(User, 'name:sir*') ... print(knight.name) """ conf = defaults.copy() conf.update(confdict) kwargs = extract_conf(confdict, 'args.') if 'hosts' in kwargs: kwargs['hosts'] = parse_list(kwargs['hosts']) if 'verify_certs' in kwargs: kwargs['verify_certs'] = parse_bool(kwargs['verify_certs']) if 'use_ssl' in kwargs: kwargs['use_ssl'] = parse_bool(kwargs['use_ssl']) es = Elasticsearch(**kwargs) if 'index' not in confdict: confdict['index'] = 'score' es_conf = ConfiguredEsModule(db, es, confdict['index']) to_insert = [] to_delete = [] @event.listens_for(db.Session, 'before_flush') def before_flush(session, flush_context, instances): """ Stores the list of new and altered objects in ``to_insert``, and deleted objects in ``to_delete``. The actual storing can only be done *after* the flush operation (in ``after_flush``, below), since new objects don't have an id at this point. But we cannot move the whole logic into the ``after_flush``, since we might miss the optional *instances* argument to this function. """ nonlocal to_insert, to_delete to_insert = [] to_delete = [] for obj in session.new: if not instances or obj in instances: if es_conf.get_es_class(obj) is not None: to_insert.append(obj) for obj in session.dirty: if not session.is_modified(obj): # might actually be unaltered, see docs of Session.dirty: # http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.dirty continue if not instances or obj in instances: if es_conf.get_es_class(obj) is not None: to_insert.append(obj) for obj in session.deleted: if not instances or obj in instances: if es_conf.get_es_class(obj) is not None: to_delete.append(obj) @event.listens_for(db.Session, 'after_flush') def after_flush(session, flush_context): for obj in to_insert: es_conf.insert(obj) for obj in to_delete: es_conf.delete(obj) if ctx and conf['ctx.member'] not in (None, 'None'): ctx.register(conf['ctx.member'], lambda ctx: CtxProxy(es_conf, ctx)) return es_conf
def init(confdict, ctx, db=None): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`router` Path to the :class:`RouteConfiguration` containing the list of routes to compile. :confkey:`preroutes` :confdefault:`list()` List of :term:`preroute` functions to call before invoking the actual route. See :ref:`http_routing` for details. :confkey:`handler.*` Keys starting with "``handler.``" are interpreted as :ref:`error handlers <http_error_handler>`. :confkey:`debug` :confdefault:`False` Setting this to `True` will enable the `werkzeug debugger`_ for your application. :confkey:`urlbase` :confdefault:`None` This will be the prefix for all URLs generated by the module. The module will create relative URLs by default (i.e. `/Sir%20Lancelot`), but you can make it create absolute URLs by default by paassing this configuration value. If you configure this to be 'http://example.net/', your URL would be 'http://example.net/Sir%20Lancelot'. Note that you can always decide, whether a *certain* URL should be absolute or relative, by passing the appropriate argument to :meth:`ConfiguredHttpModule.url`. :confkey:`ctx.member.url` :confdefault:`url` The name of the :term:`context member` function for generating URLs. :confkey:`serve.ip` :confdefault:`0.0.0.0` This will be the ip address your HTTP server will bind_ to, when using :mod:`score.serve` to serve your application. :confkey:`serve.port` :confdefault:`8080` This will be the port of your HTTP server, when using :mod:`score.serve` to serve your application. :confkey:`serve.threaded` :confdefault:`False` Setting this to `True` will make your HTTP server threaded, which should increase its performance. Note that your application will need to be thread-safe_, if you want to enable this feature. .. _werkzeug debugger: http://werkzeug.pocoo.org/docs/0.11/debug/#using-the-debugger .. _bind: http://www.xeams.com/bindtoaddress.htm .. _thread-safe: https://en.wikipedia.org/wiki/Thread_safety """ conf = dict(defaults.items()) conf.update(confdict) if 'router' not in conf: import score.http raise ConfigurationError(score.http, 'No router provided') router = parse_dotted_path(conf['router']) preroutes = list(map(parse_dotted_path, parse_list(conf['preroutes']))) error_handlers = {} exception_handlers = {} for error, handler in extract_conf(conf, 'handler.').items(): if re.match('\d(\d\d|XX)', error): error_handlers[error] = parse_dotted_path(handler) else: error = parse_dotted_path(error) exception_handlers[error] = handler debug = parse_bool(conf['debug']) if not conf['urlbase']: conf['urlbase'] = '' http = ConfiguredHttpModule( ctx, db, router, preroutes, error_handlers, exception_handlers, debug, conf['urlbase'], conf['serve.ip'], int(conf['serve.port']), parse_bool(conf['serve.threaded'])) def constructor(ctx): def url(*args, **kwargs): return http.url(ctx, *args, **kwargs) return url ctx.register(conf['ctx.member.url'], constructor) return http
def init(confdict, ctx=None): """ Initializes this module acoording to the :ref:`SCORE module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`ctx.member.url` :confdefault:`fs` The name of the :term:`context member`, that should be registered with the configured :mod:`score.ctx` module (if there is one). The default value allows you to always access configured file systems within a :class:`score.ctx.Context` like the following: >>> ctx.fs['my_configured_fs'] :confkey:`path.*` Configuration keys like `path.foo` are file system definitions that must contain a valid :ref:`pyfilesystem URL <pyfilesystem:fs-urls>`. These values automatically :meth:`register <ConfiguredPyfilesystemModule.register_path>` paths during initialization. The following example is for registering a memory file system called `foo`: .. code-block:: ini path.foo = mem:// The only customization is a *scope* parameter, which can also define the :term:`scope <pyfilesystem scope>` of a file system. Valid values for this parameter are ``global`` (the default) and ``ctx``. The same filesystem as above with a scope bound to a context would look like this: .. code-block:: ini path.foo = mem://?scope=ctx """ conf = defaults.copy() conf.update(confdict) fsconf = ConfiguredPyfilesystemModule() for name, url in extract_conf(conf, 'path.').items(): scope = 'global' if '://' in url: url = urllib.parse.urlsplit(url) query = [] for key, value in urllib.parse.parse_qsl(url.query): if key == 'scope': scope = Scope(value) else: query.append((key, value)) url = [*url] url[3] = query url = urllib.parse.urlunsplit(url) if '://' not in url: # the URL probably does not contain a netloc part and urlunsplit # generates something like 'mem:', which is actually valid. # pyfilesystem, on the other hand, interprets this as a path on # the local filesystem and tries to open it with OSFS. # the fix is simple: append two slashes to the first colon url = url.replace(':', '://', 1) if scope == Scope.CONTEXT and not ctx: import score.pyfilesystem raise InitializationError( score.pyfilesystem, 'Cannot register object with scope=ctx ' 'without a configured ctx module') try: fsconf.register_path(name, url, scope=scope) except Exception as e: import score.pyfilesystem raise InitializationError(score.pyfilesystem, str(e)) from e if ctx and conf['ctx.member'].lower() != 'none': ctx.register(conf['ctx.member'], fsconf._ctx_constructor) return fsconf