def test_that_setup_block_is_only_executed_once(tmpdir):
    """Setup blocks in modules should only be performed once."""
    touched = Path(tmpdir, 'touched.tmp')
    modules = {
        'A': {
            'on_setup': {
                'run': {
                    'shell': f'touch {touched}',
                },
            },
        },
    }
    module_manager = ModuleManager(modules=modules)

    # The touched file should not exist before we have done anything
    assert not touched.exists()

    # After finishing tasks, the file should be touched
    module_manager.finish_tasks()
    assert touched.exists()

    # We now create a new object lifetime
    del module_manager
    touched.unlink()

    # The setup block should now *not* be executed
    module_manager = ModuleManager(modules=modules)
    module_manager.finish_tasks()
    assert not touched.exists()
Exemple #2
0
def test_compiling_template_with_specific_permissions(
    default_global_options,
    _runtime,
    test_config_directory,
    tmpdir,
    specified_permission,
    expected_permission,
):
    template = test_config_directory / 'templates' / 'empty.template'
    target = Path(tmpdir) / 'target'

    application_config = {
        'module/test': {
            'on_startup': {
                'compile': {
                    'source': str(template),
                    'target': str(target),
                    'permissions': specified_permission,
                },
            },
        },
    }
    application_config.update(default_global_options)
    application_config.update(_runtime)

    module_manager = ModuleManager(application_config)
    module_manager.finish_tasks()

    assert (target.stat().st_mode & 0o777) == expected_permission
Exemple #3
0
    def test_missing_template_file(
        self,
        default_global_options,
        _runtime,
        caplog,
    ):
        application_config = {
            'module/test_module': {
                'on_startup': {
                    'compile': [
                        {
                            'source': '/not/existing'
                        },
                    ],
                },
            },
        }

        application_config.update(default_global_options)
        application_config.update(_runtime)

        module_manager = ModuleManager(application_config)

        caplog.clear()
        module_manager.finish_tasks()
        assert 'Could not compile template "/not/existing" '\
               'to target "' in caplog.record_tuples[0][2]
Exemple #4
0
def test_all_three_actions_in_on_modified_block(
    three_watchable_files,
    test_config_directory,
):
    file1, file2, file3 = three_watchable_files
    car_template = test_config_directory / 'templates' / 'a_car.template'
    mercedes_context = test_config_directory / 'context' / 'mercedes.yml'
    tesla_context = test_config_directory / 'context' / 'tesla.yml'

    modules = {
        'car': {
            'on_startup': {
                'import_context': {
                    'from_path': str(mercedes_context),
                },
                'compile': {
                    'content': str(car_template),
                    'target': str(file1),
                },
            },
            'on_modified': {
                str(file2): {
                    'import_context': {
                        'from_path': str(tesla_context),
                    },
                    'compile': {
                        'content': str(car_template),
                        'target': str(file1),
                    },
                    'run': {
                        'shell': 'touch ' + str(file3)
                    },
                },
            },
        },
    }
    module_manager = ModuleManager(modules=modules)

    # Sanity check before beginning testing
    assert not file1.is_file()
    assert not file2.is_file()
    assert not file3.is_file()

    # Now finish tasks, i.e. on_startup block
    module_manager.finish_tasks()
    assert file1.is_file()
    assert not file2.is_file()
    assert not file3.is_file()

    # Check that the correct context is inserted
    with open(file1) as file:
        assert file.read() == 'My car is a Mercedes'

    # Now modify file2 such that the on_modified block is triggered
    file2.write_text('some new content')

    # The on_modified run command should now have been executed
    assert Retry()(lambda: file3.is_file())

    module_manager.exit()
