class FilterImageTest(TemplateTestCase): image_path = path.join(path.dirname(path.dirname(__file__)), 'assets', 'public', 'static', 'betty-512x512.png') @parameterized.expand([ ('/file/F1-99x-.png', '{{ file | image(width=99) }}', File('F1', image_path, media_type=MediaType('image/png'))), ('/file/F1--x99.png', '{{ file | image(height=99) }}', File('F1', image_path, media_type=MediaType('image/png'))), ('/file/F1-99x99.png', '{{ file | image(width=99, height=99) }}', File('F1', image_path, media_type=MediaType('image/png'))), ('/file/F1-99x99.png:/file/F1-99x99.png', '{{ file | image(width=99, height=99) }}:{{ file | image(width=99, height=99) }}', File('F1', image_path, media_type=MediaType('image/png'))), ]) @sync async def test(self, expected, template, file): async with self._render(template_string=template, data={ 'file': file, }) as (actual, site): self.assertEquals(expected, actual) for file_path in actual.split(':'): self.assertTrue(path.exists(path.join(site.configuration.www_directory_path, file_path[1:]))) @sync async def test_without_width(self): file = File('F1', self.image_path, media_type=MediaType('image/png')) with self.assertRaises(ValueError): async with self._render(template_string='{{ file | image }}', data={ 'file': file, }): pass
async def test_populate_should_populate_existing_link(self, m_retriever) -> None: entry_language = 'en' entry_name = 'Amsterdam' entry_title = 'Amsterdam' entry_content = 'Capitol of the Netherlands' entry = Entry(entry_language, entry_name, entry_title, entry_content) m_retriever.get_entry.return_value = entry resource = IdentifiableSource('the_source', 'The Source') link = Link('https://en.wikipedia.org/wiki/Amsterdam') resource.links.add(link) with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: site.ancestry.sources[resource.id] = resource sut = _Populator(site, m_retriever) await sut.populate() m_retriever.get_entry.assert_called_once_with(entry_language, entry_name) self.assertEqual(1, len(resource.links)) self.assertEqual('Amsterdam', link.label) self.assertEqual('en', link.locale) self.assertEqual(MediaType('text/html'), link.media_type) self.assertIsNotNone(link.description) self.assertEqual('external', link.relationship)
async def test_without_width(self): file = File('F1', self.image_path, media_type=MediaType('image/png')) with self.assertRaises(ValueError): async with self._render(template_string='{{ file | image }}', data={ 'file': file, }): pass
def test_media_type(self) -> None: file_id = 'BETTY01' file_path = '/tmp/betty' sut = File(file_id, file_path) self.assertIsNone(sut.media_type) media_type = MediaType('text/plain') sut.media_type = media_type self.assertEquals(media_type, sut.media_type)
def test(self, expected_type: str, expected_subtype: str, expected_subtypes: List[str], expected_suffix: Optional[str], expected_parameters: Dict[str, str], media_type: str): sut = MediaType(media_type) self.assertEquals(expected_type, sut.type) self.assertEquals(expected_subtype, sut.subtype) self.assertEquals(expected_subtypes, sut.subtypes) self.assertEquals(expected_suffix, sut.suffix) self.assertEquals(expected_parameters, sut.parameters) self.assertEquals(media_type, str(sut))
async def test_populate_should_add_translation_links(self, m_retriever) -> None: entry_language = 'en' entry_name = 'Amsterdam' entry_title = 'Amsterdam' entry_content = 'Capitol of the Netherlands' entry = Entry(entry_language, entry_name, entry_title, entry_content) added_entry_language = 'nl' added_entry_name = 'Amsterdam' added_entry_title = 'Amsterdam' added_entry_content = 'Hoofdstad van Nederland' added_entry = Entry(added_entry_language, added_entry_name, added_entry_title, added_entry_content) m_retriever.get_entry.side_effect = [entry, added_entry] m_retriever.get_translations.return_value = { entry_language: entry_name, added_entry_language: added_entry_name, } resource = IdentifiableSource('the_source', 'The Source') link_en = Link('https://en.wikipedia.org/wiki/Amsterdam') resource.links.add(link_en) with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path configuration.locales.clear() configuration.locales['en-US'] = LocaleConfiguration( 'en-US', 'en') configuration.locales['nl-NL'] = LocaleConfiguration( 'nl-NL', 'nl') async with Site(configuration) as site: site.ancestry.sources[resource.id] = resource sut = _Populator(site, m_retriever) await sut.populate() m_retriever.get_entry.assert_has_calls([ call(entry_language, entry_name), call(added_entry_language, added_entry_name), ]) m_retriever.get_translations.assert_called_once_with( entry_language, entry_name) self.assertEqual(2, len(resource.links)) link_nl = resource.links.difference({link_en}).pop() self.assertEqual('Amsterdam', link_nl.label) self.assertEqual('nl', link_nl.locale) self.assertEqual(MediaType('text/html'), link_nl.media_type) self.assertIsNotNone(link_nl.description) self.assertEqual('external', link_nl.relationship)
def test_link_should_encode_full(self) -> None: link = Link('https://example.com') link.label = 'The Link' link.relationship = 'external' link.locale = 'nl-NL' link.media_type = MediaType('text/html') expected = { 'url': 'https://example.com', 'relationship': 'external', 'label': 'The Link', 'locale': 'nl-NL', 'mediaType': 'text/html', } self.assert_encodes(expected, link, 'link')
def _load_object(loader: _Loader, element: ElementTree.Element, gramps_tree_directory_path): handle = element.get('handle') entity_id = element.get('id') file_element = _xpath1(element, './ns:file') file_path = path.join(gramps_tree_directory_path, file_element.get('src')) file = File(entity_id, file_path) file.media_type = MediaType(file_element.get('mime')) description = file_element.get('description') if description: file.description = description note_handle_elements = _xpath(element, './ns:noteref') for note_handle_element in note_handle_elements: file.notes.append(loader._notes[note_handle_element.get('hlink')]) _load_attribute_privacy(file, element, 'attribute') loader._files[handle] = _IntermediateFile(file, _load_citationref_as_handles(element))
async def test_post_parse(self, m_aioresponses) -> None: resource = IdentifiableSource('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 = cache_directory_path configuration.plugins[Wikipedia] = None async with Site(configuration) as site: site.ancestry.sources[resource.id] = resource await parse(site) 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 _parse_object(ancestry: _IntermediateAncestry, element: Element, gramps_directory_path): handle = _xpath1(element, './@handle') entity_id = str(_xpath1(element, './@id')) file_element = _xpath1(element, './ns:file') file_path = path.join(gramps_directory_path, str(_xpath1(file_element, './@src'))) file = File(entity_id, file_path) file.media_type = MediaType(str(_xpath1(file_element, './@mime'))) description = str(_xpath1(file_element, './@description')) if description: file.description = description note_handles = _xpath(element, './ns:noteref/@hlink') for note_handle in note_handles: file.notes.append(ancestry.notes[note_handle]) _parse_attribute_privacy(file, element, 'attribute') ancestry.files[handle] = file
def _load_object(loader: _Loader, element: ElementTree.Element, gramps_tree_directory_path: Path): file_handle = element.get('handle') file_id = element.get('id') file_element = _xpath1(element, './ns:file') file_path = gramps_tree_directory_path / file_element.get('src') file = File(file_id, file_path) file.media_type = MediaType(file_element.get('mime')) description = file_element.get('description') if description: file.description = description _load_attribute_privacy(file, element, 'attribute') loader.add_entity(FlattenedEntity(file, file_handle)) for citation_handle in _load_handles('citationref', element): loader.add_association(File, file_handle, 'citations', Citation, citation_handle) for note_handle in _load_handles('noteref', element): loader.add_association(File, file_handle, 'notes', Note, note_handle)
async def populate_link(self, link: Link, entry_language: str, entry: Optional[Entry] = None) -> None: if link.url.startswith('http:'): link.url = 'https:' + link.url[5:] if link.media_type is None: link.media_type = MediaType('text/html') if link.relationship is None: link.relationship = 'external' if link.locale is None: link.locale = entry_language if link.description is None: # There are valid reasons for links in locales that aren't supported. with suppress(ValueError): async with self._app.with_locale(link.locale): link.description = _('Read more on Wikipedia.') if entry is not None and link.label is None: link.label = entry.title
def test_file_should_encode_full(self): with NamedTemporaryFile() as f: note = Note('the_note', 'The Note') file = File('the_file', f.name) file.media_type = MediaType('text/plain') file.notes.append(note) Person('the_person').files.append(file) expected = { '$schema': '/schema.json#/definitions/file', 'id': 'the_file', 'mediaType': 'text/plain', 'resources': [ '/en/person/the_person/index.json', ], 'notes': [ '/en/note/the_note/index.json', ], 'links': [ { 'url': '/en/file/the_file/index.json', 'relationship': 'canonical', 'mediaType': 'application/json', }, { 'url': '/nl/file/the_file/index.json', 'relationship': 'alternate', 'locale': 'nl-NL', }, { 'url': '/en/file/the_file/index.html', 'relationship': 'alternate', 'mediaType': 'text/html', }, ], } self.assert_encodes(expected, file, 'file')
class PopulatorTest(TestCase): @patch('betty.plugin.wikipedia.Retriever') @sync async def test_populate_link_should_convert_http_to_https( self, m_retriever) -> None: link = Link('http://en.wikipedia.org/wiki/Amsterdam') entry_language = 'nl' with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: sut = _Populator(site, m_retriever) await sut.populate_link(link, entry_language) self.assertEqual('https://en.wikipedia.org/wiki/Amsterdam', link.url) @parameterized.expand([ (MediaType('text/plain'), MediaType('text/plain')), (MediaType('text/html'), MediaType('text/html')), (MediaType('text/html'), None), ]) @patch('betty.plugin.wikipedia.Retriever') @sync async def test_populate_link_should_set_media_type( self, expected: MediaType, media_type: Optional[MediaType], m_retriever) -> None: link = Link('http://en.wikipedia.org/wiki/Amsterdam') link.media_type = media_type with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: sut = _Populator(site, m_retriever) await sut.populate_link(link, 'en') self.assertEqual(expected, link.media_type) @parameterized.expand([ ('alternate', 'alternate'), ('external', 'external'), ('external', None), ]) @patch('betty.plugin.wikipedia.Retriever') @sync async def test_populate_link_should_set_relationship( self, expected: str, relationship: Optional[str], m_retriever) -> None: link = Link('http://en.wikipedia.org/wiki/Amsterdam') link.relationship = relationship with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: sut = _Populator(site, m_retriever) await sut.populate_link(link, 'en') self.assertEqual(expected, link.relationship) @parameterized.expand([ ('nl-NL', 'nl', 'nl-NL'), ('nl', 'nl', None), ('nl', 'en', 'nl'), ]) @patch('betty.plugin.wikipedia.Retriever') @sync async def test_populate_link_should_set_locale(self, expected: str, entry_language: str, locale: Optional[str], m_retriever) -> None: link = Link('http://%s.wikipedia.org/wiki/Amsterdam' % entry_language) link.locale = locale with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: sut = _Populator(site, m_retriever) await sut.populate_link(link, entry_language) self.assertEqual(expected, link.locale) @parameterized.expand([ ('This is the original description', 'This is the original description'), ('Read more on Wikipedia.', None), ]) @patch('betty.plugin.wikipedia.Retriever') @sync async def test_populate_link_should_set_description( self, expected: str, description: str, m_retriever) -> None: link = Link('http://en.wikipedia.org/wiki/Amsterdam') link.description = description entry_language = 'en' with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: sut = _Populator(site, m_retriever) await sut.populate_link(link, entry_language) self.assertEqual(expected, link.description) @parameterized.expand([ ('Amsterdam', 'Amsterdam'), ('The city of Amsterdam', None), ]) @patch('betty.plugin.wikipedia.Retriever') @sync async def test_populate_link_should_set_label(self, expected: str, label: Optional[str], m_retriever) -> None: link = Link('http://en.wikipedia.org/wiki/Amsterdam') link.label = label entry = Entry('en', 'The_city_of_Amsterdam', 'The city of Amsterdam', 'Amsterdam, such a lovely place!') with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: sut = _Populator(site, m_retriever) await sut.populate_link(link, 'en', entry) self.assertEqual(expected, link.label) @patch('betty.plugin.wikipedia.Retriever') @sync async def test_populate_should_ignore_resource_without_link_support( self, m_retriever) -> None: source = Source('The Source') resource = IdentifiableCitation('the_citation', source) with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: site.ancestry.citations[resource.id] = resource sut = _Populator(site, m_retriever) await sut.populate() @patch('betty.plugin.wikipedia.Retriever') @sync async def test_populate_should_ignore_resource_without_links( self, m_retriever) -> None: resource = IdentifiableSource('the_source', 'The Source') with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: site.ancestry.sources[resource.id] = resource sut = _Populator(site, m_retriever) await sut.populate() self.assertSetEqual(set(), resource.links) @patch('betty.plugin.wikipedia.Retriever') @sync async def test_populate_should_ignore_non_wikipedia_links( self, m_retriever) -> None: link = Link('https://example.com') resource = IdentifiableSource('the_source', 'The Source') resource.links.add(link) with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: site.ancestry.sources[resource.id] = resource sut = _Populator(site, m_retriever) await sut.populate() self.assertSetEqual({link}, resource.links) @patch('betty.plugin.wikipedia.Retriever', spec=Retriever, new_callable=AsyncMock) @sync async def test_populate_should_populate_existing_link(self, m_retriever) -> None: entry_language = 'en' entry_name = 'Amsterdam' entry_title = 'Amsterdam' entry_content = 'Capitol of the Netherlands' entry = Entry(entry_language, entry_name, entry_title, entry_content) m_retriever.get_entry.return_value = entry resource = IdentifiableSource('the_source', 'The Source') link = Link('https://en.wikipedia.org/wiki/Amsterdam') resource.links.add(link) with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path async with Site(configuration) as site: site.ancestry.sources[resource.id] = resource sut = _Populator(site, m_retriever) await sut.populate() m_retriever.get_entry.assert_called_once_with(entry_language, entry_name) self.assertEqual(1, len(resource.links)) self.assertEqual('Amsterdam', link.label) self.assertEqual('en', link.locale) self.assertEqual(MediaType('text/html'), link.media_type) self.assertIsNotNone(link.description) self.assertEqual('external', link.relationship) @patch('betty.plugin.wikipedia.Retriever', spec=Retriever, new_callable=AsyncMock) @sync async def test_populate_should_add_translation_links(self, m_retriever) -> None: entry_language = 'en' entry_name = 'Amsterdam' entry_title = 'Amsterdam' entry_content = 'Capitol of the Netherlands' entry = Entry(entry_language, entry_name, entry_title, entry_content) added_entry_language = 'nl' added_entry_name = 'Amsterdam' added_entry_title = 'Amsterdam' added_entry_content = 'Hoofdstad van Nederland' added_entry = Entry(added_entry_language, added_entry_name, added_entry_title, added_entry_content) m_retriever.get_entry.side_effect = [entry, added_entry] m_retriever.get_translations.return_value = { entry_language: entry_name, added_entry_language: added_entry_name, } resource = IdentifiableSource('the_source', 'The Source') link_en = Link('https://en.wikipedia.org/wiki/Amsterdam') resource.links.add(link_en) with TemporaryDirectory() as output_directory_path: with TemporaryDirectory() as cache_directory_path: configuration = Configuration(output_directory_path, 'https://example.com') configuration.cache_directory_path = cache_directory_path configuration.locales.clear() configuration.locales['en-US'] = LocaleConfiguration( 'en-US', 'en') configuration.locales['nl-NL'] = LocaleConfiguration( 'nl-NL', 'nl') async with Site(configuration) as site: site.ancestry.sources[resource.id] = resource sut = _Populator(site, m_retriever) await sut.populate() m_retriever.get_entry.assert_has_calls([ call(entry_language, entry_name), call(added_entry_language, added_entry_name), ]) m_retriever.get_translations.assert_called_once_with( entry_language, entry_name) self.assertEqual(2, len(resource.links)) link_nl = resource.links.difference({link_en}).pop() self.assertEqual('Amsterdam', link_nl.label) self.assertEqual('nl', link_nl.locale) self.assertEqual(MediaType('text/html'), link_nl.media_type) self.assertIsNotNone(link_nl.description) self.assertEqual('external', link_nl.relationship)
def test_invalid_type_should_raise_value_error(self, media_type: str): with self.assertRaises(InvalidMediaType): MediaType(media_type)