def test_get_globals(minimal_basic_settings, fixtures_settings, caplog): """ Context should be correclty filled with context globals (SITE shortcut, settings, optimus version) """ projectdir = os.path.join(fixtures_settings.fixtures_path, "basic_template") settings = minimal_basic_settings(projectdir) # Init builder with default environment builder = PageBuilder(settings) assert builder.jinja_env.globals["SITE"]["name"] == "basic" assert builder.jinja_env.globals["debug"] is True # Tamper settings to change context settings.SITE_NAME = "Foobar" settings.DEBUG = False context = builder.get_globals() assert context["SITE"]["name"] == "Foobar" assert context["SITE"]["web_url"] == "http://localhost" assert context["debug"] is False assert "OPTIMUS" in context assert "_SETTINGS" in context assert context["_SETTINGS"]["LANGUAGE_CODE"] == "en_US"
def builder_interface(settings, views): """ Build all enabled pages from given views module. Arguments: settings (optimus.conf.model.SettingsModel): Settings object which defines everything required for building. views (object): Module which defines page views to build, in fact the module object require only a ``PAGES`` attribute that is a list of Page view. Returns: dict: A dictionnary with initialized builder (``builder`` item), asset manager (``assets_env`` item) and the list of builded pages (``builded`` item). """ # Initialize required structure according to settings initialize(settings) # Init asset manager assets_env = register_assets(settings) # Init page builder builder = PageBuilder(settings, assets_env=assets_env) # Proceed to page building from registered pages builded = builder.build_bulk(views.PAGES) return { "assets_env": assets_env, "builded": builded, "builder": builder, }
def build_command(context, basedir, settings_name): """ Build project pages """ # Set required environment variables to load settings if PROJECT_DIR_ENVVAR not in os.environ \ or not os.environ[PROJECT_DIR_ENVVAR]: os.environ[PROJECT_DIR_ENVVAR] = basedir if SETTINGS_NAME_ENVVAR not in os.environ \ or not os.environ[SETTINGS_NAME_ENVVAR]: os.environ[SETTINGS_NAME_ENVVAR] = settings_name # Load current project settings from optimus.conf.registry import settings # Debug output display_settings(settings, ('DEBUG', 'PROJECT_DIR', 'SOURCES_DIR', 'TEMPLATES_DIR', 'LOCALES_DIR')) initialize(settings) # 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=basedir) # Proceed to page building from registered pages builder.build_bulk(pages_map.PAGES)
def test_scan_bulk(minimal_basic_settings, fixtures_settings, temp_builds_dir, sample_fixture_name, attempted_templates): """ Scan page templates all pages This will only works for sample fixtures that use the same as 'basic_template'. """ basepath = temp_builds_dir.join('builder_scan_bulk_{}'.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) # 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) # Collect finded templates for each defined page view knowed = builder.scan_bulk(pages_map.PAGES) assert sorted(list(knowed)) == attempted_templates
def handler_ready_shortcut(sample_fixture_name, tempdir_name, minimal_basic_settings, fixtures_settings, temp_builds_dir): """ 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) # 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) # Fill registry pages_builder.scan_bulk(pages_map.PAGES) handler = AssetsWatchEventHandler(settings, assets_env, pages_builder, **settings.WATCHER_ASSETS_PATTERNS) return settings, handler
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_get_environnement(minimal_basic_settings, fixtures_settings, caplog): """ Start with default env then use 'get_environnement' to get another one with only one dummy extension """ class DummyExtension(Extension): """ Dummy extension """ tags = set(["dummy"]) def DummyFilter(content): return "Nope" # Get basic sample settings projectdir = os.path.join(fixtures_settings.fixtures_path, "basic_template") settings = minimal_basic_settings(projectdir) # Init builder with default environment builder = PageBuilder(settings) # Tamper settings to define only dummy extension settings.JINJA_EXTENSIONS = [DummyExtension] # Tamper settings to define a dummy filter settings.JINJA_FILTERS = {"dummy_filter": DummyFilter} # Get new jinja environment jinja_env = builder.get_environnement() # Only dummy extension enabled assert list(jinja_env.extensions.keys()) == [ "02_get_environnement.DummyExtension" ] assert "dummy_filter" in jinja_env.filters # Using 'get_environnement' afterwards trigger additional debug log assert caplog.record_tuples == [ ( "optimus", logging.DEBUG, ("No Jinja2 environment given, initializing a new environment"), ), ("optimus", logging.DEBUG, "'i18n' enabled"), ("optimus", logging.DEBUG, ("PageBuilder initialized")), ( "optimus", logging.DEBUG, ("No Jinja2 environment given, initializing a new environment"), ), ]
def test_get_environnement(minimal_basic_settings, fixtures_settings, caplog): """ Start with default env then use 'get_environnement' to get another one with only one dummy extension """ class DummyExtension(Extension): """ Dummy extension """ tags = set(['dummy']) # Get basic sample settings projectdir = os.path.join(fixtures_settings.fixtures_path, 'basic_template') settings = minimal_basic_settings(projectdir) # Init builder with default environment builder = PageBuilder(settings) # Tamper settings to define only dummy extension settings.JINJA_EXTENSIONS = [DummyExtension] # Get new jinja environment jinja_env = builder.get_environnement() # Only dummy extension enabled assert list(jinja_env.extensions.keys()) == [ '02_get_environnement.DummyExtension' ] # Using 'get_environnement' afterwards trigger additional debug log assert caplog.record_tuples == [ ( 'optimus', logging.DEBUG, ('No Jinja2 environment given, initializing a new environment') ), ( 'optimus', logging.DEBUG, "'i18n' enabled" ), ( 'optimus', logging.DEBUG, ('PageBuilder initialized') ), ( 'optimus', logging.DEBUG, ('No Jinja2 environment given, initializing a new environment') ), ]
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_empty(minimal_basic_settings, fixtures_settings, caplog): """ Empty init with settings from 'minimal_basic' structure, no custom jinja or webassets environments """ # Get basic sample settings projectdir = os.path.join(fixtures_settings.fixtures_path, "minimal_basic") settings = minimal_basic_settings(projectdir) # Init builder builder = PageBuilder(settings) # Sample settings define only i18n extension assert list(builder.jinja_env.extensions.keys()) == [ "jinja2.ext.InternationalizationExtension", ] assert caplog.record_tuples == [ ( "optimus", logging.DEBUG, ("No Jinja2 environment given, initializing a new environment"), ), ("optimus", logging.DEBUG, "'i18n' enabled"), ("optimus", logging.DEBUG, ("PageBuilder initialized")), ]
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 test_get_globals_https(minimal_basic_settings, fixtures_settings, caplog): """ When setting 'HTTPS_ENABLED' is enabled, 'SITE.web_url' should start with 'https://'. """ projectdir = os.path.join(fixtures_settings.fixtures_path, "basic_template") settings = minimal_basic_settings(projectdir) # Init builder with default environment builder = PageBuilder(settings) # Tamper settings to change context settings.HTTPS_ENABLED = True context = builder.get_globals() assert context["SITE"]["web_url"] == "https://localhost"
def test_get_translation(i18n_template_settings, fixtures_settings, 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) == 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', ] # Define settings to view afterwards assert hasattr(settings, 'PAGES_MAP') == 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 <*****@*****.**>', ]
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_get_globals(minimal_basic_settings, fixtures_settings, caplog): """ Start with default env then use 'get_environnement' to get another one with only one dummy extension """ projectdir = os.path.join(fixtures_settings.fixtures_path, 'basic_template') settings = minimal_basic_settings(projectdir) # Init builder with default environment builder = PageBuilder(settings) assert builder.jinja_env.globals['SITE']['name'] == 'basic' assert builder.jinja_env.globals['debug'] == True # Tamper settings to change context settings.SITE_NAME = 'Foobar' settings.DEBUG = False context = builder.get_globals() assert context['SITE']['name'] == 'Foobar' assert context['debug'] == False
def test_build_bulk(minimal_basic_settings, fixtures_settings, 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) 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) # 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) # 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) == True
def test_custom_jinja(minimal_basic_settings, fixtures_settings, caplog): """ Init with settings from 'minimal_basic' structure and custom jinja environment """ # Get basic sample settings projectdir = os.path.join(fixtures_settings.fixtures_path, "minimal_basic") settings = minimal_basic_settings(projectdir) # Init a custom Jinja environment without any extension jinja_env = Jinja2Environment(loader=FileSystemLoader( settings.TEMPLATES_DIR), ) # Init builder with custom Jinja environment builder = PageBuilder(settings, jinja_env=jinja_env) # No enabled extension assert list(builder.jinja_env.extensions.keys()) == [] assert caplog.record_tuples == [ ("optimus", logging.DEBUG, ("PageBuilder initialized")), ]
def test_build_item(minimal_basic_settings, fixtures_settings, 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) # 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 # 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) # 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
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)
def watch_command(context, basedir, settings_name): """ Watch for changes in project sources to automatically build project ressources """ logger = logging.getLogger("optimus") # Set required environment variables to load settings if PROJECT_DIR_ENVVAR not in os.environ \ or not os.environ[PROJECT_DIR_ENVVAR]: os.environ[PROJECT_DIR_ENVVAR] = basedir if SETTINGS_NAME_ENVVAR not in os.environ or \ not os.environ[SETTINGS_NAME_ENVVAR]: os.environ[SETTINGS_NAME_ENVVAR] = settings_name # Load current project settings from optimus.conf.registry import settings # Debug output display_settings(settings, ('DEBUG', 'PROJECT_DIR', 'SOURCES_DIR', 'TEMPLATES_DIR', 'LOCALES_DIR')) initialize(settings) # 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=basedir) # Proceed to page building from registered pages logger.debug('Trigger pages build to start') builder.build_bulk(pages_map.PAGES) builder.scan_bulk(pages_map.PAGES) observer = Observer() # Init templates and assets event watchers templates_event_handler = TemplatesWatchEventHandler( settings, builder, **settings.WATCHER_TEMPLATES_PATTERNS ) if assets_env is not None: assets_event_handler = AssetsWatchEventHandler( settings, assets_env, builder, **settings.WATCHER_ASSETS_PATTERNS ) # Registering event watchers and start to watch observer.schedule( templates_event_handler, settings.TEMPLATES_DIR, recursive=True ) if assets_env is not None: observer.schedule( assets_event_handler, settings.SOURCES_DIR, recursive=True ) logger.warning('Starting to watch sources, use CTRL+C to stop it') observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: logger.warning('Stopping watcher..') observer.stop() observer.join()