Exemple #1
0
    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)
Exemple #3
0
    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")
Exemple #5
0
    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)
Exemple #6
0
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)
Exemple #7
0
    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)
Exemple #8
0
    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)
Exemple #9
0
    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})
Exemple #10
0
    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)
Exemple #12
0
    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)
Exemple #13
0
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()
Exemple #14
0
    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)
Exemple #15
0
# 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'])
Exemple #18
0
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()
Exemple #19
0
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)
Exemple #20
0
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()