def test_len(self) -> None: extension_configuration_a = ExtensionConfiguration( ConfigurableExtension) extension_configuration_b = ExtensionConfiguration( NonConfigurableExtension) sut = ExtensionsConfiguration([ extension_configuration_a, extension_configuration_b, ]) with assert_in_scope(sut): self.assertEquals(2, len(sut))
def test_iter(self) -> None: extension_configuration_a = ExtensionConfiguration( ConfigurableExtension) extension_configuration_b = ExtensionConfiguration( NonConfigurableExtension) sut = ExtensionsConfiguration([ extension_configuration_a, extension_configuration_b, ]) with assert_in_scope(sut): self.assertCountEqual( [extension_configuration_a, extension_configuration_b], iter(sut))
async def test_extensions_with_comes_after_with_other_extension( self) -> None: configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS) configuration.extensions.add( ExtensionConfiguration( ComesAfterNonConfigurableExtensionExtension)) configuration.extensions.add( ExtensionConfiguration(NonConfigurableExtension)) async with App(configuration) as sut: carrier = [] await sut.dispatcher.dispatch(Tracker, 'track')(carrier) self.assertEquals(2, len(carrier)) self.assertEquals(NonConfigurableExtension, type(carrier[0])) self.assertEquals(ComesAfterNonConfigurableExtensionExtension, type(carrier[1]))
async def test_extensions_with_one_extension(self) -> None: configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS) configuration.extensions.add( ExtensionConfiguration(NonConfigurableExtension)) async with App(configuration) as sut: self.assertIsInstance(sut.extensions[NonConfigurableExtension], NonConfigurableExtension)
async def test_filter(self, m_aioresponses) -> None: entry_url = 'https://en.wikipedia.org/wiki/Amsterdam' links = [ Link(entry_url), # Add a link to Wikipedia, but using a locale that's not used by the app, to test it's ignored. Link('https://nl.wikipedia.org/wiki/Amsterdam'), # Add a link that doesn't point to Wikipedia at all to test it's ignored. Link('https://example.com'), ] api_url = 'https://en.wikipedia.org/w/api.php?action=query&titles=Amsterdam&prop=extracts&exintro&format=json&formatversion=2' title = 'Amstelredam' extract = 'De hoofdstad van Nederland.' api_response_body = { 'query': { 'pages': [ { 'title': title, 'extract': extract, }, ], } } m_aioresponses.get(api_url, payload=api_response_body) with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration( output_directory_path, 'https://ancestry.example.com') configuration.cache_directory_path = Path(cache_directory_path) configuration.extensions.add(ExtensionConfiguration(Wikipedia)) async with App(configuration) as app: actual = app.jinja2_environment.from_string( '{% for entry in (links | wikipedia) %}{{ entry.content }}{% endfor %}').render(links=links) self.assertEquals(extract, actual)
async def test_post_load(self): person = Person('P0') Presence(person, Subject(), Event(None, Birth())) source_file = File('F0', __file__) source = Source('S0', 'The Source') source.private = True source.files.append(source_file) citation_file = File('F0', __file__) citation_source = Source('The Source') citation = Citation('C0', citation_source) citation.private = True citation.files.append(citation_file) with TemporaryDirectory() as output_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.extensions.add(ExtensionConfiguration(Privatizer)) async with App(configuration) as app: app.ancestry.entities.append(person) app.ancestry.entities.append(source) app.ancestry.entities.append(citation) await load(app) self.assertTrue(person.private) self.assertTrue(source_file.private) self.assertTrue(citation_file.private)
def test_configuration(self): extension_type_configuration = ExtensionTypeConfiguration() sut = ExtensionConfiguration(Extension, True, extension_type_configuration) self.assertEquals(extension_type_configuration, sut.extension_type_configuration) with assert_reactor_called(sut): extension_type_configuration.react.trigger()
async def test_extensions_with_multiple_extensions_with_cyclic_dependencies( self) -> None: configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS) configuration.extensions.add( ExtensionConfiguration(CyclicDependencyOneExtension)) with self.assertRaises(CycleError): async with App(configuration) as sut: sut.extensions
async def test_extensions_with_multiple_extensions_with_duplicate_dependencies( self) -> None: configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS) configuration.extensions.add( ExtensionConfiguration(DependsOnNonConfigurableExtensionExtension)) configuration.extensions.add( ExtensionConfiguration( AlsoDependsOnNonConfigurableExtensionExtension)) async with App(configuration) as sut: carrier = [] await sut.dispatcher.dispatch(Tracker, 'track')(carrier) self.assertEquals(3, len(carrier)) self.assertEquals(NonConfigurableExtension, type(carrier[0])) self.assertIn(DependsOnNonConfigurableExtensionExtension, [type(extension) for extension in carrier]) self.assertIn(AlsoDependsOnNonConfigurableExtensionExtension, [type(extension) for extension in carrier])
async def test_extensions_addition_to_configuration(self) -> None: configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS) async with App(configuration) as sut: # Get the extensions before making configuration changes to warm the cache. sut.extensions configuration.extensions.add( ExtensionConfiguration(NonConfigurableExtension)) self.assertIsInstance(sut.extensions[NonConfigurableExtension], NonConfigurableExtension)
async def test_extensions_removal_from_configuration(self) -> None: configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS) configuration.extensions.add( ExtensionConfiguration(NonConfigurableExtension)) async with App(configuration) as sut: # Get the extensions before making configuration changes to warm the cache. sut.extensions del configuration.extensions[NonConfigurableExtension] self.assertNotIn(NonConfigurableExtension, sut.extensions)
def test_getitem(self) -> None: extension_configuration_a = ExtensionConfiguration( ConfigurableExtension) sut = ExtensionsConfiguration([ extension_configuration_a, ]) with assert_in_scope(sut): self.assertEquals(extension_configuration_a, sut[ConfigurableExtension])
def test_add(self) -> None: sut = ExtensionsConfiguration() extension_configuration = ExtensionConfiguration(ConfigurableExtension) with assert_scope_empty(): with assert_reactor_called(sut): sut.add(extension_configuration) self.assertEquals(extension_configuration, sut[ConfigurableExtension]) with assert_reactor_called(sut): extension_configuration.react.trigger()
async def test_post_parse(self) -> None: event = Event('E0', Birth()) with TemporaryDirectory() as output_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.extensions.add(ExtensionConfiguration(Cleaner)) async with App(configuration) as app: app.ancestry.entities.append(event) await load(app) self.assertEquals([], list(app.ancestry.entities[Event]))
def test_delitem(self) -> None: extension_configuration = ExtensionConfiguration(ConfigurableExtension) sut = ExtensionsConfiguration([ extension_configuration, ]) with assert_scope_empty(): with assert_reactor_called(sut): del sut[ConfigurableExtension] self.assertCountEqual([], sut) self.assertCountEqual([], extension_configuration.react._reactors)
def test_should_load_one_extension_without_configuration(self) -> None: with _build_minimal_configuration_dict() as configuration_dict: configuration_dict['extensions'] = { NonConfigurableExtension.name(): {}, } configuration = _from_dict(configuration_dict) expected = ExtensionsConfiguration([ ExtensionConfiguration(NonConfigurableExtension, True), ]) self.assertEquals(expected, configuration.extensions)
async def test_load(self): with TemporaryDirectory() as output_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.extensions.add(ExtensionConfiguration(Demo)) async with App(configuration) as app: await load(app) self.assertNotEqual(0, len(app.ancestry.entities[Person])) self.assertNotEqual(0, len(app.ancestry.entities[Place])) self.assertNotEqual(0, len(app.ancestry.entities[Event])) self.assertNotEqual(0, len(app.ancestry.entities[Source])) self.assertNotEqual(0, len(app.ancestry.entities[Citation]))
async def test_post_parse(self) -> None: person = Person('P0') person.private = True PersonName(person, 'Jane', 'Dough') with TemporaryDirectory() as output_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.extensions.add(ExtensionConfiguration(Anonymizer)) async with App(configuration) as app: app.ancestry.entities.append(person) await load(app) self.assertEquals(0, len(person.names))
def test_should_dump_one_extension_without_configuration(self) -> None: with _build_minimal_configuration() as configuration: configuration.extensions.add( ExtensionConfiguration(NonConfigurableExtension)) configuration_dict = _to_dict(configuration) expected = { NonConfigurableExtension.name(): { 'enabled': True, 'configuration': {}, }, } self.assertEquals(expected, configuration_dict['extensions'])
async def test_extensions_with_one_configurable_extension(self) -> None: configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS) check = 1337 configuration.extensions.add( ExtensionConfiguration( ConfigurableExtension, True, ConfigurableExtensionConfiguration(check=check, ))) async with App(configuration) as sut: self.assertIsInstance(sut.extensions[ConfigurableExtension], ConfigurableExtension) self.assertEquals( check, sut.extensions[ConfigurableExtension]._configuration.check)
async def test_extensions_with_one_extension_with_single_chained_dependency( self) -> None: configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS) configuration.extensions.add( ExtensionConfiguration( DependsOnNonConfigurableExtensionExtensionExtension)) async with App(configuration) as sut: carrier = [] await sut.dispatcher.dispatch(Tracker, 'track')(carrier) self.assertEquals(3, len(carrier)) self.assertEquals(NonConfigurableExtension, type(carrier[0])) self.assertEquals(DependsOnNonConfigurableExtensionExtension, type(carrier[1])) self.assertEquals( DependsOnNonConfigurableExtensionExtensionExtension, type(carrier[2]))
async def test_post_load(self, m_aioresponses) -> None: resource = Source('the_source', 'The Source') link = Link('https://en.wikipedia.org/wiki/Amsterdam') resource.links.add(link) entry_title = 'Amstelredam' entry_extract = 'Capitol of the Netherlands' entry_api_response_body = { 'query': { 'pages': [ { 'title': entry_title, 'extract': entry_extract, }, ], } } entry_api_url = 'https://en.wikipedia.org/w/api.php?action=query&titles=Amsterdam&prop=extracts&exintro&format=json&formatversion=2' m_aioresponses.get(entry_api_url, payload=entry_api_response_body) translations_api_response_body = { 'query': { 'pages': [ { 'langlinks': [], }, ], }, } translations_api_url = 'https://en.wikipedia.org/w/api.php?action=query&titles=Amsterdam&prop=langlinks&lllimit=500&format=json&formatversion=2' m_aioresponses.get(translations_api_url, payload=translations_api_response_body) with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration( output_directory_path, 'https://example.com') configuration.cache_directory_path = Path(cache_directory_path) configuration.extensions.add(ExtensionConfiguration(Wikipedia)) async with App(configuration) as app: app.ancestry.entities.append(resource) await load(app) self.assertEqual(1, len(resource.links)) self.assertEqual(entry_title, link.label) self.assertEqual('en', link.locale) self.assertEqual(MediaType('text/html'), link.media_type) self.assertIsNotNone(link.description) self.assertEqual('external', link.relationship)
def test_should_dump_one_extension_with_configuration(self) -> None: with _build_minimal_configuration() as configuration: configuration.extensions.add( ExtensionConfiguration( ConfigurableExtension, True, ConfigurableExtensionConfiguration( check=1337, default='I will always be there for you.', ))) configuration_dict = _to_dict(configuration) expected = { ConfigurableExtension.name(): { 'enabled': True, 'configuration': { 'check': 1337, 'default': 'I will always be there for you.', }, }, } self.assertEquals(expected, configuration_dict['extensions'])
async def start(self) -> None: self._output_directory = TemporaryDirectory() output_directory_path = await self._output_directory.__aenter__() configuration = Configuration(output_directory_path, 'https://example.com') configuration.extensions.add(ExtensionConfiguration(Demo)) # Include all of the translations Betty ships with. configuration.locales.replace([ LocaleConfiguration('en-US', 'en'), LocaleConfiguration('nl-NL', 'nl'), LocaleConfiguration('fr-FR', 'fr'), LocaleConfiguration('uk', 'uk'), ]) self._app = App(configuration) self._server = None await self._app.activate() await load.load(self._app) await generate.generate(self._app) self._server = serve.AppServer(self._app) await self._server.start()
def test_should_load_one_extension_with_configuration(self) -> None: with _build_minimal_configuration_dict() as configuration_dict: extension_configuration = { 'check': 1337, } configuration_dict['extensions'] = { ConfigurableExtension.name(): { 'configuration': extension_configuration, }, } configuration = _from_dict(configuration_dict) expected = ExtensionsConfiguration([ ExtensionConfiguration( ConfigurableExtension, True, ConfigurableExtensionConfiguration( check=1337, default='I will always be there for you.', )), ]) self.assertEquals(expected, configuration.extensions)
async def test_post_parse(self): person = Person('P0') reference_presence = Presence(person, Subject(), Event(None, Residence())) reference_presence.event.date = Date(1970, 1, 1) with TemporaryDirectory() as output_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.extensions.add(ExtensionConfiguration(Deriver)) async with App(configuration) as app: app.ancestry.entities.append(person) await load(app) self.assertEquals(3, len(person.presences)) self.assertEquals( DateRange(None, Date(1970, 1, 1), end_is_boundary=True), person.start.date) self.assertEquals(DateRange(Date(1970, 1, 1), start_is_boundary=True), person.end.date)
async def test_remove_family_tree(tmpdir, qtbot) -> None: configuration = Configuration(tmpdir, 'https://example.com') configuration.extensions.add( ExtensionConfiguration( Gramps, configuration=GrampsConfiguration(family_trees=ReactiveList([ FamilyTreeConfiguration('/tmp/family-tree.gpkg'), ])), )) async with App(configuration) as app: sut = app.extensions[Gramps] widget = sut.gui_build() qtbot.addWidget(widget) widget.show() qtbot.mouseClick(widget._family_trees_widget._remove_buttons[0], QtCore.Qt.LeftButton) assert len(sut._configuration.family_trees) == 0 assert [] == widget._family_trees_widget._remove_buttons
def _update_enabled(enabled: bool) -> None: try: self._app.configuration.extensions[ extension_type].enabled = enabled except KeyError: self._app.configuration.extensions.add( ExtensionConfiguration( extension_type, enabled, )) if enabled: extension_gui_widget = self._app.extensions[ extension_type].gui_build() if extension_gui_widget is not None: layout.addWidget(extension_gui_widget) else: extension_gui_item = layout.itemAt(1) if extension_gui_item is not None: extension_gui_widget = extension_gui_item.widget() layout.removeWidget(extension_gui_widget) extension_gui_widget.setParent(None) del extension_gui_widget
async def test_add_family_tree_set_path(assert_not_window, assert_window, tmpdir, qtbot) -> None: configuration = Configuration(tmpdir, 'https://example.com') configuration.extensions.add(ExtensionConfiguration(Gramps)) async with App(configuration) as app: sut = app.extensions[Gramps] widget = sut.gui_build() qtbot.addWidget(widget) widget.show() qtbot.mouseClick(widget._add_family_tree_button, QtCore.Qt.LeftButton) add_family_tree_window = assert_window(_AddFamilyTreeWindow) file_path = '/tmp/family-tree.gpkg' add_family_tree_window._widget._file_path.setText(file_path) qtbot.mouseClick(add_family_tree_window._widget._save_and_close, QtCore.Qt.LeftButton) assert_not_window(_AddFamilyTreeWindow) assert len(sut._configuration.family_trees) == 1 family_tree = sut._configuration.family_trees[0] assert family_tree.file_path == Path(file_path)
async def test_add_family_tree_find_path(assert_window, mocker, tmpdir, qtbot) -> None: configuration = Configuration(tmpdir, 'https://example.com') configuration.extensions.add(ExtensionConfiguration(Gramps)) async with App(configuration) as app: sut = app.extensions[Gramps] widget = sut.gui_build() qtbot.addWidget(widget) widget.show() qtbot.mouseClick(widget._add_family_tree_button, QtCore.Qt.LeftButton) add_family_tree_window = assert_window(_AddFamilyTreeWindow) file_path = '/tmp/family-tree.gpkg' mocker.patch.object(QFileDialog, 'getOpenFileName', mocker.MagicMock(return_value=[file_path, None])) qtbot.mouseClick(add_family_tree_window._widget._file_path_find, QtCore.Qt.LeftButton) qtbot.mouseClick(add_family_tree_window._widget._save_and_close, QtCore.Qt.LeftButton) assert len(sut._configuration.family_trees) == 1 family_tree = sut._configuration.family_trees[0] assert family_tree.file_path == Path(file_path)