def init(confdict, ctx=None): """ Initializes this module acoording to the :ref:`SCORE module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`backend` :confdefault:`python` The shell backend to use. You can use either of the shells prvided by this module ("python", "ipython" and "bpython") or a string, that will be resolved using :func:`score.init.parse_dotted_path`. :confkey:`backend.autoinstall` :confdefault:`True` Whether the given *backend* should be installed automatically, if it was not found. :confkey:`callbacks` A :func:`list <score.init.parse_list>` of :func:`dotted python paths <score.init.parse_dotted_path>` to functions that will be called before the shell is spawned. Every callback will receive a `dict` representing the variables that will be available in the shell. The callbacks are free to add further variables to this list. """ conf = defaults.copy() conf.update(confdict) shell_cls = Shell.get(conf['backend']) if not shell_cls: shell_cls = parse_dotted_path(conf['backend']) backend = shell_cls(conf['backend.autoinstall']) callbacks = [] for path in parse_list(conf['callbacks']): callback = parse_dotted_path(path) if not callable(callback): raise ConfigurationError('Given callback not callable: %s' % path) callbacks.append(callback) return ConfiguredShellModule(ctx, backend, callbacks)
def init(confdict): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`autoreload` :confdefault:`False` When set to :func:`true <score.init.parse_bool>`, the server will automatically reload whenever it detects a change in one of the python files, that are in use. :confkey:`modules` The :func:`list <score.init.parse_list>` of modules to serve. This need to be a list of module aliases, i.e. the same name, with which you configured the module with ("score.http" becomes "http" if not specified otherwise.) """ conf = defaults.copy() conf.update(confdict) modules = parse_list(conf['modules']) if not modules: import score.serve raise InitializationError(score.serve, 'No modules configured') autoreload = parse_bool(conf['autoreload']) return ConfiguredServeModule(conf['conf'], modules, autoreload)
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): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`autoreload` :confdefault:`False` When set to :func:`true <score.init.parse_bool>`, the server will automatically reload whenever it detects a change in one of the python files, that are in use. :confkey:`modules` The :func:`list <score.init.parse_list>` of modules to serve. This need to be a list of module aliases, i.e. the same name, with which you configured the module with ("score.http" becomes "http" if not specified otherwise.) """ conf = defaults.copy() conf.update(confdict) modules = parse_list(conf['modules']) if not modules: import score.serve raise InitializationError(score.serve, 'No modules configured') autoreload = parse_bool(conf['autoreload']) monitor_host_port = None if conf['monitor']: monitor_host_port = parse_host_port(conf['monitor']) return ConfiguredServeModule(conf['conf'], modules, autoreload, monitor_host_port)
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, ctx, http, jslib=None): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`endpoints` :confdefault:`list()` A :func:`list <score.init.parse_list>` of :func:`dotted paths <score.init.parse_dotted_path>` pointing to any amount of :class:`Endpoints <.Endpoint>`. The registered functions of these Endpoints will be available in javascript. :confkey:`expose` :confdefault:`False` Whether security critical data may be exposed through the API. This value should be left at its default value in production, but may be switched to `True` during development to receive Exceptions and stacktraces in the browser console. :confkey:`jslib.require` :confdefault:`score.jsapi` The name of the require.js module to create the virtual javascript with. When left at its default value, the resulting javascript can be included like the following: .. code-block:: javascript require(['score.jsapi'], function(Api) { var api = new Api(); // ... use api here ... }); """ conf = dict(defaults.items()) conf.update(confdict) endpoints = list(map(parse_dotted_path, parse_list(conf['endpoints']))) expose = parse_bool(conf['expose']) jsapi = ConfiguredJsapiModule(ctx, http, jslib, expose, conf['jslib.require']) for endpoint in endpoints: jsapi.add_endpoint(endpoint) if jslib: import score.jsapi version = score.jsapi.__version__ dependencies = { conf['jslib.require'] + '/excformat': version, 'bluebird': '3.X.X', 'score.init': '0.X.X', 'score.oop': '0.4.X' } @jslib.virtlib(conf['jslib.require'] + '/excformat', version, {}) def exc2json(ctx): return gen_excformat_js(ctx) @jslib.virtlib(conf['jslib.require'], version, dependencies) def api(ctx): return jsapi.generate_js() return jsapi
def _collect_services(self): self._services = OrderedDict() score = init_from_file(self.conf.conf) if self._changedetector: for file in parse_list(score.conf['score.init']['_files']): self._changedetector.observe(file) for desc in self.conf.modules: for name, worker in self._iter_workers(score, desc): self._services[name] = Service(name, worker)
def parse_connect_conf(conf): conf = conf.copy() if 'hosts' in conf: conf['hosts'] = parse_list(conf['hosts']) if 'verify_certs' in conf: conf['verify_certs'] = parse_bool(conf['verify_certs']) if 'use_ssl' in conf: conf['use_ssl'] = parse_bool(conf['use_ssl']) if 'timeout' in conf: conf['timeout'] = parse_time_interval(conf['timeout']) return conf
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, tpl): """ Initializes this module acoording to the :ref:`SCORE module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`cachedir` :confdefault:`None` A cache folder to use for storing parsed templates. Highly recommended. """ conf = defaults.copy() conf.update(confdict) return ConfiguredJinja2Module(tpl, conf['extension'], conf['cachedir'], parse_list(conf['filters']))
def init(confdict, tpl, webassets): """ Initializes this module acoording to the :ref:`SCORE module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`config_file` :confdefault:`None` An optional javascript file containing the `requirejs configuration`_. This file should only contain the configuration object itself, but the object does not have to adhere to a strict JSON syntax and may contain javascript functions. The following is a perfectly valid example for the referenced file's content: .. code-block:: javascript { map: { 'some/newmodule': { 'foo': 'foo1.2' }, }, shim: { 'foo': { deps: ['bar'], exports: 'Foo', init: function (bar) { return this.Foo.noConflict(); } } } } .. _requirejs configuration: http://requirejs.org/docs/api.html#config :confkey:`passthrough_extensions` :confdefault:`[]` A list of additional file extensions that this module is allowed to pass to browsers. If you want to pass mustache_ templates to the browser, for example, you must provide the ``mustache`` extension in this list. .. _mustache: http://mustache.github.io/ :confkey:`path.nodejs` :confdefault:`nodejs` The path to the nodejs_ executable. This value is only relevant if :term:`asset bundling <asset bundle>` is enabled in :mod:`score.webassets`. .. _nodejs: https://nodejs.org/en/ """ conf = defaults.copy() conf.update(confdict) return ConfiguredRequirejsModule( tpl, webassets, conf['config_file'], conf['path.nodejs'], parse_list(conf['passthrough_extensions']))
def init(confdict, webassets=None): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`backends` List of score module aliases that should be used as backends to the templating. """ conf = dict(defaults.items()) conf.update(confdict) backends = parse_list(conf['backends']) assert backends, 'No backends configured' return ConfiguredTplFallbackModule(backends)
def init_score(clickctx): conf = parse_config_file(clickctx.obj['conf'].path) try: modules = parse_list(conf['score.init']['modules']) except KeyError: modules = [] modules.append('score.serve') if 'score.init' not in conf: conf['score.init'] = {} conf['score.init']['modules'] = modules if 'serve' not in conf: conf['serve'] = {} if 'conf' not in conf['serve']: conf['serve']['conf'] = clickctx.obj['conf'].path return score_init(conf)
def _collect_services(self): self._services = OrderedDict() score = init_from_file(self.conf.conf) if self._changedetector: for file in parse_list(score.conf['score.init']['_files']): self._changedetector.observe(file) for mod in self.conf.modules: workers = score._modules[mod].score_serve_workers() if isinstance(workers, list): for i, worker in enumerate(workers): name = '%s/%d' % (mod, i) self._services[name] = Service(name, worker) elif isinstance(workers, dict): for name, worker in workers.items(): name = '%s/%s' % (mod, name) self._services[name] = Service(name, worker)
def init(confdict, jsapi): """ Initializes this module according to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: """ conf = dict(defaults.items()) conf.update(confdict) sources = list(map(parse_dotted_path, parse_list(conf['sources']))) dynq = ConfiguredDynqModule(jsapi, sources, conf['jsapi.name']) if jsapi.jslib: import score.dynq @jsapi.jslib.virtlib(conf['jslib.require'], score.dynq.__version__, ['score.init', 'score.oop', 'score.dynq']) def api(ctx): return dynq.generate_js() return dynq
def init(confdict, ctx): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`ruleset` :confdefault:`RuleSet()` A dotted path to an instance of :class:`RuleSet` in your project. This module will be initialized without any rules, if this configuration key is omitted, resulting in denial of every operation. :confkey:`authenticators` :confdefault:`list()` List of :class:`Authenticators` capable of determining the current actor. :confkey:`ctx.member` :confdefault:`actor` The :term:`context member` under which the current actor should be made available. Leaving this at its default will allow you to access the current actor as the following: >>> ctx.actor """ conf = defaults.copy() conf.update(confdict) if conf['ruleset'] in (None, 'None'): ruleset = RuleSet() else: ruleset = parse_dotted_path(conf['ruleset']) if 'authenticator' in conf: assert not conf['authenticators'] conf['authenticators'] = [conf['authenticator']] del conf['authenticator'] auth = ConfiguredAuthModule(ruleset, conf['ctx.member']) authenticator = NullAuthenticator() for line in reversed(parse_list(conf['authenticators'])): authenticator = parse_call(line, (auth, authenticator)) auth.authenticator = authenticator _register_ctx_actor(conf, ctx, auth) _register_ctx_permits(conf, ctx, auth) return auth
def init(confdict, ctx): """ Initializes this module acoording to :ref:`our module initialization guidelines <module_initialization>` with the following configuration keys: :confkey:`ruleset` :faint:`[default=RuleSet()]` A dotted path to an instance of :class:`RuleSet` in your project. This module will be initialized without any rules, if this configuration key is omitted, resulting in denial of every operation. :confkey:`authenticators` :faint:`[default=list()]` List of :class:`Authenticators` capable of determining the current actor. :confkey:`ctx.member` :faint:`[default=actor]` The :term:`context member` under which the current actor should be made available. Leaving this at its default will allow you to access the current actor as the following: >>> ctx.actor """ conf = defaults.copy() conf.update(confdict) if conf['ruleset'] in (None, 'None'): ruleset = RuleSet() else: ruleset = parse_dotted_path(conf['ruleset']) if 'authenticator' in conf: assert not conf['authenticators'] conf['authenticators'] = [conf['authenticator']] del conf['authenticator'] auth = ConfiguredAuthModule(ruleset, conf['ctx.member']) authenticator = NullAuthenticator() for line in reversed(parse_list(conf['authenticators'])): authenticator = parse_call(line, (auth, authenticator)) auth.authenticator = authenticator _register_ctx_actor(conf, ctx, auth) _register_ctx_permits(conf, ctx, auth) return auth
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