Exemple #5
0
def test_has_unfinished_tasks(simple_application_config, freezer):
    # Move time to midday
    midday = datetime.now().replace(hour=12, minute=0)
    freezer.move_to(midday)

    # At instanziation, the module should have unfinished tasks
    weekday_module = ModuleManager(simple_application_config)
    assert weekday_module.has_unfinished_tasks() == True

    # After finishing tasks, there should be no unfinished tasks (duh!)
    weekday_module.finish_tasks()
    assert weekday_module.has_unfinished_tasks() == False

    # If we move the time forwards, but not to a new event, there should still
    # not be any unfinished tasks
    before_midnight = datetime.now().replace(hour=23, minute=59)
    freezer.move_to(before_midnight)
    assert weekday_module.has_unfinished_tasks() == False

    # But right after a event (new weekday), there should be unfinished
    # tasks
    two_minutes = timedelta(minutes=2)
    freezer.move_to(before_midnight + two_minutes)
    assert weekday_module.has_unfinished_tasks() == True

    # Again, after finishing tasks, there should be no unfinished tasks left
    weekday_module.finish_tasks()
    assert weekday_module.has_unfinished_tasks() == False
Exemple #6
0
def test_import_sections_on_event(config_with_modules, freezer):
    config_with_modules['module/weekday_module']['on_event'][
        'import_context'] = [{
            'to_section': 'week',
            'from_path': 'astrality/tests/templates/weekday.yml',
            'from_section': '{event}',
        }]
    config_with_modules.pop('module/solar_module')
    module_manager = ModuleManager(config_with_modules)

    assert module_manager.application_context['fonts'] == {
        1: 'FuraCode Nerd Font'
    }

    sunday = datetime(year=2018, month=2, day=4)
    freezer.move_to(sunday)
    module_manager.finish_tasks()

    # Make application_context comparisons easier
    module_manager.application_context.pop('env')

    # Startup does not count as a event, so no context has been imported
    assert module_manager.application_context == {
        'fonts': Resolver({1: 'FuraCode Nerd Font'}),
    }

    monday = datetime(year=2018, month=2, day=5)
    freezer.move_to(monday)
    module_manager.finish_tasks()

    # The event has now changed, so context should be imported
    assert module_manager.application_context == {
        'fonts': Resolver({1: 'FuraCode Nerd Font'}),
        'week': Resolver({'day': 'monday'}),
    }
Exemple #7
0
def test_compiling_template_with_specific_permissions(
    test_config_directory,
    tmpdir,
    specified_permission,
    expected_permission,
):
    template = test_config_directory / 'templates' / 'empty.template'
    target = Path(tmpdir) / 'target'

    modules = {
        'test': {
            'on_startup': {
                'compile': {
                    'content': str(template),
                    'target': str(target),
                    'permissions': specified_permission,
                },
            },
        },
    }

    module_manager = ModuleManager(modules=modules, )
    module_manager.finish_tasks()

    assert (target.stat().st_mode & 0o777) == expected_permission
def test_symlinking_in_on_startup_block(
    action_block_factory,
    module_factory,
    create_temp_files,
):
    """ModuleManager should symlink properly."""
    file1, file2, file3, file4 = create_temp_files(4)
    file2.write_text('original')

    action_block = action_block_factory(symlink=[
        {
            'content': str(file1),
            'target': str(file2)
        },
        {
            'content': str(file3),
            'target': str(file4)
        },
    ], )
    module = module_factory(on_startup=action_block)

    module_manager = ModuleManager()
    module_manager.modules = {'test': module}
    module_manager.finish_tasks()

    assert file2.is_symlink()
    assert file2.resolve() == file1
    assert file4.is_symlink()
    assert file4.resolve() == file3
Exemple #9
0
def test_recompile_templates_when_modified_overridden(
    three_watchable_files,
    default_global_options,
    _runtime,
):
    """
    If a file is watched in a on_modified block, it should override the
    recompile_modified_templates option.
    """
    template, target, touch_target = three_watchable_files
    template.touch()

    application_config = {
        'module/module_name': {
            'on_startup': {
                'compile': {
                    'source': str(template),
                    'target': str(target),
                },
            },
            'on_modified': {
                str(template): {
                    'run': {
                        'shell': 'touch ' + str(touch_target)
                    },
                },
            },
        },
        'context/section': {
            1: 'value',
        },
    }
    application_config.update(default_global_options)
    application_config.update(_runtime)
    application_config['config/modules'] = {
        'recompile_modified_templates': True,
    }

    module_manager = ModuleManager(application_config)

    # Sanity check before beginning testing
    with open(template) as file:
        assert file.read() == ''

    assert not target.is_file()

    # Compile the template
    module_manager.finish_tasks()
    with open(target) as file:
        assert file.read() == ''

    # Now write to the template and see if it is *compiled*, but the on_modified
    # command is run instead
    template.write_text('{{ section.2 }}')
    time.sleep(0.7)
    with open(target) as file:
        assert file.read() == ''
    assert touch_target.is_file()

    module_manager.exit()
