aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pym/gentoolkit/metadata.py')
-rw-r--r--pym/gentoolkit/metadata.py454
1 files changed, 228 insertions, 226 deletions
diff --git a/pym/gentoolkit/metadata.py b/pym/gentoolkit/metadata.py
index 9dc9619..2678611 100644
--- a/pym/gentoolkit/metadata.py
+++ b/pym/gentoolkit/metadata.py
@@ -31,8 +31,8 @@
'Thomas Mills Hinkle'
"""
-__all__ = ('MetaData',)
-__docformat__ = 'epytext'
+__all__ = ("MetaData",)
+__docformat__ = "epytext"
# =======
# Imports
@@ -48,260 +48,262 @@ from portage import settings
# Classes
# =======
+
class _Maintainer:
- """An object for representing one maintainer.
-
- @type email: str or None
- @ivar email: Maintainer's email address. Used for both Gentoo and upstream.
- @type name: str or None
- @ivar name: Maintainer's name. Used for both Gentoo and upstream.
- @type description: str or None
- @ivar description: Description of what a maintainer does. Gentoo only.
- @type restrict: str or None
- @ivar restrict: e.g. >=portage-2.2 means only maintains versions
- of Portage greater than 2.2. Should be DEPEND string with < and >
- converted to &lt; and &gt; respectively.
- @type status: str or None
- @ivar status: If set, either 'active' or 'inactive'. Upstream only.
- """
-
- def __init__(self, node):
- self.email = None
- self.name = None
- self.description = None
- self.restrict = node.get('restrict')
- self.status = node.get('status')
- for attr in node.iter():
- setattr(self, attr.tag, attr.text)
-
- def __repr__(self):
- return "<%s %r>" % (self.__class__.__name__, self.email)
+ """An object for representing one maintainer.
+
+ @type email: str or None
+ @ivar email: Maintainer's email address. Used for both Gentoo and upstream.
+ @type name: str or None
+ @ivar name: Maintainer's name. Used for both Gentoo and upstream.
+ @type description: str or None
+ @ivar description: Description of what a maintainer does. Gentoo only.
+ @type restrict: str or None
+ @ivar restrict: e.g. &gt;=portage-2.2 means only maintains versions
+ of Portage greater than 2.2. Should be DEPEND string with < and >
+ converted to &lt; and &gt; respectively.
+ @type status: str or None
+ @ivar status: If set, either 'active' or 'inactive'. Upstream only.
+ """
+
+ def __init__(self, node):
+ self.email = None
+ self.name = None
+ self.description = None
+ self.restrict = node.get("restrict")
+ self.status = node.get("status")
+ for attr in node.iter():
+ setattr(self, attr.tag, attr.text)
+
+ def __repr__(self):
+ return "<%s %r>" % (self.__class__.__name__, self.email)
class _Useflag:
- """An object for representing one USE flag.
-
- @todo: Is there any way to have a keyword option to leave in
- <pkg> and <cat> for later processing?
- @type name: str or None
- @ivar name: USE flag
- @type restrict: str or None
- @ivar restrict: e.g. &gt;=portage-2.2 means flag is only avaiable in
- versions greater than 2.2
- @type description: str
- @ivar description: description of the USE flag
- """
-
- def __init__(self, node):
- self.name = node.get('name')
- self.restrict = node.get('restrict')
- _desc = ''
- if node.text:
- _desc = node.text
- for child in node.iter():
- # prevent duplicate text
- if child.text and child.text not in _desc:
- _desc += child.text
- if child.tail and not child.tail in _desc:
- _desc += child.tail
- # This takes care of tabs and newlines left from the file
- self.description = re.sub(r'\s+', ' ', _desc)
-
- def __repr__(self):
- return "<%s %r>" % (self.__class__.__name__, self.name)
+ """An object for representing one USE flag.
+
+ @todo: Is there any way to have a keyword option to leave in
+ <pkg> and <cat> for later processing?
+ @type name: str or None
+ @ivar name: USE flag
+ @type restrict: str or None
+ @ivar restrict: e.g. &gt;=portage-2.2 means flag is only avaiable in
+ versions greater than 2.2
+ @type description: str
+ @ivar description: description of the USE flag
+ """
+
+ def __init__(self, node):
+ self.name = node.get("name")
+ self.restrict = node.get("restrict")
+ _desc = ""
+ if node.text:
+ _desc = node.text
+ for child in node.iter():
+ # prevent duplicate text
+ if child.text and child.text not in _desc:
+ _desc += child.text
+ if child.tail and not child.tail in _desc:
+ _desc += child.tail
+ # This takes care of tabs and newlines left from the file
+ self.description = re.sub(r"\s+", " ", _desc)
+
+ def __repr__(self):
+ return "<%s %r>" % (self.__class__.__name__, self.name)
class _Upstream:
- """An object for representing one package's upstream.
-
- @type maintainers: list
- @ivar maintainers: L{_Maintainer} objects for each upstream maintainer
- @type changelogs: list
- @ivar changelogs: URLs to upstream's ChangeLog file in str format
- @type docs: list
- @ivar docs: Sequence of tuples containing URLs to upstream documentation
- in the first slot and 'lang' attribute in the second, e.g.,
- [('http.../docs/en/tut.html', None), ('http.../doc/fr/tut.html', 'fr')]
- @type bugtrackers: list
- @ivar bugtrackers: URLs to upstream's bugtracker. May also contain an email
- address if prepended with 'mailto:'
- @type remoteids: list
- @ivar remoteids: Sequence of tuples containing the project's hosting site
- name in the first slot and the project's ID name or number for that
- site in the second, e.g., [('sourceforge', 'systemrescuecd')]
- """
-
- def __init__(self, node):
- self.node = node
- self.maintainers = self.upstream_maintainers()
- self.changelogs = self.upstream_changelogs()
- self.docs = self.upstream_documentation()
- self.bugtrackers = self.upstream_bugtrackers()
- self.remoteids = self.upstream_remoteids()
-
- def __repr__(self):
- return "<%s %r>" % (self.__class__.__name__, self.__dict__)
-
- def upstream_bugtrackers(self):
- """Retrieve upstream bugtracker location from xml node."""
- return [e.text for e in self.node.findall('bugs-to')]
-
- def upstream_changelogs(self):
- """Retrieve upstream changelog location from xml node."""
- return [e.text for e in self.node.findall('changelog')]
-
- def upstream_documentation(self):
- """Retrieve upstream documentation location from xml node."""
- result = []
- for elem in self.node.findall('doc'):
- lang = elem.get('lang')
- result.append((elem.text, lang))
- return result
-
- def upstream_maintainers(self):
- """Retrieve upstream maintainer information from xml node."""
- return [_Maintainer(m) for m in self.node.findall('maintainer')]
-
- def upstream_remoteids(self):
- """Retrieve upstream remote ID from xml node."""
- return [(e.text, e.get('type')) for e in self.node.findall('remote-id')]
+ """An object for representing one package's upstream.
+
+ @type maintainers: list
+ @ivar maintainers: L{_Maintainer} objects for each upstream maintainer
+ @type changelogs: list
+ @ivar changelogs: URLs to upstream's ChangeLog file in str format
+ @type docs: list
+ @ivar docs: Sequence of tuples containing URLs to upstream documentation
+ in the first slot and 'lang' attribute in the second, e.g.,
+ [('http.../docs/en/tut.html', None), ('http.../doc/fr/tut.html', 'fr')]
+ @type bugtrackers: list
+ @ivar bugtrackers: URLs to upstream's bugtracker. May also contain an email
+ address if prepended with 'mailto:'
+ @type remoteids: list
+ @ivar remoteids: Sequence of tuples containing the project's hosting site
+ name in the first slot and the project's ID name or number for that
+ site in the second, e.g., [('sourceforge', 'systemrescuecd')]
+ """
+
+ def __init__(self, node):
+ self.node = node
+ self.maintainers = self.upstream_maintainers()
+ self.changelogs = self.upstream_changelogs()
+ self.docs = self.upstream_documentation()
+ self.bugtrackers = self.upstream_bugtrackers()
+ self.remoteids = self.upstream_remoteids()
+
+ def __repr__(self):
+ return "<%s %r>" % (self.__class__.__name__, self.__dict__)
+
+ def upstream_bugtrackers(self):
+ """Retrieve upstream bugtracker location from xml node."""
+ return [e.text for e in self.node.findall("bugs-to")]
+
+ def upstream_changelogs(self):
+ """Retrieve upstream changelog location from xml node."""
+ return [e.text for e in self.node.findall("changelog")]
+
+ def upstream_documentation(self):
+ """Retrieve upstream documentation location from xml node."""
+ result = []
+ for elem in self.node.findall("doc"):
+ lang = elem.get("lang")
+ result.append((elem.text, lang))
+ return result
+
+ def upstream_maintainers(self):
+ """Retrieve upstream maintainer information from xml node."""
+ return [_Maintainer(m) for m in self.node.findall("maintainer")]
+
+ def upstream_remoteids(self):
+ """Retrieve upstream remote ID from xml node."""
+ return [(e.text, e.get("type")) for e in self.node.findall("remote-id")]
class MetaData:
- """Access metadata.xml"""
-
- def __init__(self, metadata_path):
- """Parse a valid metadata.xml file.
-
- @type metadata_path: str
- @param metadata_path: path to a valid metadata.xml file
- @raise IOError: if C{metadata_path} can not be read
- """
-
- self.metadata_path = metadata_path
- self._xml_tree = etree.parse(metadata_path)
-
- # Used for caching
- self._herdstree = None
- self._descriptions = None
- self._maintainers = None
- self._useflags = None
- self._upstream = None
-
- def __repr__(self):
- return "<%s %r>" % (self.__class__.__name__, self.metadata_path)
+ """Access metadata.xml"""
+
+ def __init__(self, metadata_path):
+ """Parse a valid metadata.xml file.
+
+ @type metadata_path: str
+ @param metadata_path: path to a valid metadata.xml file
+ @raise IOError: if C{metadata_path} can not be read
+ """
+
+ self.metadata_path = metadata_path
+ self._xml_tree = etree.parse(metadata_path)
+
+ # Used for caching
+ self._herdstree = None
+ self._descriptions = None
+ self._maintainers = None
+ self._useflags = None
+ self._upstream = None
+
+ def __repr__(self):
+ return "<%s %r>" % (self.__class__.__name__, self.metadata_path)
+
+ def _get_herd_email(self, herd):
+ """Get a herd's email address.
+
+ @type herd: str
+ @param herd: herd whose email you want
+ @rtype: str or None
+ @return: email address or None if herd is not in herds.xml
+ @raise IOError: if $PORTDIR/metadata/herds.xml can not be read
+ """
+
+ if self._herdstree is None:
+ herds_path = os.path.join(settings["PORTDIR"], "metadata/herds.xml")
+ try:
+ self._herdstree = etree.parse(herds_path)
+ except IOError:
+ # For some trees, herds.xml may not exist. Bug #300108.
+ return None
+
+ # Some special herds are not listed in herds.xml
+ if herd in ("no-herd", "maintainer-wanted", "maintainer-needed"):
+ return None
+
+ for node in self._herdstree.iter("herd"):
+ if node.findtext("name") == herd:
+ return node.findtext("email")
+
+ def herds(self, include_email=False):
+ """Return a list of text nodes for <herd>.
+
+ @type include_email: bool
+ @keyword include_email: if True, also look up the herd's email
+ @rtype: list
+ @return: if include_email is False, return a list of strings;
+ if include_email is True, return a list of tuples containing:
+ [('herd1', 'herd1@gentoo.org'), ('no-herd', None);
+ """
+
+ result = []
+ for elem in self._xml_tree.findall("herd"):
+ text = elem.text
+ if text is None:
+ text = ""
+ if include_email:
+ herd_mail = self._get_herd_email(text)
+ result.append((text, herd_mail))
+ else:
+ result.append(text)
- def _get_herd_email(self, herd):
- """Get a herd's email address.
-
- @type herd: str
- @param herd: herd whose email you want
- @rtype: str or None
- @return: email address or None if herd is not in herds.xml
- @raise IOError: if $PORTDIR/metadata/herds.xml can not be read
- """
-
- if self._herdstree is None:
- herds_path = os.path.join(settings['PORTDIR'], 'metadata/herds.xml')
- try:
- self._herdstree = etree.parse(herds_path)
- except IOError:
- # For some trees, herds.xml may not exist. Bug #300108.
- return None
+ return result
- # Some special herds are not listed in herds.xml
- if herd in ('no-herd', 'maintainer-wanted', 'maintainer-needed'):
- return None
+ def descriptions(self):
+ """Return a list of text nodes for <longdescription>.
- for node in self._herdstree.iter('herd'):
- if node.findtext('name') == herd:
- return node.findtext('email')
+ @rtype: list
+ @return: package description in string format
+ @todo: Support the C{lang} attribute
+ """
- def herds(self, include_email=False):
- """Return a list of text nodes for <herd>.
+ if self._descriptions is not None:
+ return self._descriptions
- @type include_email: bool
- @keyword include_email: if True, also look up the herd's email
- @rtype: list
- @return: if include_email is False, return a list of strings;
- if include_email is True, return a list of tuples containing:
- [('herd1', 'herd1@gentoo.org'), ('no-herd', None);
- """
+ long_descriptions = self._xml_tree.findall("longdescription")
+ self._descriptions = [e.text for e in long_descriptions]
+ return self._descriptions
- result = []
- for elem in self._xml_tree.findall('herd'):
- text = elem.text
- if text is None:
- text = ''
- if include_email:
- herd_mail = self._get_herd_email(text)
- result.append((text, herd_mail))
- else:
- result.append(text)
+ def maintainers(self):
+ """Get maintainers' name, email and description.
- return result
+ @rtype: list
+ @return: a sequence of L{_Maintainer} objects in document order.
+ """
- def descriptions(self):
- """Return a list of text nodes for <longdescription>.
+ if self._maintainers is not None:
+ return self._maintainers
- @rtype: list
- @return: package description in string format
- @todo: Support the C{lang} attribute
- """
+ self._maintainers = []
+ for node in self._xml_tree.findall("maintainer"):
+ self._maintainers.append(_Maintainer(node))
- if self._descriptions is not None:
- return self._descriptions
+ return self._maintainers
- long_descriptions = self._xml_tree.findall("longdescription")
- self._descriptions = [e.text for e in long_descriptions]
- return self._descriptions
+ def use(self):
+ """Get names and descriptions for USE flags defined in metadata.
- def maintainers(self):
- """Get maintainers' name, email and description.
+ @rtype: list
+ @return: a sequence of L{_Useflag} objects in document order.
+ """
- @rtype: list
- @return: a sequence of L{_Maintainer} objects in document order.
- """
+ if self._useflags is not None:
+ return self._useflags
- if self._maintainers is not None:
- return self._maintainers
+ self._useflags = []
+ for node in self._xml_tree.iter("flag"):
+ self._useflags.append(_Useflag(node))
- self._maintainers = []
- for node in self._xml_tree.findall('maintainer'):
- self._maintainers.append(_Maintainer(node))
+ return self._useflags
- return self._maintainers
-
- def use(self):
- """Get names and descriptions for USE flags defined in metadata.
-
- @rtype: list
- @return: a sequence of L{_Useflag} objects in document order.
- """
-
- if self._useflags is not None:
- return self._useflags
-
- self._useflags = []
- for node in self._xml_tree.iter('flag'):
- self._useflags.append(_Useflag(node))
+ def upstream(self):
+ """Get upstream contact information.
- return self._useflags
+ @rtype: list
+ @return: a sequence of L{_Upstream} objects in document order.
+ """
- def upstream(self):
- """Get upstream contact information.
+ if self._upstream is not None:
+ return self._upstream
- @rtype: list
- @return: a sequence of L{_Upstream} objects in document order.
- """
-
- if self._upstream is not None:
- return self._upstream
+ self._upstream = []
+ for node in self._xml_tree.findall("upstream"):
+ self._upstream.append(_Upstream(node))
- self._upstream = []
- for node in self._xml_tree.findall('upstream'):
- self._upstream.append(_Upstream(node))
+ return self._upstream
- return self._upstream
# vim: set ts=4 sw=4 tw=79: