Skip to content

Commit

Permalink
appstream: extract title and version
Browse files Browse the repository at this point in the history
This PR extracts title and version from AppStream's name tag and
from the version property of the first release tag.

According to the AppStream docs:

> name: A human-readable name for this software component. For
> example, if the component ID was "libc", its name might be
> "GNU Standard C Library".

> Each release of the software component should have a <release/>
> tag describing it, but at least one release child must be present
> for the current release of the software. The release children
> should be sorted in a latest-to-oldest order to simplify reading
> the metadata file.
  • Loading branch information
merlijn-sebrechts committed Oct 22, 2019
1 parent 93503ac commit 1800f3f
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 0 deletions.
13 changes: 13 additions & 0 deletions snapcraft/extractors/_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def __init__(
self,
*,
common_id: str = "",
title: str = "",
summary: str = "",
description: str = "",
version: str = "",
Expand All @@ -39,6 +40,7 @@ def __init__(
:param str: common_id: The common identifier across multiple packaging
formats
:param str title: Extracted title
:param str summary: Extracted summary
:param str description: Extracted description
:param str version: Extracted version
Expand All @@ -52,6 +54,8 @@ def __init__(

if common_id:
self._data["common_id"] = common_id
if title:
self._data["title"] = title
if summary:
self._data["summary"] = summary
if description:
Expand Down Expand Up @@ -87,6 +91,15 @@ def get_common_id(self) -> str:
common_id = self._data.get("common_id")
return str(common_id) if common_id else None

def get_title(self) -> str:
"""Return extracted title.
:returns: Extracted title
:rtype: str
"""
title = self._data.get("title")
return str(title) if title else None

def get_summary(self) -> str:
"""Return extracted summary.
Expand Down
11 changes: 11 additions & 0 deletions snapcraft/extractors/appstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ def extract(relpath: str, *, workdir: str) -> ExtractedMetadata:
common_id = _get_value_from_xml_element(dom, "id")
summary = _get_value_from_xml_element(dom, "summary")
description = _get_value_from_xml_element(dom, "description")
title = _get_value_from_xml_element(dom, "name")
version = _get_latest_release_from_nodes(dom.findall("releases/release"))

desktop_file_paths = []
desktop_file_ids = _get_desktop_file_ids_from_nodes(dom.findall("launchable"))
Expand All @@ -99,8 +101,10 @@ def extract(relpath: str, *, workdir: str) -> ExtractedMetadata:

return ExtractedMetadata(
common_id=common_id,
title=title,
summary=summary,
description=description,
version=version,
icon=icon,
desktop_file_paths=desktop_file_paths,
)
Expand Down Expand Up @@ -136,6 +140,13 @@ def _get_value_from_xml_element(tree, key) -> Optional[str]:
return None


def _get_latest_release_from_nodes(nodes) -> Optional[str]:
for node in nodes:
if "version" in node.attrib:
return node.attrib["version"]
return None


def _get_desktop_file_ids_from_nodes(nodes) -> List[str]:
desktop_file_ids = [] # type: List[str]
for node in nodes:
Expand Down
81 changes: 81 additions & 0 deletions tests/unit/extractors/test_appstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ class AppstreamTestCase(unit.TestCase):
"expect": "test-id",
},
),
(
"title",
{
"key": "name",
"attributes": {},
"param_name": "title",
"value": "test-title",
"expect": "test-title",
},
),
],
[
("metainfo", {"file_extension": "metainfo.xml"}),
Expand Down Expand Up @@ -457,6 +467,77 @@ def test_appstream_with_ul_in_p(self):
),
)

def test_appstream_multilang_title(self):
file_name = "foliate.appdata.xml"
content = textwrap.dedent(
"""\
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<name>Foliate</name>
<name xml:lang="id_ID">Foliate_id</name>
<name xml:lang="pt_BR">Foliate_pt</name>
<name xml:lang="ru_RU">Foliate_ru</name>
<name xml:lang="nl_NL">Foliate_nl</name>
<name xml:lang="fr_FR">Foliate_fr</name>
<name xml:lang="cs_CS">Foliate_cs</name>
</component>
"""
)

with open(file_name, "w") as f:
print(content, file=f)

metadata = appstream.extract(file_name, workdir=".")

self.expectThat(metadata.get_title(), Equals("Foliate"))

def test_appstream_release(self):
file_name = "foliate.appdata.xml"
content = textwrap.dedent(
"""\
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<releases>
<release version="1.5.3" date="2019-07-25">
<description>
<ul>
<li>Fixed Flatpak version not being able to open .mobi, .azw, and .azw3 files</li>
<li>Improved Wiktionary lookup, now with links and example sentences</li>
<li>Improved popover footnote extraction and formatting</li>
<li>Added option to export annotations to BibTeX</li>
</ul>
</description>
</release>
<release version="1.5.2" date="2019-07-19">
<description>
<ul>
<li>Fixed table of contents navigation not working with some books</li>
<li>Fixed not being able to zoom images with Kindle books</li>
<li>Fixed not being able to open books with .epub3 filename extension</li>
<li>Fixed temporary directory not being cleaned after closing</li>
</ul>
</description>
</release>
<release version="1.5.1" date="2019-07-17">
<description>
<ul>
<li>Fixed F9 shortcut not working</li>
<li>Updated translations</li>
</ul>
</description>
</release>
</releases>
</component>
"""
)

with open(file_name, "w") as f:
print(content, file=f)

metadata = appstream.extract(file_name, workdir=".")

self.expectThat(metadata.get_version(), Equals("1.5.3"))


class AppstreamUnhandledFileTestCase(unit.TestCase):
def test_unhandled_file_test_case(self):
Expand Down

0 comments on commit 1800f3f

Please sign in to comment.