Exemple #10
0
def test_recompile_templates_when_modified_overridden(
    three_watchable_files,
    test_config_directory,
):
    """
    If a file is watched in a on_modified block, it should override the
    reprocess_modified_files option.
    """
    template, target, touch_target = three_watchable_files
    template.touch()

    modules = {
        'module_name': {
            'on_startup': {
                'compile': {
                    'content': str(template),
                    'target': str(target),
                },
            },
            'on_modified': {
                str(template): {
                    'run': {'shell': 'touch ' + str(touch_target)},
                },
            },
        },
    }

    application_config = {'modules': {'reprocess_modified_files': True}}
    module_manager = ModuleManager(
        config=application_config,
        modules=modules,
        context=Context({
            'section': {1: 'value'},
        }),
        directory=test_config_directory,
    )

    # Sanity check before beginning testing
    with open(template) as file:
        assert file.read() == ''

    assert not target.is_file()

    # Compile the template
    module_manager.finish_tasks()
    with open(target) as file:
        assert file.read() == ''

    # Now write to the template and see if it is *compiled*, but the on_modified
    # command is run instead
    template.write_text('{{ section.2 }}')

    retry = Retry()
    assert retry(lambda: target.read_text() == '')
    assert retry(lambda: touch_target.is_file())

    module_manager.exit()
Exemple #11
0
def test_that_running_processes_causes_keep_running():
    """If shell commands are running, keep_running should be True."""
    module_manager = ModuleManager(modules={
        'A': {
            'run': {
                'shell': 'sleep 10'
            }
        },
    }, )
    module_manager.finish_tasks()
    assert module_manager.keep_running is True
Exemple #12
0
def test_hot_reloading(
    test_template_targets,
    test_config_directory,
):
    template_target1, template_target2 = test_template_targets
    config1 = test_config_directory / 'modules1.yml'
    config2 = test_config_directory / 'modules2.yml'
    target_config = test_config_directory / 'modules.yml'

    # Copy the first configuration into place
    shutil.copy(str(config1), str(target_config))

    modules1 = utils.compile_yaml(
        config1,
        context={},
    )

    application_config1 = {'astrality': {'hot_reload_config': True}}
    module_manager = ModuleManager(
        config=application_config1,
        modules=modules1,
        directory=test_config_directory,
    )

    # Before beginning, the template should not be compiled
    assert not template_target1.is_file()

    # But when we finalize tasks, it should be compiled
    module_manager.finish_tasks()
    assert template_target1.is_file()

    # Also check that the filewatcher has been started
    assert module_manager.directory_watcher.observer.is_alive()

    # We now "edit" the configuration file
    shutil.copy(str(config2), str(target_config))

    # Since hot reloading is enabled, the new template target should be
    # compiled, and the old one cleaned up
    retry = Retry()
    assert retry(lambda: template_target2.is_file())
    assert retry(lambda: not template_target1.is_file())

    # And we switch back again
    shutil.copy(str(config1), str(target_config))
    assert retry(lambda: template_target1.is_file())
    assert retry(lambda: not template_target2.is_file())

    # Cleanup config file
    if target_config.is_file():
        os.remove(target_config)

    # Stop the filewatcher
    module_manager.directory_watcher.stop()
