aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Erdmann <dywi@mailerd.de>2012-06-15 22:21:26 +0200
committerAndré Erdmann <dywi@mailerd.de>2012-06-15 22:21:26 +0200
commit09dca3f1c3677a834841c1d2c9e2ac40e54459b2 (patch)
tree5149c6871d800d3c32c518e2dc1b2d63000a8602
parentrun_config uses visualize() now (diff)
downloadR_overlay-09dca3f1c3677a834841c1d2c9e2ac40e54459b2.tar.gz
R_overlay-09dca3f1c3677a834841c1d2c9e2ac40e54459b2.tar.bz2
R_overlay-09dca3f1c3677a834841c1d2c9e2ac40e54459b2.zip
metadata: comments/fixes/enhancements
modified: roverlay/portage/metadata/abstractnodes.py modified: roverlay/portage/metadata/creation.py modified: roverlay/portage/metadata/nodes.py
-rw-r--r--roverlay/portage/metadata/abstractnodes.py92
-rw-r--r--roverlay/portage/metadata/creation.py21
-rw-r--r--roverlay/portage/metadata/nodes.py83
3 files changed, 182 insertions, 14 deletions
diff --git a/roverlay/portage/metadata/abstractnodes.py b/roverlay/portage/metadata/abstractnodes.py
index 487d26d..50c9f56 100644
--- a/roverlay/portage/metadata/abstractnodes.py
+++ b/roverlay/portage/metadata/abstractnodes.py
@@ -10,19 +10,37 @@ get_indent = lambda k : k * INDENT
# -- "abstract" metadata nodes --
class _MetadataBasicNode ( object ):
+ """
+ This is the most basic metadata node that should never be used directly.
+ """
def __init__ ( self, name, flags ):
+ """Initializes a _MetadataBasicNode.
+
+ arguments:
+ * name -- name of this node, e.g. 'flag'
+ * flags -- flags of this node, e.g. 'name=byte-compile'
+ """
self.name = name
self.flags = flags
+ # priority is used to sort nodes (e.g. longdescription after description)
self.priority = 1000
self._enabled = True
self._set_level ( 0 )
# --- end of __init__ (...) ---
def active ( self ):
+ """Returns True if this node is active."""
return self._enabled
+ # --- end of active (...) ---
def _set_level ( self, _level, has_indent=True ):
+ """Sets the level (depth) of this node.
+
+ arguments:
+ * _level -- level to set
+ * has_indent -- if this node should indent its subnodes (or text)
+ """
self.level = _level
if has_indent:
self.indent = get_indent ( self.level )
@@ -31,14 +49,25 @@ class _MetadataBasicNode ( object ):
# --- end of _set_level (...) ---
def set_flag ( self, flagname, flagvalue=None ):
+ """Sets the specified flag.
+
+ arguments:
+ * flagname -- flag name
+ * flagvalue -- flag value, defaults to None->''
+ """
self.flags [flagname] = '' if flagvalue is None else flagvalue
# --- end of set_flag (...) ---
def _flaglist ( self ):
- return [ '%s="%s"' % ftup for ftup in self.flags.items() ]
+ """Returns a "flagname=flagvalue" list."""
+ return [ '%s="%s"' % ftup for ftup in self.flags.items() ]
# --- end of _flaglist (...) ---
+
def _flagstr ( self ):
+ """Returns the string representation of this node's flags, including
+ a leading whitespace char.
+ """
if self.flags is None:
return ''
@@ -51,12 +80,17 @@ class _MetadataBasicNode ( object ):
# --- end of _flagstr (...) ---
def _do_verify ( self ):
+ """Verifies this node.
+ Does nothing if self._verify is not implemented, else dies on error.
+ """
if hasattr ( self, '_verify' ) and not self._verify():
# todo, verify could return ( Status, ErrorMessages ) etc.
raise Exception ( "verification failed for a metadata node." )
+ # --- end of _do_verify (...) ---
- # not using __repr__, make (recursive) node calls explicit
+ # not using __str__, make (recursive) node calls explicit
def to_str ( self ):
+ """Returns a string representing this node."""
self._do_verify()
return "%s<%s%s></%s>" % (
@@ -65,9 +99,11 @@ class _MetadataBasicNode ( object ):
self._flagstr(),
self.name
)
+ # --- end of to_str (...) ---
class MetadataNode ( _MetadataBasicNode ):
+ """A _MetadataBasicNode with child nodes."""
def __init__ ( self, name, flags=dict() ):
super ( MetadataNode, self ) . __init__ ( name, flags )
@@ -75,15 +111,25 @@ class MetadataNode ( _MetadataBasicNode ):
# --- end of __init__ (...) ---
def add ( self, node ):
+ """Adds a child node to this node. Fixes/sets the level of this node.
+
+ arguments:
+ * node --
+ """
node._set_level ( self.level + 1 )
self.nodes.append ( node )
+ # --- end of add (...) ---
+ # copy add to _add_node
_add_node = add
def _sort_nodes ( self ):
+ """Sorts the child nodes of this node."""
self.nodes.sort ( key=lambda node : node.priority )
+ # --- end of _sort_nodes (...) ---
def _nodelist ( self ):
+ """Returns a list of strings representing the child nodes."""
return list (
filter (
None,
@@ -93,16 +139,19 @@ class MetadataNode ( _MetadataBasicNode ):
# --- end of _nodelist (...) ---
def _nodestr ( self ):
+ """Returns a string representing all child nodes."""
self._sort_nodes()
# todo filter only None?
node_repr = self._nodelist()
if len ( node_repr ):
+ # add newlines before/after and indent after node_repr!
return "\n%s\n%s" % ( '\n'.join ( node_repr ), self.indent )
else:
return ''
# --- end of _nodestr (...) ---
def to_str ( self ):
+ """Returns a string representing this node and all of its child nodes."""
self._do_verify()
return "%s<%s%s>%s</%s>" % (
self.indent,
@@ -142,10 +191,17 @@ class MetadataLeaf ( _MetadataBasicNode ):
self._text_wrapper.subsequent_indent = self.text_indent
def _value_str ( self ):
+ """Returns the value string. Derived classes may override this."""
#if self.value_format == ?: format value ~
- return self.value
+ return str ( self.value )
+ # --- end of _value_str (...) ---
def _pretty_value_str ( self ):
+ """Returns a formatted value string (max line length etc.).
+ Not used here, but subclasses can use it by simply writing
+ '_value_str = MetadataLeaf._pretty_value_str' in the class body.
+ """
+ # FIXME/TODO: could move this func to util
if not self.value: return ""
if self._text_wrapper is None:
@@ -160,14 +216,15 @@ class MetadataLeaf ( _MetadataBasicNode ):
# why?
return ""
elif len ( val_lines ) == 1:
+ # single line, no indent/newline
return val_lines [0]
else:
+ # add newline before/after, add indent after
val_lines [0] = '\n' + self.text_indent + val_lines [0]
val_lines.append ( self.indent )
return '\n'.join ( val_lines )
# --- end of _pretty_value_str (...) ---
-
def to_str ( self ):
self._do_verify()
if self.print_node_name:
@@ -181,7 +238,7 @@ class MetadataLeaf ( _MetadataBasicNode ):
else:
# not very useful, but allows to insert strings as nodes
return self.indent + self._value_str()
-
+ # --- end of to_str (...) ---
class MetadataNodeNamedAccess ( MetadataNode ):
"""A metadata node that offers key-based (dictionary) access to some of
@@ -189,16 +246,39 @@ class MetadataNodeNamedAccess ( MetadataNode ):
def __init__ ( self, name, flags=dict() ):
super ( MetadataNodeNamedAccess, self ) . __init__ ( name, flags )
+ # the access dict
self.node_dict = dict()
def add ( self, node, with_dict_entry=True, fail_if_existent=True ):
- """comment TODO; overwrites old dict entries!"""
+ """Adds a child node.
+
+ arguments:
+ * node -- node to add
+ * with_dict_entry -- add node to the access dict, defaults to True
+ * fail_if_existent -- fail if node's name already in the access dict,
+ defaults to True
+ """
+
super ( MetadataNodeNamedAccess, self ) . add ( node )
if with_dict_entry:
if fail_if_existent and node.name in self.node_dict:
raise Exception ( "key exists." )
else:
self.node_dict [node.name] = node
+ # --- end of add (...) ---
def get ( self, node_name ):
+ """Returns node by name.
+
+ arguments:
+ * node_name
+
+ raises: KeyError if node_name not in the access dict
+ """
return self.node_dict [node_name]
+ # --- end of get (...) ---
+
+ def has_named ( self, node_name ):
+ """Returns True if node_name in the access dict else False."""
+ return node_name in self.node_dict
+ # --- end of has_named (...) ---
diff --git a/roverlay/portage/metadata/creation.py b/roverlay/portage/metadata/creation.py
index d582d9e..d2f133c 100644
--- a/roverlay/portage/metadata/creation.py
+++ b/roverlay/portage/metadata/creation.py
@@ -7,8 +7,15 @@ import roverlay.config
from roverlay.portage.metadata import nodes
class MetadataJob ( object ):
+ """R package description data -> metadata.xml interface."""
def __init__ ( self, package_info, logger ):
+ """Initializes a MetadataJob.
+
+ arguments:
+ * package_info -- reserved for future usage
+ * logger -- logger to use (this instance won't call getChild)
+ """
self.logger = logger
self._metadata = nodes.MetadataRoot()
# reserved for future usage ("dominant ebuilds": when ebuildjobs
@@ -16,7 +23,7 @@ class MetadataJob ( object ):
self.package_info = None
# --- end of __init__ (...) ---
- def update_metadata ( self, desc_data, package_info ):
+ def update ( self, desc_data, package_info ):
"""Updates the metadata using the given description data.
It's expected that this method is called when Ebuild creation is done.
@@ -31,7 +38,7 @@ class MetadataJob ( object ):
mref = self._metadata
- max_textline_width = config.get ( 'METADATA.linewidth', 25 )
+ max_textline_width = roverlay.config.get ( 'METADATA.linewidth', 65 )
have_desc = False
@@ -53,7 +60,15 @@ class MetadataJob ( object ):
) )
have_desc = True
- # --- end of update_metadata (...) ---
+ mref.add_useflag ( 'byte-compile', 'enable byte-compiling' )
+
+ if package_info ['has_suggests']:
+ mref.add_useflag ( 'R_suggests', 'install optional dependencies' )
+
+ # --- end of update (...) ---
+
+ # used in some test scripts
+ update_metadata = update
def write ( self, _file ):
"""Writes the metadata into a file.
diff --git a/roverlay/portage/metadata/nodes.py b/roverlay/portage/metadata/nodes.py
index 7c3b890..36bf22d 100644
--- a/roverlay/portage/metadata/nodes.py
+++ b/roverlay/portage/metadata/nodes.py
@@ -2,8 +2,7 @@
# Copyright 2006-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
-# -- concrete metadata nodes --
-
+# import abstract nodes
from roverlay.portage.metadata.abstractnodes import \
MetadataNode, MetadataNodeNamedAccess, MetadataLeaf
@@ -13,21 +12,60 @@ class MetadataRoot ( MetadataNodeNamedAccess ):
Intended usage is metadata file creation.
"""
+ # the common metadata.xml header
HEADER = '\n'.join ( [
'<?xml version="1.0" encoding="UTF-8"?>',
'<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">'
] )
+
def __init__ ( self ):
super ( MetadataRoot, self ) . __init__ ( 'pkgmetadata' )
self.priority = 0
+ # --- end of __init__ (...) ---
def empty ( self ):
+ """Returns True if this node has no child nodes."""
#return 0 == len ( self.nodes ) or \
# True in ( node.empty() for node in self.nodes )
return 0 == len ( self.nodes )
+ # --- end of empty (...) ---
+
+ def add_useflag ( self, flag_name, flag_description ):
+ """Adds a USE Flag to the metadata.
+ A UseFlagListNode 'use' will be created if required and a new UseFlagNode
+ will then be created an added to 'use'.
+
+ arguments:
+ * flag_name -- see UseFlagNode.__init__
+ * flag_description -- see UseFlagNode.__init__
+
+ returns: the created UseFlagNode for further editing
+ """
+ if not self.has_named ( 'use' ):
+ # passing fail_if_existent, this node shouldn't be used in parallel
+ self.add (
+ UseFlagListNode(),
+ with_dict_entry=True, fail_if_existent=True
+ )
+
+ node = self.get ( 'use' )
+ use_node = UseFlagNode ( flag_name, flag_description )
+ node.add ( use_node )
+
+ return use_node
+ # --- end of add_useflag (...) ---
def write_file ( self, _file ):
+ """Writes the metadata to a file.
+
+ arguments:
+ * _file -- either a File object or a string
+
+ returns: success True/False
+
+ raises: *passes IOError
+ """
to_write = self.to_str()
own_fh = False
@@ -62,7 +100,16 @@ class MetadataRoot ( MetadataNodeNamedAccess ):
class DescriptionNode ( MetadataLeaf ):
+ """A description (<description.../>, <longdescription.../>) node."""
+
def __init__ ( self, description, is_long=False, linewidth=None ):
+ """Initializes a DescriptionNode.
+
+ arguments:
+ * description -- description text
+ * is_long -- if this is a longdescription or a description node
+ * linewidth -- max text line width, TODO/FIXME: is this ignored?
+ """
super ( DescriptionNode, self ) . __init__ (
'longdescription' if is_long else 'description',
value=description,
@@ -73,11 +120,21 @@ class DescriptionNode ( MetadataLeaf ):
self.linewidth = linewidth
self.priority = 150 if is_long else 149
+ # --- end of __init__ (...) ---
+ # using value formatting
_value_str = MetadataLeaf._pretty_value_str
+
class UseFlagNode ( MetadataLeaf ):
+ """A USE Flag node, <flag name=x>this flag does...</flag>"""
def __init__ ( self, flag_name, flag_description ):
+ """Initializes an USE Flag node.
+
+ arguments:
+ * flag_name -- name of the use flag
+ * flag_description -- flag description
+ """
super ( UseFlagNode, self ) . __init__ (
'flag',
flags=dict ( name = flag_name ),
@@ -85,12 +142,21 @@ class UseFlagNode ( MetadataLeaf ):
)
# priority shouldn't be used for this node
self.priority = -1
+ # --- end of __init__ (...) ---
class UseFlagListNode ( MetadataNode ):
+ """A USE Flag list node, <use>...</use>."""
+
def __init__ ( self, flags=dict() ):
+ """Initializes an USE Flag list node.
+
+ arguments:
+ * flags -- optional
+ """
super ( UseFlagListNode, self ) . __init__ ( 'use', flags=flags )
self.priority = 850
+ # --- end of __init__ (...) ---
def active ( self ):
"""The UseFlag list is only active if it is enabled and at least
@@ -100,21 +166,28 @@ class UseFlagListNode ( MetadataNode ):
# todo/fixme: could use super ( UseFlagListNode, self ).active() instead
# of self._enabled
return True in ( node.active() for node in self.nodes ) and self._enabled
-
+ # --- end of active (...) ---
def _sort_nodes ( self ):
"""UseFlags are sorted by lowercase flag name, not priority."""
self.nodes.sort ( key=lambda node : node.flags ['name'].lower() )
+ # --- end of _sort_nodes (...) ---
def add ( self, node ):
+ """Adds a child node only if it is a UseFlagNode.
+
+ arguments:
+ * node --
+ """
if isinstance ( node, UseFlagNode ):
super ( UseFlagListNode, self ) . add ( node )
else:
raise Exception ( "UseFlagListNode accepts UseFlagNodes only." )
-
-
+ # --- end of add (...) ---
class NopNode ( MetadataNode ):
+ """This node is meant for testing only."""
def __init__ ( self ):
super ( NopNode, self ) . __init__ ( 'nop', flags=dict() )
+ # --- end of __init__ (...) ---