def test_use_redis(self): app_config = self.basic_valid_app_config.copy() config = BlueberryPyConfiguration(app_config=app_config) self.assertFalse(config.use_redis) app_config["controllers"][''].update({"/": {"tools.sessions.storage_type": "redis"}}) config = BlueberryPyConfiguration(app_config=app_config) self.assertTrue(config.use_redis)
def test_controllers_config(self): app_config = {"global": {}} self.assertRaisesRegexp(BlueberryPyConfigurationError, "You must declare at least one controller\.", callable_obj=BlueberryPyConfiguration, app_config=app_config) app_config = {"controllers": {}} self.assertRaisesRegexp(BlueberryPyConfigurationError, "You must declare at least one controller\.", callable_obj=BlueberryPyConfiguration, app_config=app_config) app_config = {"controllers": {'api': {'tools.json_in.on': True}}} self.assertRaisesRegexp(BlueberryPyConfigurationError, "You must define a controller in the \[controllers\]\[api\] section\.", callable_obj=BlueberryPyConfiguration, app_config=app_config) class Root(object): def index(self): return "hello world!" app_config = {"controllers": {"": {"controller": Root}}} with warnings.catch_warnings(record=True): warnings.simplefilter("error") with self.assertRaisesUserWarningRegex( "Controller '' has no exposed method\."): BlueberryPyConfiguration(app_config=app_config) class Root(object): def index(self): return "hello world!" index.exposed = True app_config = {"controllers": {"": {"controller": Root}}} config = BlueberryPyConfiguration(app_config=app_config) rest_controller = cherrypy.dispatch.RoutesDispatcher() app_config = {"controllers": {"/api": {"controller": rest_controller}}} with warnings.catch_warnings(record=True): warnings.simplefilter("error") with self.assertRaisesUserWarningRegex( "Controller '/api' has no connected routes\."): BlueberryPyConfiguration(app_config=app_config) class DummyRestController(object): def dummy(self, **kwargs): return "hello world!" rest_controller.connect("dummy", "/dummy", DummyRestController, action="dummy") app_config = {"controllers": {"/api": {"controller": rest_controller}}} config = BlueberryPyConfiguration(app_config=app_config)
def test_sqlalchemy_config(self): app_config = self.basic_valid_app_config.copy() app_config.update({"global": {"engine.sqlalchemy.on": True}, "sqlalchemy_engine": {"url": "sqlite://"}}) config = BlueberryPyConfiguration(app_config=app_config) self.assertEqual(config.sqlalchemy_config, {"sqlalchemy_engine": {"url": "sqlite://"}}) app_config = self.basic_valid_app_config.copy() app_config.update({"global": {"engine.sqlalchemy.on": True}, "sqlalchemy_engine_Model1": {"url": "sqlite://"}, "sqlalchemy_engine_Model2": {"url": "sqlite://"}}) config = BlueberryPyConfiguration(app_config=app_config) self.assertEqual(config.sqlalchemy_config, {"sqlalchemy_engine_Model1": {"url": "sqlite://"}, "sqlalchemy_engine_Model2": {"url": "sqlite://"}})
def test_config_file_paths(self): config = BlueberryPyConfiguration(config_dir="/tmp") config_file_paths = config.config_file_paths self.assertEqual(len(config_file_paths), 3) self.assertEqual(config_file_paths[0], "/tmp/dev/app.yml") self.assertEqual(config_file_paths[1], "/tmp/dev/bundles.yml") self.assertEqual(config_file_paths[2], "/tmp/dev/logging.yml")
def test_use_email(self): app_config = self.basic_valid_app_config.copy() app_config.update({"email": {}}) with warnings.catch_warnings(record=True): warnings.simplefilter("error") assertRaisesRegex = (getattr(self, "assertRaisesRegex", None) or getattr(self, "assertRaisesRegexp")) assertRaisesRegex(UserWarning, "BlueberryPy email configuration is empty.", callable_obj=BlueberryPyConfiguration, app_config=app_config) app_config.update({"email": {"debug": 1}}) with warnings.catch_warnings(record=True): warnings.simplefilter("error") assertRaisesRegex = (getattr(self, "assertRaisesRegex", None) or getattr(self, "assertRaisesRegexp")) assertRaisesRegex(UserWarning, "Unknown key 'debug' found for \[email\]. Did you mean 'debuglevel'?", callable_obj=BlueberryPyConfiguration, app_config=app_config) app_config.update({"email": {"host": "localhost", "port": 1025}}) config = BlueberryPyConfiguration(app_config=app_config) self.assertTrue(config.use_email)
def console(**kwargs): """ An REPL fully configured for experimentation. usage: blueberrypy console [options] options: -e ENVIRONMENT, --environment=ENVIRONMENT apply the given config environment -h, --help show this help message and exit """ banner = """ ***************************************************************************** * If the configuration file you specified contains a [sqlalchemy_engine*] * * section, a default SQLAlchemy engine and session should have been created * * for you automatically already. * ***************************************************************************** """ environment = kwargs.get("environment") config_dir = kwargs.get("config_dir") environment and cherrypy.config.update({"environment": environment}) Console( BlueberryPyConfiguration(config_dir=config_dir, environment=environment)).interact(banner)
def test_use_jinja2(self): app_config = self.basic_valid_app_config.copy() app_config.update({"jinja2": {}}) self.assertRaisesRegexp(BlueberryPyNotConfiguredError, "Jinja2 configuration not found.", callable_obj=BlueberryPyConfiguration, app_config=app_config) app_config.update({"jinja2": {"loader": DictLoader({})}}) config = BlueberryPyConfiguration(app_config=app_config) self.assertTrue(config.use_jinja2)
def test_use_sqlalchemy(self): app_config = self.basic_valid_app_config.copy() app_config.update({"global": {"engine.sqlalchemy.on": True}}) self.assertRaisesRegexp(BlueberryPyNotConfiguredError, "SQLAlchemy configuration not found.", callable_obj=BlueberryPyConfiguration, app_config=app_config) app_config.update({"global": {"engine.sqlalchemy.on": True}, "sqlalchemy_engine": {"url": "sqlite://"}}) config = BlueberryPyConfiguration(app_config=app_config) self.assertTrue(config.use_sqlalchemy) app_config.update({"global": {"engine.sqlalchemy.on": True}, "sqlalchemy_engine_Model": {"url": "sqlite://"}}) config = BlueberryPyConfiguration(app_config=app_config) self.assertTrue(config.use_sqlalchemy)
def test_jinja2_config(self): app_config = self.basic_valid_app_config.copy() dict_loader = DictLoader({}) app_config.update({"jinja2": {"loader": dict_loader, "use_webassets": True}}) webassets_env = Environment("/tmp", "/") webassets_env.register("js", "dummy.js", "dummy2.js", output="dummy.js") config = BlueberryPyConfiguration(app_config=app_config, webassets_env=webassets_env) self.assertEqual(config.jinja2_config, {"loader": dict_loader})
def test_config_file_paths(self): # stub out os.path.exists import os.path old_exists = os.path.exists def proxied_exists(path): if path == "/tmp/dev/app.yml": return True elif path == "/tmp/dev/bundles.yml": return True elif path == "/tmp/dev/logging.yml": return True return old_exists(path) os.path.exists = proxied_exists old_open = builtins.open # stub out open class FakeFile(StringIO): def __enter__(self): return self def __exit__(self, exc_type=None, exc_value=None, traceback=None): return False def proxied_open(filename, mode='r', buffering=1): if filename == "/tmp/dev/app.yml": return FakeFile() elif filename == "/tmp/dev/bundles.yml": return FakeFile(textwrap.dedent(""" directory: /tmp url: / """)) elif filename == "/tmp/dev/logging.yml": return FakeFile() else: return old_open(filename, mode, buffering) builtins.open = proxied_open # stub out validate() old_validate = BlueberryPyConfiguration.validate BlueberryPyConfiguration.validate = lambda self: None try: config = BlueberryPyConfiguration(config_dir="/tmp") config_file_paths = config.config_file_paths self.assertEqual(len(config_file_paths), 3) self.assertEqual(config_file_paths[0], "/tmp/dev/app.yml") self.assertEqual(config_file_paths[1], "/tmp/dev/bundles.yml") self.assertEqual(config_file_paths[2], "/tmp/dev/logging.yml") finally: BlueberryPyConfiguration.validate = old_validate os.path.exists = old_exists builtins.open = old_open
def test_use_email(self): app_config = self.basic_valid_app_config.copy() app_config.update({"email": {}}) with warnings.catch_warnings(record=True): warnings.simplefilter("error") with self.assertRaisesUserWarningRegex( "BlueberryPy email configuration is empty."): BlueberryPyConfiguration(app_config=app_config) app_config.update({"email": {"debug": 1}}) with warnings.catch_warnings(record=True): warnings.simplefilter("error") with self.assertRaisesUserWarningRegex( "Unknown key 'debug' found for \[email\]. " "Did you mean 'debuglevel'?"): BlueberryPyConfiguration(app_config=app_config) app_config.update({"email": {"host": "localhost", "port": 1025}}) config = BlueberryPyConfiguration(app_config=app_config) self.assertTrue(config.use_email)
def setup_server(): config = BlueberryPyConfiguration(app_config=testconfig) if config.use_email and config.email_config: email.configure(config.email_config) if config.use_logging and config.logging_config: cherrypy.engine.logging = LoggingPlugin(cherrypy.engine, config=config.logging_config) if config.use_redis: cherrypy.lib.sessions.RedisSession = RedisSession if config.use_sqlalchemy: cherrypy.engine.sqlalchemy = SQLAlchemyPlugin(cherrypy.engine, config=config.sqlalchemy_config) cherrypy.tools.orm_session = SQLAlchemySessionTool() if config.use_jinja2: if config.webassets_env: configure_jinja2(assets_env=config.webassets_env, **config.jinja2_config) else: configure_jinja2(**config.jinja2_config) cherrypy.config.update(config.app_config) # mount the controllers for script_name, section in config.controllers_config.viewitems(): section = section.copy() controller = section.pop("controller") if isinstance(controller, cherrypy.dispatch.RoutesDispatcher): routes_config = {'/': {"request.dispatch": controller}} for path in section.viewkeys(): if path.strip() == '/': routes_config['/'].update(section['/']) else: routes_config[path] = section[path].copy() app_config = config.app_config.copy() app_config.pop("controllers") routes_config.update(app_config) cherrypy.tree.mount(None, script_name=script_name, config=routes_config) else: app_config = config.app_config.copy() app_config.pop("controllers") controller_config = section.copy() controller_config.update(app_config) cherrypy.tree.mount(controller(), script_name=script_name, config=controller_config)
def bundle(**kwargs): """ Webassets bundle management. usage: blueberrypy bundle [options] Before you can use this command to bundle up your Web assets, you should have created either a project skeleton using the 'create' command or provided a configuration directory using the global option -c --config_dir. options: -h, --help show this help message and exit -C ENV_VAR_NAME, --env-var ENV_VAR_NAME add the given config from environment variable name [default: BLUEBERRYPY_CONFIG] -b, --build build the asset bundles -w, --watch automatically rebuild the asset bundles upon changes in the static directory -c, --clean delete the generated asset bundles """ config = BlueberryPyConfiguration(config_dir=kwargs.get('config_dir'), env_var_name=kwargs.get('env_var')) assets_env = config.webassets_env if not assets_env: raise BlueberryPyNotConfiguredError("Webassets configuration not found.") from webassets.script import CommandLineEnvironment assets_cli = CommandLineEnvironment(assets_env, logger) if kwargs.get("build"): try: assets_cli.build() except AttributeError: assets_cli.rebuild() elif kwargs.get("watch"): assets_cli.watch() elif kwargs.get("clean"): assets_cli.clean()
def test_use_webassets(self): app_config = self.basic_valid_app_config.copy() app_config.update({"jinja2": {"use_webassets": True, "loader": DictLoader({})}}) self.assertRaisesRegexp(BlueberryPyNotConfiguredError, "Webassets configuration not found.", callable_obj=BlueberryPyConfiguration, app_config=app_config) webassets_env = Environment("/tmp", "/") self.assertRaisesRegexp(BlueberryPyNotConfiguredError, "No bundles found in webassets env.", callable_obj=BlueberryPyConfiguration, app_config=app_config, webassets_env=webassets_env) webassets_env = Environment("/tmp", "/") webassets_env.register("js", "dummy.js", "dummy2.js", output="dummy.js") config = BlueberryPyConfiguration(app_config=app_config, webassets_env=webassets_env) self.assertTrue(config.use_webassets)
# for 'autogenerate' support from GDGUkraine.model import metadata as target_metadata environment = 'dev' # If environment name was passed via command line argument # e.g. -x environment=dev, let's use its value: try: environment = [ x.split('=')[1] for x in context.config.cmd_opts.x if x.split('=')[0] == 'environment' ][0] except: pass conf = BlueberryPyConfiguration(environment=environment) app_config = conf.app_config sqlalchemy_config = conf.sqlalchemy_config # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config global_config = app_config.get('global', {}) alembic_config = global_config.get(config.config_ini_section) alembic_excludes = global_config.get('alembic.exclude', {}) exclude_tables = alembic_excludes.get('tables', {}) exclude_indexes = alembic_excludes.get('indexes', {}) exclude_fkeys = alembic_excludes.get('foreign_keys', {})
def test_validate(self): with self.assertRaisesRegexp( BlueberryPyNotConfiguredError, "BlueberryPy application configuration not found."): BlueberryPyConfiguration()
def test_config_overrides_file(self): config = BlueberryPyConfiguration(config_dir="/tmp") self.assertEqual('new value1', config.app_config['value1']) self.assertEqual('value2', config.app_config['value2'])
def serve(**kwargs): """ Spawn a new running Cherrypy process usage: blubeberry serve [options] options: -h, --help show this help message and exit -b BINDING, --bind BINDING the address and port to bind to. [default: 127.0.0.1:8080] -e ENVIRONMENT, --environment ENVIRONMENT apply the given config environment -C ENV_VAR_NAME, --env-var ENV_VAR_NAME add the given config from environment variable name [default: BLUEBERRYPY_CONFIG] -f start a fastcgi server instead of the default HTTP server -s start a scgi server instead of the default HTTP server -d, --daemonize run the server as a daemon. [default: False] -p, --drop-privilege drop privilege to separately specified umask, uid and gid. [default: False] -P PIDFILE, --pidfile PIDFILE store the process id in the given file -u UID, --uid UID setuid to uid [default: www] -g GID, --gid GID setgid to gid [default: www] -m UMASK, --umask UMASK set umask [default: 022] """ config = BlueberryPyConfiguration(config_dir=kwargs.get('config_dir'), env_var_name=kwargs.get('env_var')) cpengine = cherrypy.engine cpenviron = kwargs.get("environment") if cpenviron: config = BlueberryPyConfiguration(config_dir=kwargs.get('config_dir'), env_var_name=kwargs.get('env_var'), environment=cpenviron) cherrypy.config.update({"environment": cpenviron}) if config.use_email and config.email_config: from blueberrypy import email email.configure(config.email_config) if config.use_logging and config.logging_config: from blueberrypy.plugins import LoggingPlugin cpengine.logging = LoggingPlugin(cpengine, config=config.logging_config) if config.use_redis: from blueberrypy.session import RedisSession cherrypy.lib.sessions.RedisSession = RedisSession if config.use_sqlalchemy: from blueberrypy.plugins import SQLAlchemyPlugin cpengine.sqlalchemy = SQLAlchemyPlugin(cpengine, config=config.sqlalchemy_config) from blueberrypy.tools import SQLAlchemySessionTool cherrypy.tools.orm_session = SQLAlchemySessionTool() if config.use_jinja2: if config.webassets_env: configure_jinja2(assets_env=config.webassets_env, **config.jinja2_config) else: configure_jinja2(**config.jinja2_config) # update global config first, so subsequent command line options can # override the settings in the config files cherrypy.config.update(config.app_config) if kwargs.get("bind"): address, port = kwargs.get("bind").strip().split(":") cherrypy.server.socket_host = address cherrypy.server.socket_port = int(port) if kwargs.get("daemonize"): cherrypy.config.update({'log.screen': False}) Daemonizer(cpengine).subscribe() if kwargs.get("drop_privilege"): cherrypy.config.update({'engine.autoreload_on': False}) DropPrivileges(cpengine, umask=int(kwargs.get("umask")), uid=kwargs.get("uid") or "www", gid=kwargs.get("gid") or "www").subscribe() if kwargs.get("pidfile"): PIDFile(cpengine, kwargs.get("pidfile")).subscribe() fastcgi, scgi = kwargs.get("fastcgi"), kwargs.get("scgi") if fastcgi and scgi: cherrypy.log.error("You may only specify one of the fastcgi and " "scgi options.", 'ENGINE') sys.exit(1) elif fastcgi or scgi: # Turn off autoreload when using *cgi. cherrypy.config.update({'engine.autoreload_on': False}) # Turn off the default HTTP server (which is subscribed by default). cherrypy.server.unsubscribe() addr = cherrypy.server.bind_addr if fastcgi: f = servers.FlupFCGIServer(application=cherrypy.tree, bindAddress=addr) elif scgi: f = servers.FlupSCGIServer(application=cherrypy.tree, bindAddress=addr) s = servers.ServerPlugin(cpengine, httpserver=f, bind_addr=addr) s.subscribe() if hasattr(cpengine, 'signal_handler'): cpengine.signal_handler.subscribe() # for win32 only if hasattr(cpengine, "console_control_handler"): cpengine.console_control_handler.subscribe() # mount the controllers for script_name, section in config.controllers_config.viewitems(): section = section.copy() controller = section.pop("controller") if isinstance(controller, cherrypy.dispatch.RoutesDispatcher): routes_config = {'/': {"request.dispatch": controller}} for path in section.viewkeys(): if path.strip() == '/': routes_config['/'].update(section['/']) else: routes_config[path] = section[path].copy() app_config = config.app_config.copy() app_config.pop("controllers") routes_config.update(app_config) cherrypy.tree.mount(None, script_name=script_name, config=routes_config) else: app_config = config.app_config.copy() app_config.pop("controllers") controller_config = section.copy() controller_config.update(app_config) cherrypy.tree.mount(controller(), script_name=script_name, config=controller_config) # Add the blueberrypy config files into CP's autoreload monitor # Jinja2 templates are monitored by Jinja2 itself and will autoreload if # needed if config.config_file_paths: for path in config.config_file_paths: cpengine.autoreload.files.add(path) try: cpengine.start() except: sys.exit(1) else: cpengine.block()
def console(**kwargs): """ An REPL fully configured for experimentation. usage: blueberrypy console [options] options: -e ENVIRONMENT, --environment=ENVIRONMENT apply the given config environment -C ENV_VAR_NAME, --env-var ENV_VAR_NAME add the given config from environment variable name [default: BLUEBERRYPY_CONFIG] --ipython use IPython shell instead of Python one -h, --help show this help message and exit """ banner = """ ***************************************************************************** * If the configuration file you specified contains a [sqlalchemy_engine*] * * section, a default SQLAlchemy engine and session should have been created * * for you automatically already. * ***************************************************************************** """ environment = kwargs.get("environment") config_dir = kwargs.get("config_dir") environment and cherrypy.config.update({"environment": environment}) configuration = BlueberryPyConfiguration( config_dir=config_dir, environment=environment, env_var_name=kwargs.get('env_var'), ) use_ipython = kwargs.get("ipython", False) package_name = shell.get_package_name(configuration) if use_ipython: try: from IPython.terminal.interactiveshell import TerminalInteractiveShell except ImportError as e: print(e) print("""Cannot import iPython. Did you install it?""") return try: app_package = import_module(package_name) except ImportError as e: print(e) app_package = None repl = TerminalInteractiveShell( user_ns=shell.get_user_namespace(configuration), user_module=app_package, display_completions='multicolumn', # oldstyle is 'readlinelike' mouse_support=True, space_for_menu=10, # reserve N lines for the completion menu ) repl.show_banner(banner) repl.mainloop() else: try: import readline except ImportError as e: print(e) else: import rlcompleter sys.ps1 = "[%s]>>> " % package_name sys.ps2 = "[%s]... " % package_name ns = shell.get_user_namespace(configuration, include_pkg=True) repl = InteractiveConsole(locals=ns) repl.prompt = package_name repl.interact(banner)
import functools from blueberrypy.config import BlueberryPyConfiguration from sqlalchemy import engine_from_config from sqlalchemy.orm import sessionmaker, scoped_session from testconfig import config as testconfig from GDGUkraine.model import metadata config = BlueberryPyConfiguration( app_config=testconfig, # Don't update config from env var! This may lead to losing the DB!!111 env_var_name=None, ) engine = engine_from_config(config.sqlalchemy_config['sqlalchemy_engine'], '') Session = scoped_session(sessionmaker(engine)) metadata.bind = engine def orm_session(func): def _orm_session(*args, **kwargs): session = Session() try: return func(*args, **kwargs) except: raise finally: session.close()