Exemple #13
0
def test_that_cleanup_cli_works(
    method,
    create_temp_files,
    patch_xdg_directory_standard,
):
    """--cleanup module_name, all module created files should be deleted"""
    (
        template1,
        template2,
        template3,
        target1,
        target2,
        target3,
    ) = create_temp_files(6)

    for template in (template1, template2, template3):
        template.write_text('new content')

    for target in (target1, target2, target3):
        target.write_text('original content')

    modules = {
        'A': {
            method: [
                {
                    'content': str(template1),
                    'target': str(target1),
                },
                {
                    'content': str(template2),
                    'target': str(target2),
                },
            ],
        },
        'B': {
            method: {
                'content': str(template3),
                'target': str(target3),
            },
        },
    }
    module_manager = ModuleManager(modules=modules)
    module_manager.finish_tasks()

    for target in (target1, target2, target3):
        assert target.resolve().read_text() == 'new content'

    bin_script = str(Path(__file__).parents[3] / 'bin' / 'astrality')
    data_home = 'XDG_DATA_HOME="' + str(patch_xdg_directory_standard) + '/.." '
    command = data_home + bin_script + ' --cleanup A --cleanup B'
    os.system(command)

    for target in (target1, target2, target3):
        assert target.resolve().read_text() == 'original content'
Exemple #14
0
def test_that_only_startup_event_block_is_run_on_startup(
    two_test_file_paths,
    test_config_directory,
    default_global_options,
    _runtime,
    freezer,
):
    thursday = datetime(
        year=2018,
        month=2,
        day=15,
        hour=12,
    )
    freezer.move_to(thursday)

    test_file1, test_file2 = two_test_file_paths
    application_config = {
        'module/A': {
            'event_listener': {
                'type': 'weekday'
            },
            'on_startup': {
                'run': [{
                    'shell': 'touch ' + str(test_file1)
                }],
            },
            'on_event': {
                'run': [{
                    'shell': 'touch ' + str(test_file2)
                }],
            },
        },
    }
    application_config.update(default_global_options)
    application_config.update(_runtime)
    module_manager = ModuleManager(application_config)

    # Before call to finish_tasks, no actions should have been performed
    assert not test_file1.is_file() and not test_file2.is_file()

    # Now call finish_tasks for the first time, only startup event block should
    # be run
    module_manager.finish_tasks()
    time.sleep(0.5)
    assert test_file1.is_file()
    assert not test_file2.is_file()

    friday = datetime(
        year=2018,
        month=2,
        day=16,
        hour=12,
    )
Exemple #15
0
 def test_using_finish_tasks_on_example_configuration(
     self,
     conf,
     modules,
     context,
 ):
     module_manager = ModuleManager(
         config=conf,
         modules=modules,
         context=context,
     )
     module_manager.finish_tasks()
Exemple #16
0
def test_import_sections_on_startup(config_with_modules, freezer):
    modules, context = config_with_modules

    # Insert day the module was started into 'start day'
    modules[
        'weekday_module'
    ]['on_startup']['import_context'] = [{
        'to_section': 'start_day',
        'from_path': 'astrality/tests/templates/weekday.yml',
        'from_section': '{event}',
    }]

    # Insert the current day into 'day_now'
    modules[
        'weekday_module'
    ]['on_event']['import_context'] = [{
        'to_section': 'day_now',
        'from_path': 'astrality/tests/templates/weekday.yml',
        'from_section': '{event}',
    }]
    modules.pop('solar_module')
    module_manager = ModuleManager(
        modules=modules,
        context=Context({
            'fonts': {1: 'FuraCode Nerd Font'},
        }),
        directory=Path(__file__).parents[3],
    )

    # Before finishing tasks, no context sections are imported
    assert module_manager.application_context['fonts'] \
        == {1: 'FuraCode Nerd Font'}

    # Start module on a monday
    sunday = datetime(year=2018, month=2, day=4)
    freezer.move_to(sunday)
    module_manager.finish_tasks()
    assert module_manager.application_context == {
        'fonts': Context({1: 'FuraCode Nerd Font'}),
        'start_day': Context({'day': 'sunday'}),
    }

    # 'now_day' should now be added, but 'start_day' should remain unchanged
    monday = datetime(year=2018, month=2, day=5)
    freezer.move_to(monday)
    module_manager.finish_tasks()
    assert module_manager.application_context == {
        'fonts': Context({1: 'FuraCode Nerd Font'}),
        'start_day': Context({'day': 'sunday'}),
        'day_now': Context({'day': 'monday'}),
    }
