def test_dummy_unfinded(caplog, temp_builds_dir, fixtures_settings, reset_syspath): """ Unfindable module from sample dummy package """ basedir = os.path.join(fixtures_settings.fixtures_path, "dummy_package") module_name = "idontexist" setup_project(basedir, "dummy_value", set_envvar=False) with pytest.raises(SystemExit): import_settings_module(module_name, basedir=basedir) assert caplog.record_tuples == [ ( "optimus", logging.INFO, "Register project base directory: {}".format(basedir), ), ("optimus", logging.INFO, 'Loading "{}" module'.format(module_name)), ( "optimus", logging.CRITICAL, "Unable to find settings module: {}".format(module_name), ), ] # Cleanup sys.path for next tests reset_syspath(basedir)
def test_dummy_invalid_import(caplog, temp_builds_dir, fixtures_settings, reset_syspath): """ Import invalid (bad import) module from sample dummy package """ basedir = os.path.join(fixtures_settings.fixtures_path, "dummy_package") module_name = "invalid_import" setup_project(basedir, "dummy_value", set_envvar=False) with pytest.raises(ImportError): import_settings_module(module_name, basedir=basedir) assert caplog.record_tuples == [ ( "optimus", logging.INFO, "Register project base directory: {}".format(basedir), ), ("optimus", logging.INFO, 'Loading "{}" module'.format(module_name)), ( "optimus", logging.CRITICAL, "Unable to load settings module, it probably have errors: {}". format(module_name), ), ] # Cleanup sys.path for next tests reset_syspath(basedir)
def build_command(context, basedir, settings_name): """ Build project pages """ # Set project before to be able to load its modules setup_project(basedir, settings_name) # Load current project settings and page map settings = import_settings_module(settings_name, basedir=basedir) # In test environment, force the module reload to avoid previous test cache to be # used (since the module have the same path). if context.obj["test_env"]: settings = importlib.reload(settings) settings = load_settings(settings) views = import_pages_module(settings.PAGES_MAP, basedir=basedir) if context.obj["test_env"]: views = importlib.reload(views) # Debug output display_settings( settings, ("DEBUG", "PROJECT_DIR", "SOURCES_DIR", "TEMPLATES_DIR", "LOCALES_DIR"), ) builder_interface(settings, views)
def test_missing_required_settings(caplog, fixtures_settings, reset_syspath): """ Correctly imported settings but module miss some required ones """ basedir = os.path.join(fixtures_settings.fixtures_path, "dummy_package") module_name = "miss_required_settings" exception_msg = ( "The following settings are required but not defined: " "PROJECT_DIR, SOURCES_DIR, TEMPLATES_DIR, PUBLISH_DIR, " "STATIC_DIR" ) setup_project(basedir, "dummy_value", set_envvar=False) with pytest.raises(InvalidSettings, match=exception_msg): import_settings(name=module_name, basedir=basedir) assert caplog.record_tuples == [ ( "optimus", logging.INFO, "Register project base directory: {}".format(basedir), ), ("optimus", logging.INFO, 'Loading "{}" module'.format(module_name)), ] # Cleanup sys.path for next tests reset_syspath(basedir)
def test_build_bulk( minimal_basic_settings, fixtures_settings, reset_syspath, temp_builds_dir, sample_fixture_name, attempted_destinations, ): """ Build all pages in one bulk action Since 'build_item' test allready compare builded file, we dont do it again here, just check returned paths """ basepath = temp_builds_dir.join( "builder_build_bulk_{}".format(sample_fixture_name)) projectdir = os.path.join(basepath.strpath, sample_fixture_name) # Copy sample from fixtures dir templatedir = os.path.join(fixtures_settings.fixtures_path, sample_fixture_name) shutil.copytree(templatedir, projectdir) # Setup project setup_project(projectdir, "dummy_value") # Get basic sample settings settings = minimal_basic_settings(projectdir) # Define a dummy filter to test filter registration and usage settings.JINJA_FILTERS = {"dummy_filter": DummyFilter} # Init webassets and builder assets_env = register_assets(settings) builder = PageBuilder(settings, assets_env=assets_env) pages_map = import_pages_module(settings.PAGES_MAP, basedir=projectdir) # NOTE: We need to force reloading importation else the previous import settings # with different values, is still re-used pages_map = importlib.reload(pages_map) # Collect finded templates for each defined page view buildeds = builder.build_bulk(pages_map.PAGES) # Check every attempted file has been created (promise) assert buildeds == [ os.path.join(settings.PUBLISH_DIR, path) for path in attempted_destinations ] # Check promised builded file exists for dest in attempted_destinations: absdest = os.path.join(settings.PUBLISH_DIR, dest) assert os.path.exists(absdest) is True # Cleanup sys.path for next tests reset_syspath(projectdir)
def test_wrong_basedir(temp_builds_dir, caplog, fixtures_settings, reset_syspath): """ Settings module name is given but basedir is wrong """ package_name = "niet_package" basedir = os.path.join(fixtures_settings.fixtures_path, package_name) with pytest.raises(ImportError): setup_project(basedir, "dummy_value", set_envvar=False) # Cleanup sys.path for next tests reset_syspath(basedir)
def test_unknowed_project(caplog, fixtures_settings, reset_syspath): """ Unfindable package """ package_name = "niet_package" basedir = os.path.join(fixtures_settings.fixtures_path, package_name) with pytest.raises(ImportError): setup_project(basedir, "dummy_value", set_envvar=False) # Cleanup sys.path for next tests reset_syspath(basedir)
def test_get_translation(i18n_template_settings, fixtures_settings, reset_syspath, temp_builds_dir, caplog): """ Start with default env then use 'get_environnement' to get another one with only one dummy extension """ basepath = temp_builds_dir.join("builder_get_translation") project_name = "i18n_sample" projectdir = os.path.join(basepath.strpath, project_name) # Copy sample from fixtures dir templatedir = os.path.join(fixtures_settings.fixtures_path, "i18n_template") shutil.copytree(templatedir, projectdir) with caplog.at_level(logging.WARNING, logger="optimus"): assert os.path.exists(projectdir) is True settings = i18n_template_settings(projectdir) assert settings.SITE_NAME == "basic_i18n" # Init builder with default environment builder = PageBuilder(settings) # Ensure i18n is enabled assert list(builder.jinja_env.extensions.keys()) == [ "jinja2.ext.InternationalizationExtension", ] setup_project(projectdir, "dummy_value", set_envvar=False) # Define settings to view afterwards assert hasattr(settings, "PAGES_MAP") is True pages_map = import_pages_module(settings.PAGES_MAP, basedir=projectdir) for pageview in pages_map.PAGES: pageview.settings = settings setattr(settings, "PAGES", pages_map.PAGES) # Get enabled catalog lang from enabled page views translations = [] for item in settings.PAGES: t = builder.get_translation_for_item(item) translations.append(t.info()["language-team"]) assert translations == [ "en_US <*****@*****.**>", "fr_FR <*****@*****.**>", ] # Cleanup sys.path for next tests reset_syspath(projectdir)
def test_success(fixtures_settings, reset_syspath): """ Success """ basedir = os.path.join(fixtures_settings.fixtures_path, "basic_template") setup_project(basedir, "dummy_value", set_envvar=False) mod = import_settings(name="settings", basedir=basedir) assert mod.SITE_NAME == "basic" # Cleanup sys.path for next tests reset_syspath(basedir)
def test_scan_item( minimal_basic_settings, fixtures_settings, reset_syspath, temp_builds_dir, sample_fixture_name, attempted_templates, ): """ Scan page templates for each page This will only works for sample fixtures that use the same as 'basic_template'. """ basepath = temp_builds_dir.join("builder_scan_item_{}".format(sample_fixture_name)) project_name = sample_fixture_name projectdir = os.path.join(basepath.strpath, project_name) # Copy sample from fixtures dir templatedir = os.path.join(fixtures_settings.fixtures_path, sample_fixture_name) shutil.copytree(templatedir, projectdir) # Setup project setup_project(projectdir, "dummy_value") # Get basic sample settings settings = minimal_basic_settings(projectdir) # Init webassets and builder assets_env = register_assets(settings) builder = PageBuilder(settings, assets_env=assets_env) pages_map = import_pages_module(settings.PAGES_MAP, basedir=projectdir) # NOTE: We need to force reloading importation else the previous import settings # with different values, is still re-used pages_map = importlib.reload(pages_map) # Collect finded templates for each defined page view knowed = set([]) for pageview in pages_map.PAGES: found = builder.scan_item(pageview) knowed.update(found) # We dont really care about order, so aply default sorting assert sorted(list(knowed)) == attempted_templates # Cleanup sys.path for next tests reset_syspath(projectdir)
def watch_command(context, basedir, settings_name): """ Watch for changes in project sources to automatically build project ressources """ logger = logging.getLogger("optimus") # Set project before to be able to load its modules setup_project(basedir, settings_name) # Load current project settings and page map settings = import_settings_module(settings_name, basedir=basedir) # In test environment, force the module reload to avoid previous test cache to be # used (since the module have the same path). if context.obj["test_env"]: settings = importlib.reload(settings) settings = load_settings(settings) views = import_pages_module(settings.PAGES_MAP, basedir=basedir) if context.obj["test_env"]: views = importlib.reload(views) # Debug output display_settings( settings, ("DEBUG", "PROJECT_DIR", "SOURCES_DIR", "TEMPLATES_DIR", "LOCALES_DIR"), ) logger.debug("Trigger pages build to start") build_env = builder_interface(settings, views) # Init and configure observer with events observer = watcher_interface(settings, views, build_env) logger.warning("Starting to watch sources, use CTRL+C to stop it") # Do not start observer during tests since we cannot manage interruption and # watcher threads if not context.obj["test_env"]: observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: logger.warning("Stopping watcher..") observer.stop() observer.join()
def test_minimal_settings_fill(fixtures_settings, reset_syspath): """ Check some settings filled with a minimal settings module """ basedir = os.path.join(fixtures_settings.fixtures_path, "dummy_package") module_name = "minimal_settings" setup_project(basedir, "dummy_value", set_envvar=False) mod = import_settings(name=module_name, basedir=basedir) assert mod.PROJECT_DIR == "/home/foo" assert mod.BUNDLES == {} assert list(mod.ENABLED_BUNDLES) == [] # Cleanup sys.path for next tests reset_syspath(basedir)
def runserver_command(context, basedir, settings_name, index, hostname): """ Launch a simple HTTP server rooted on the project build directory Default behavior is to bind server on IP address '127.0.0.1' and port '80'. You may give another host to bind to as argument 'HOSTNAME'. 'HOSTNAME' can be either a simple address like '0.0.0.0' or an address and port like '0.0.0.0:8001'. If no custom port is given, '80' is used as default. """ logger = logging.getLogger("optimus") # Set project before to be able to load its modules setup_project(basedir, settings_name) # Load current project settings and page map settings = import_settings_module(settings_name, basedir=basedir) # In test environment, force the module reload to avoid previous test cache to be # used (since the module have the same path). if context.obj["test_env"]: settings = importlib.reload(settings) settings = load_settings(settings) # Debug output display_settings( settings, ("DEBUG", "PROJECT_DIR", "SOURCES_DIR", "TEMPLATES_DIR", "LOCALES_DIR"), ) try: server_env = server_interface(settings, hostname, index=index) except ServerConfigurationError as e: logger.error(e) raise click.Abort() # Don't start cherrypy server during tests if not context.obj["test_env"]: server_env["cherrypy"].quickstart( None, server_env["mount_on"], config=server_env["app_conf"], )
def handler_ready_shortcut( sample_fixture_name, tempdir_name, minimal_basic_settings, fixtures_settings, temp_builds_dir, reset_fixture, ): """ Get everything ready to return a fully usable handler and settings """ basepath = temp_builds_dir.join(tempdir_name) projectdir = os.path.join(basepath.strpath, sample_fixture_name) # Copy sample from fixtures dir templatedir = os.path.join(fixtures_settings.fixtures_path, sample_fixture_name) shutil.copytree(templatedir, projectdir) # Setup project setup_project(projectdir, "dummy_value") # Get basic sample settings, builder, assets environment and page views settings = minimal_basic_settings(projectdir) assets_env = register_assets(settings) pages_builder = PageBuilder(settings, assets_env=assets_env) pages_map = import_pages_module(settings.PAGES_MAP, basedir=projectdir) # NOTE: We need to force reloading importation else the previous import settings # with different values, is still re-used pages_map = importlib.reload(pages_map) # Fill registry pages_builder.scan_bulk(pages_map.PAGES) handler = TemplatesWatchEventHandler(settings, pages_builder, **settings.WATCHER_TEMPLATES_PATTERNS) # Tricks to return the "reset function" which needs "projectdir" path that is only # available from "handler_ready_shortcut" but not in the test itself def resetter(): reset_fixture(projectdir) return settings, handler, resetter
def test_dummy_valid(caplog, fixtures_settings, reset_syspath): """ Import valid module from sample dummy package """ basedir = os.path.join(fixtures_settings.fixtures_path, "dummy_package") module_name = "valid" setup_project(basedir, "dummy_value", set_envvar=False) mod = import_project_module(module_name, basedir=basedir) assert caplog.record_tuples == [ ( "optimus", logging.INFO, "Register project base directory: {}".format(basedir), ), ("optimus", logging.INFO, 'Loading "{}" module'.format(module_name)), ] assert mod.SOME_VAR == "Yep" # Cleanup sys.path for next tests reset_syspath(basedir)
def po_command(context, init, update, compile_opt, basedir, settings_name): """ Manage project translation catalogs for all registred languages """ # Set project before to be able to load its modules setup_project(basedir, settings_name) # Load current project settings and page map settings = import_settings_module(settings_name, basedir=basedir) # In test environment, force the module reload to avoid previous test cache to be # used (since the module have the same path). if context.obj["test_env"]: settings = importlib.reload(settings) settings = load_settings(settings) # Debug output display_settings( settings, ("DEBUG", "PROJECT_DIR", "SOURCES_DIR", "TEMPLATES_DIR", "LOCALES_DIR"), ) po_interface(settings, init=init, update=update, compile_opt=compile_opt)
def test_success(monkeypatch, caplog, fixtures_settings, flush_settings, reset_syspath): """ Check automatic settings loading from registry is working I didnt finded a clean way to re-import (not reload) settings module to avoid troubles with previously imported stuff NOTE: The trick is difficult to reproduce correctly with the new "import_project_module" + "setup_project" technic. It may be abandonned since it needs a lot of r&d for a single test. """ basedir = os.path.join(fixtures_settings.fixtures_path, "dummy_package") monkeypatch.setenv(PROJECT_DIR_ENVVAR, basedir) monkeypatch.setenv(SETTINGS_NAME_ENVVAR, "minimal_settings") setup_project(basedir, "dummy_value", set_envvar=False) # Tricky/Creepy way to check automatic settings loading from registry so # the settings is not memorized and wont alter further test. # WARNING: any further test must not try to do "from optimus.conf import # registry" else it will be memorized. mod = import_project_module( "registry", basedir=os.path.join( os.path.abspath(os.path.dirname(optimus.__file__)), "conf" ), ) assert mod.settings is not None assert mod.settings.SITE_NAME == "minimal" assert mod.settings.PUBLISH_DIR == "_build/dev" # Cleanup sys.path for next tests reset_syspath(basedir)
def test_build_item( minimal_basic_settings, fixtures_settings, reset_syspath, temp_builds_dir, sample_fixture_name, attempted_destinations, ): """ Build each page This will only works for sample fixtures that use the same as 'basic_template'. Also we build in production mode so webassets apply minification, this is required since in development mode webassets use a hash on every asset file that we can't rely on and would break builded file comparaison """ basepath = temp_builds_dir.join( "builder_build_item_{}".format(sample_fixture_name)) projectdir = os.path.join(basepath.strpath, sample_fixture_name) attempts_dir = os.path.join(fixtures_settings.fixtures_path, "builds", sample_fixture_name) # Copy sample from fixtures dir templatedir = os.path.join(fixtures_settings.fixtures_path, sample_fixture_name) shutil.copytree(templatedir, projectdir) # Setup project setup_project(projectdir, "dummy_value") # Get basic sample settings settings = minimal_basic_settings(projectdir) # Enabled production mode for webassets without url expire in a custom # cache dir, so we have stable asset filename for comparaison cache_dir = os.path.join(projectdir, "webassets-cache") os.makedirs(cache_dir) settings.DEBUG = False settings.WEBASSETS_CACHE = cache_dir settings.WEBASSETS_URLEXPIRE = False # Define a dummy filter to test filter registration and usage settings.JINJA_FILTERS = {"dummy_filter": DummyFilter} # Init webassets and builder assets_env = register_assets(settings) builder = PageBuilder(settings, assets_env=assets_env) pages_map = import_pages_module(settings.PAGES_MAP, basedir=projectdir) # NOTE: We need to force reloading importation else the previous import settings # with different values, is still re-used pages_map = importlib.reload(pages_map) # Collect finded templates for each defined page view buildeds = [] for pageview in pages_map.PAGES: found = builder.build_item(pageview) buildeds.append(found) # Add absolute build dir to each attempted relative path assert buildeds == [ os.path.join(settings.PUBLISH_DIR, path) for path in attempted_destinations ] # Check every builded destination exists for path in attempted_destinations: dest_path = os.path.join(settings.PUBLISH_DIR, path) attempt_path = os.path.join(attempts_dir, path) # Open builded file with io.open(dest_path, "r") as destfp: built = destfp.read() # Write attempted file from builded file # This is only temporary stuff to enable when writing new test or # updating existing one # with io.open(attempt_path, 'w') as writefp: # writefp.write(built) # Open attempted file from 'builds' with io.open(attempt_path, "r") as attemptfp: attempted = attemptfp.read() assert built == attempted # Cleanup sys.path for next tests reset_syspath(projectdir)