Exemple #17
0
def test_hot_reloading(test_template_targets, default_global_options, _runtime,
                       test_config_directory):
    template_target1, template_target2 = test_template_targets
    config1 = test_config_directory / 'astrality1.yml'
    config2 = test_config_directory / 'astrality2.yml'
    target_config = test_config_directory / 'astrality.yml'
    temp_directory = Path('/tmp/astrality')

    # Copy the first configuration into place
    shutil.copy(str(config1), str(target_config))

    application_config1 = dict_from_config_file(
        config1,
        context={},
    )
    application_config1.update(default_global_options)
    application_config1.update(_runtime)
    application_config1['config/astrality']['hot_reload_config'] = True

    module_manager = ModuleManager(application_config1)

    # Before beginning, the template should not be compiled
    assert not template_target1.is_file()

    # But when we finalize tasks, it should be compiled
    module_manager.finish_tasks()
    assert template_target1.is_file()

    # Also check that the filewatcher has been started
    assert module_manager.directory_watcher.observer.is_alive()

    # We now "edit" the configuration file
    shutil.copy(str(config2), str(target_config))
    time.sleep(0.7)

    # Since hot reloading is enabled, the new template target should be
    # compiled, and the old one cleaned up
    assert template_target2.is_file()
    assert not template_target1.is_file()

    # And we switch back again
    shutil.copy(str(config1), str(target_config))
    time.sleep(0.7)
    assert template_target1.is_file()
    assert not template_target2.is_file()

    # Cleanup config file
    if target_config.is_file():
        os.remove(target_config)
Exemple #18
0
def test_correct_relative_paths_used_in_external_module(
    temp_test_files,
    test_config_directory,
):
    application_config = {
        'modules': {
            'modules_directory': 'test_modules',
            'enabled_modules': [{
                'name': 'using_all_actions::*'
            }],
        },
    }
    module_manager = ModuleManager(config=application_config)

    (
        compile_target,
        touch_target,
        watch_touch_target,
        watched_file,
    ) = temp_test_files

    # Sanity check before testing
    for file in (
            compile_target,
            touch_target,
            watch_touch_target,
    ):
        assert not file.is_file()

    # Finish task and see if context import, compilation, and run has been
    # correctly run relative to the module directory path
    module_manager.finish_tasks()
    with open(compile_target, 'r') as file:
        assert file.read() == "Vietnam's capitol is Ho Chi Minh City"
    assert touch_target.is_file()

    # Now modify the observed file, and see if on_modified is triggered
    watched_file.write_text('This watched file has been modified')

    retry = Retry()
    assert retry(
        lambda: compile_target.read_text() == "Vietnam's capitol is Hanoi", )
    assert retry(lambda: watch_touch_target.is_file())

    touch_target.unlink()
    compile_target.unlink()
    watch_touch_target.unlink()
    watched_file.write_text('')
Exemple #19
0
    def test_missing_template_file(self, caplog):
        modules = {
            'test_module': {
                'on_startup': {
                    'compile': [
                        {'content': '/not/existing'},
                    ],
                },
            },
        }
        module_manager = ModuleManager(modules=modules)

        caplog.clear()
        module_manager.finish_tasks()
        assert 'Could not compile template "/not/existing" '\
               'to target "' in caplog.record_tuples[0][2]
Exemple #20
0
def test_recompile_templates_when_modified(
    three_watchable_files,
    default_global_options,
    _runtime,
):
    template, target, _ = three_watchable_files
    template.touch()

    application_config = {
        'module/module_name': {
            'on_startup': {
                'compile': {
                    'source': str(template),
                    'target': str(target),
                },
            },
        },
        'context/section': {
            1: 'value',
        },
    }
    application_config.update(default_global_options)
    application_config.update(_runtime)
    application_config['config/modules'] = {
        'recompile_modified_templates': True,
    }

    module_manager = ModuleManager(application_config)

    # Sanity check before beginning testing
    with open(template) as file:
        assert file.read() == ''

    assert not target.is_file()

    # Compile the template
    module_manager.finish_tasks()
    with open(target) as file:
        assert file.read() == ''

    # Now write to the template and see if it is recompiled
    template.write_text('{{ section.2 }}')
    time.sleep(0.7)
    with open(target) as file:
        assert file.read() == 'value'

    module_manager.exit()
Exemple #21
0
def test_that_all_exit_actions_are_correctly_performed(
    default_global_options,
    _runtime,
    test_config_directory,
    test_target,
):
    application_config = {
        'module/car': {
            'on_startup': {
                'import_context': {
                    'from_path': 'context/mercedes.yml',
                },
                'compile': {
                    'source': 'templates/a_car.template',
                    'target': str(test_target),
                },
            },
            'on_exit': {
                'import_context': {
                    'from_path': 'context/tesla.yml',
                },
                'compile': {
                    'source': 'templates/a_car.template',
                    'target': str(test_target),
                },
            },
        },
    }
    application_config.update(default_global_options)
    application_config.update(_runtime)

    module_manager = ModuleManager(application_config)

    # Before we start, the template target should not exist
    assert not test_target.is_file()

    # We finish tasks, reslulting in Mercedes being compiled
    module_manager.finish_tasks()
    with open(test_target) as file:
        assert file.read() == 'My car is a Mercedes'

    # We now exit, and check if the context import and compilation has been
    # performed
    module_manager.exit()
    with open(test_target) as file:
        assert file.read() == 'My car is a Tesla'
Exemple #22
0
def test_import_sections_on_startup(config_with_modules, freezer):
    # Insert day the module was started into 'start day'
    config_with_modules['module/weekday_module']['on_startup'][
        'import_context'] = [{
            'to_section': 'start_day',
            'from_path': 'astrality/tests/templates/weekday.yml',
            'from_section': '{event}',
        }]

    # Insert the current day into 'day_now'
    config_with_modules['module/weekday_module']['on_event'][
        'import_context'] = [{
            'to_section': 'day_now',
            'from_path': 'astrality/tests/templates/weekday.yml',
            'from_section': '{event}',
        }]
    config_with_modules.pop('module/solar_module')
    module_manager = ModuleManager(config_with_modules)

    # Remove 'env' context for easier comparisons
    module_manager.application_context.pop('env')

    # Before finishing tasks, no context sections are imported
    assert module_manager.application_context['fonts'] == {
        1: 'FuraCode Nerd Font'
    }

    # Start module on a monday
    sunday = datetime(year=2018, month=2, day=4)
    freezer.move_to(sunday)
    module_manager.finish_tasks()
    assert module_manager.application_context == {
        'fonts': Resolver({1: 'FuraCode Nerd Font'}),
        'start_day': Resolver({'day': 'sunday'}),
    }

    # 'now_day' should now be added, but 'start_day' should remain unchanged
    monday = datetime(year=2018, month=2, day=5)
    freezer.move_to(monday)
    module_manager.finish_tasks()
    assert module_manager.application_context == {
        'fonts': Resolver({1: 'FuraCode Nerd Font'}),
        'start_day': Resolver({'day': 'sunday'}),
        'day_now': Resolver({'day': 'monday'}),
    }
Exemple #23
0
def test_that_stowed_templates_are_also_watched(three_watchable_files):
    """Stowing template instead of compiling it should still be watched."""
    template, target, _ = three_watchable_files
    template.touch()

    modules = {
        'module_name': {
            'on_startup': {
                'stow': {
                    'content': str(template),
                    'target': str(target),
                    'templates': '(.+)',
                    'non_templates': 'ignore',
                },
            },
        },
    }

    application_config = {'modules': {'reprocess_modified_files': True}}
    module_manager = ModuleManager(
        config=application_config,
        modules=modules,
        context=Context({
            'section': {
                1: 'value'
            },
        }),
    )

    # Sanity check before beginning testing
    with open(template) as file:
        assert file.read() == ''

    assert not target.is_file()

    # Stow the template
    module_manager.finish_tasks()
    with open(target) as file:
        assert file.read() == ''

    # Now write to the template and see if it is recompiled
    template.write_text('{{ section.2 }}')
    assert Retry()(lambda: target.read_text() == 'value')

    module_manager.exit()
def test_that_dry_run_is_respected(create_temp_files):
    """ModuleManager should pass on dry_run to its actions."""
    (
        touched,
        copy_content,
        copy_target,
        compile_content,
        compile_target,
        symlink_content,
        symlink_target,
    ) = create_temp_files(7)
    touched.unlink()
    copy_target.write_text('copy_original')
    compile_target.write_text('compile_original')

    modules = {
        'A': {
            'run': {
                'shell': 'touch ' + str(touched),
            },
            'copy': {
                'content': str(copy_content),
                'target': str(copy_target),
            },
            'compile': {
                'content': str(compile_content),
                'target': str(compile_target),
            },
            'symlink': {
                'content': str(symlink_content),
                'target': str(symlink_target),
            },
        },
    }
    module_manager = ModuleManager(
        modules=modules,
        directory=touched.parents[1],
        dry_run=True,
    )
    module_manager.finish_tasks()

    assert not touched.exists()
    assert copy_target.read_text() == 'copy_original'
    assert compile_target.read_text() == 'compile_original'
    assert not symlink_target.is_symlink()
Exemple #25
0
def test_correct_relative_paths_used_in_external_module(
    temp_test_files,
    test_config_directory,
    default_global_options,
    _runtime,
):
    application_config = {
        'config/modules': {
            'modules_directory': 'test_modules',
            'enabled_modules': [{
                'name': 'using_all_actions::*'
            }],
        },
    }
    application_config.update(default_global_options)
    application_config.update(_runtime)

    module_manager = ModuleManager(application_config)

    compile_target, touch_target, watch_touch_target, watched_file = temp_test_files

    # Sanity check before testing
    for file in (
            compile_target,
            touch_target,
            watch_touch_target,
    ):
        assert not file.is_file()

    # Finish task and see if context import, compilation, and run has been
    # correctly run relative to the module directory path
    module_manager.finish_tasks()
    with open(compile_target, 'r') as file:
        assert file.read() == "Vietnam's capitol is Ho Chi Minh City"
    assert touch_target.is_file()

    # Now modify the observed file, and see if on_modified is triggered
    watched_file.write_text('This watched file has been modified')
    time.sleep(0.7)

    with open(compile_target, 'r') as file:
        assert file.read() == "Vietnam's capitol is Hanoi"
    assert watch_touch_target.is_file()
Exemple #26
0
def test_recompile_templates_when_modified(three_watchable_files):
    template, target, _ = three_watchable_files
    template.touch()

    modules = {
        'module_name': {
            'on_startup': {
                'compile': {
                    'content': str(template),
                    'target': str(target),
                },
            },
        },
    }

    application_config = {'modules': {'reprocess_modified_files': True}}
    module_manager = ModuleManager(
        config=application_config,
        modules=modules,
        context=Context({
            'section': {
                1: 'value'
            },
        }),
    )

    # Sanity check before beginning testing
    with open(template) as file:
        assert file.read() == ''

    assert not target.is_file()

    # Compile the template
    module_manager.finish_tasks()
    with open(target) as file:
        assert file.read() == ''

    # Now write to the template and see if it is recompiled
    template.write_text('{{ section.2 }}')
    assert Retry()(lambda: target.read_text() == 'value')

    module_manager.exit()
    module_manager.directory_watcher.stop()
Exemple #27
0
def test_detection_of_new_event_involving_several_modules(
    config_with_modules,
    freezer,
):
    modules, context = config_with_modules

    # Move time to right before noon
    solar_event_listener = event_listener.Solar(modules)
    noon = solar_event_listener.location.sun()['noon']
    one_minute = timedelta(minutes=1)
    freezer.move_to(noon - one_minute)
    module_manager = ModuleManager(
        modules=modules,
        context=context,
    )

    # All modules should now considered to have now events
    assert module_manager.has_unfinished_tasks() is True

    # Running on event method for all the event changed modules
    module_manager.finish_tasks()

    # After running these methods, they should all be reverted to not changed
    assert module_manager.has_unfinished_tasks() is False

    # Move time to right after noon
    freezer.move_to(noon + one_minute)

    # The solar event listener should now be considered to have been event
    # changed
    assert module_manager.has_unfinished_tasks() is True

    # Again, check if on_event() method makes them unchanged
    module_manager.finish_tasks()
    assert module_manager.has_unfinished_tasks() is False

    # Move time two days forwards
    two_days = timedelta(days=2)
    freezer.move_to(noon + two_days)

    # Now both event listeners should be considered to have new events
    assert module_manager.has_unfinished_tasks() is True
Exemple #28
0
def test_import_sections_on_event(config_with_modules, freezer):
    modules, context = config_with_modules

    modules[
        'weekday_module'
    ]['on_event']['import_context'] = [{
        'to_section': 'week',
        'from_path': 'astrality/tests/templates/weekday.yml',
        'from_section': '{event}',
    }]

    modules.pop('solar_module')
    module_manager = ModuleManager(
        modules=modules,
        context=Context({
            'fonts': {1: 'FuraCode Nerd Font'},
        }),
        directory=Path(__file__).parents[3],
    )

    assert module_manager.application_context['fonts'] \
        == Context({1: 'FuraCode Nerd Font'})

    sunday = datetime(year=2018, month=2, day=4)
    freezer.move_to(sunday)
    module_manager.finish_tasks()

    # Startup does not count as a event, so no context has been imported
    assert module_manager.application_context == Context({
        'fonts': Context({1: 'FuraCode Nerd Font'}),
    })

    monday = datetime(year=2018, month=2, day=5)
    freezer.move_to(monday)
    module_manager.finish_tasks()

    # The event has now changed, so context should be imported
    assert module_manager.application_context == {
        'fonts': Context({1: 'FuraCode Nerd Font'}),
        'week': Context({'day': 'monday'}),
    }
Exemple #29
0
def test_on_modified_event_in_module(modules_config):
    (
        modules,
        empty_template,
        empty_template_target,
        touch_target,
        secondary_template,
        secondary_template_target,
    ) = modules_config

    module_manager = ModuleManager(modules=modules)

    # Start the file watcher by invoking the startup command indirectly
    # through finish_tasks() method
    module_manager.finish_tasks()

    # Assert that the template file is really empty as a sanity check
    assert empty_template.read_text() == ''

    # And that target files are not created yet
    assert not touch_target.is_file()
    assert not empty_template_target.is_file()
    assert not secondary_template_target.is_file()

    # Trigger the on_modified event
    empty_template.write_text('new content')

    # And assert that the new template has been compiled
    retry = Retry()
    assert retry(lambda: empty_template_target.is_file())
    assert retry(lambda: empty_template_target.read_text() == 'new content')

    # Assert that also templates from other modules are compiled
    assert retry(lambda: secondary_template_target.is_file())
    assert retry(
        lambda: secondary_template_target.read_text() == 'one\ntwo\nthree',
    )

    # And that the new file has been touched
    assert retry(lambda: touch_target.is_file())
Exemple #30
0
def test_on_modified_event_in_module(modules_config):
    (
        config,
        empty_template,
        empty_template_target,
        touch_target,
        secondary_template,
        secondary_template_target,
    ) = modules_config
    module_manager = ModuleManager(config)

    # Start the file watcher by invoking the startup command indirectly
    # through finish_tasks() method
    module_manager.finish_tasks()

    # Assert that the template file is really empty as a sanity check
    with open(empty_template) as file:
        assert file.read() == ''

    # And that target files are not created yet
    assert not touch_target.is_file()
    assert not empty_template_target.is_file()
    assert not secondary_template_target.is_file()

    # Trigger the on_modified event
    empty_template.write_text('new content')
    time.sleep(1)

    # And assert that the new template has been compiled
    assert empty_template_target.is_file()
    with open(empty_template_target) as file:
        assert file.read() == 'new content'

    # Assert that also templates from other modules are compiled
    assert secondary_template_target.is_file()
    with open(secondary_template_target) as file:
        assert file.read() == 'one\ntwo\nthree'

    # And that the new file has been touched
    assert touch_target.is_file()