diff options
Diffstat (limited to 'roverlay/ebuild')
-rw-r--r-- | roverlay/ebuild/abstractcomponents.py | 36 | ||||
-rw-r--r-- | roverlay/ebuild/creation.py | 82 | ||||
-rw-r--r-- | roverlay/ebuild/depres.py | 23 | ||||
-rw-r--r-- | roverlay/ebuild/ebuilder.py | 30 | ||||
-rw-r--r-- | roverlay/ebuild/evars.py | 26 |
5 files changed, 157 insertions, 40 deletions
diff --git a/roverlay/ebuild/abstractcomponents.py b/roverlay/ebuild/abstractcomponents.py index 73dac03..019c252 100644 --- a/roverlay/ebuild/abstractcomponents.py +++ b/roverlay/ebuild/abstractcomponents.py @@ -5,11 +5,23 @@ INDENT = '\t' def listlike ( ref ): + """Returns True if ref is listlike (a non-str iterable).""" return hasattr ( ref, '__iter__' ) and not isinstance ( ref, str ) class ListValue ( object ): + """An evar value with a list of elements.""" def __init__ ( self, value, indent_level=1, empty_value=None ): + """Initializes a ListValue. + + arguments: + * value -- + * indent_level -- indention level ('\t') for extra value lines + * empty_value -- if set: a string value that is always part + of this ListValue's elements but ignored + by len(). + Use cases are '${IUSE:-}' in the IUSE var etc. + """ self.set_level ( indent_level ) self.empty_value = empty_value @@ -23,13 +35,14 @@ class ListValue ( object ): self.val_join = ' ' self.set_value ( value ) - + # --- end of __init__ (...) --- def __len__ ( self ): l = len ( self.value ) return l if self.empty_value is None else l - 1 def set_level ( self, level ): + """Sets the indention level.""" self.level = level self.var_indent = (level - 1) * INDENT self.val_indent = level * INDENT @@ -37,6 +50,7 @@ class ListValue ( object ): # --- end of set_level (...) --- def set_value ( self, value ): + """Sets the value.""" self.value = list() if self.empty_value is not None: self.value.append ( self.empty_value ) @@ -44,6 +58,7 @@ class ListValue ( object ): # --- end of set_value (...) --- def add_value ( self, value ): + """Adds/Appends a value.""" if value is None: pass elif listlike ( value ): @@ -55,6 +70,7 @@ class ListValue ( object ): add = add_value def to_str ( self ): + """Returns a string representing this ListValue.""" if len ( self.value ) == 0: ret = "" elif len ( self.value ) == 1: @@ -73,21 +89,37 @@ class ListValue ( object ): class EbuildVar ( object ): + """An ebuild variable.""" def __init__ ( self, name, value, priority ): + """Initializes an EbuildVar. + + arguments: + * name -- e.g. 'SRC_URI' + * value -- + * priority -- used for sorting (e.g. 'R_SUGGESTS' before 'DEPEND'), + lower means higher priority + """ self.name = name self.priority = priority self.value = value self.set_level ( 0 ) def set_level ( self, level ): + """Sets the indention level.""" self.level = level self.indent = self.level * INDENT if hasattr ( self.value, 'set_level' ): self.value.set_level ( level + 1 ) # --- end of set_level (...) --- - def active ( self ): return True + def active ( self ): + """Returns True if this EbuildVar is enabled and has a string to + return. + (EbuildVar's active() returns always True, derived classes may + override this.) + """ + return True def __str__ ( self ): return '%s%s="%s"' % ( self.indent, self.name, self.value ) diff --git a/roverlay/ebuild/creation.py b/roverlay/ebuild/creation.py index e2f4872..fca864d 100644 --- a/roverlay/ebuild/creation.py +++ b/roverlay/ebuild/creation.py @@ -1,4 +1,4 @@ -# R Overlay -- ebuild creation, <?> +# R Overlay -- ebuild creation # Copyright 2006-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 @@ -10,13 +10,26 @@ from roverlay.rpackage.descriptionreader import DescriptionReader LOGGER = logging.getLogger ( 'EbuildCreation' ) +# USE_FULL_DESCRIPTION +# * True: use Title and Description for ebuild's DESCRIPTION variable +# * else: use Title _or_ Description USE_FULL_DESCRIPTION = False +# FALLBACK_DESCRIPTION is used as DESCRIPTION= value if not empty and +# the R package has no Title/Description +FALLBACK_DESCRIPTION = "<none>" class EbuildCreation ( object ): + """Used to create an ebuild using DESCRIPTION data.""" def __init__ ( self, package_info, depres_channel_spawner=None ): + """Initializes the creation of an ebuild. + arguments: + * package_info -- + * depres_channel_spawner -- function that returns a communication + channel to the resolver + """ self.package_info = package_info self.logger = LOGGER.getChild ( package_info ['name'] ) @@ -24,7 +37,6 @@ class EbuildCreation ( object ): # > 0 busy/working; 0 == done,success; < 0 done,fail self.status = 1 - self.depres_channel_spawner = depres_channel_spawner self.package_info.set_readonly() @@ -36,6 +48,7 @@ class EbuildCreation ( object ): def fail ( self ) : return self.status < 0 def run ( self ): + """Creates an ebuild. Returns None (implicit).""" if self.status < 1: raise Exception ( "Cannot run again." ) @@ -58,6 +71,8 @@ class EbuildCreation ( object ): # --- end of run (...) --- def _lazyimport_desc_data ( self ): + """Reads R package description data.""" + # TODO/FIXME: read this somewhere else? if self.package_info.get ( 'desc_data', fallback_value=None, do_fallback=True ) is None: @@ -75,23 +90,51 @@ class EbuildCreation ( object ): # --- end of _lazyimport_desc_data (...) --- + def _get_ebuild_description ( self ): + """Creates a DESCRIPTION variable.""" + desc = self.package_info ['desc_data'] + + description = None + if USE_FULL_DESCRIPTION: + # use Title and Description for DESCRIPTION= + if 'Title' in desc: + description = desc ['Title'] + + if 'Description' in desc: + if description is None: + description = desc ['Description'] + else: + description += '// ' + desc ['Description'] + else: + # use either Title or Description for DESCRIPTION= + # (Title preferred 'cause it should be shorter) + if 'Title' in desc: + description = desc ['Title'] + elif 'Description' in desc: + description = desc ['Description'] + + + if description is not None: + return evars.DESCRIPTION ( description ) + elif FALLBACK_DESCRIPTION: + return evars.DESCRIPTION ( FALLBACK_DESCRIPTION ) + else: + return None + # --- end of _get_ebuild_description (...) --- def _make_ebuild ( self ): - desc = self.package_info ['desc_data'] - if desc is None: + """Tries to create ebuild data.""" + if self.package_info ['desc_data'] is None: self.logger ( 'desc empty - cannot create an ebuild for this package.' ) return False - ebuild = ebuilder.Ebuilder() - _dep_resolution = depres.EbuildDepRes ( self.package_info, self.logger, create_iuse=True, run_now=True, depres_channel_spawner=self.depres_channel_spawner ) - if not _dep_resolution.success(): # log here? (FIXME) return False @@ -99,29 +142,15 @@ class EbuildCreation ( object ): dep_result = _dep_resolution.get_result() + ebuild = ebuilder.Ebuilder() + # add *DEPEND, IUSE to the ebuild ebuild.use ( *dep_result [1] ) - description = None - if USE_FULL_DESCRIPTION: - if 'Title' in desc: - description = desc ['Title'] - - if 'Description' in desc: - if description is None: - description = desc ['Description'] - else: - description += '// ' + desc ['Description'] - else: - if 'Title' in desc: - description = desc ['Title'] - elif 'Description' in desc: - description = desc ['Description'] - - - if description is not None: - ebuild.use ( evars.DESCRIPTION ( description ) ) + # DESCRIPTION + ebuild.use ( self._get_ebuild_description() ) + # SRC_URI ebuild.use ( evars.SRC_URI ( self.package_info ['SRC_URI'] ) ) ebuild_text = ebuild.to_str() @@ -132,3 +161,4 @@ class EbuildCreation ( object ): ) return True + # --- end of _make_ebuild (...) --- diff --git a/roverlay/ebuild/depres.py b/roverlay/ebuild/depres.py index db0f906..3838060 100644 --- a/roverlay/ebuild/depres.py +++ b/roverlay/ebuild/depres.py @@ -6,7 +6,7 @@ import roverlay.static.depres from roverlay.ebuild import evars -# move this to const / config +# TODO/FIXME/IGNORE move this to const / config FIELDS = { 'R_SUGGESTS' : [ 'Suggests' ], 'DEPENDS' : [ 'Depends', 'Imports' ], @@ -21,11 +21,21 @@ EBUILDVARS = { class EbuildDepRes ( object ): + """Handles dependency resolution for a single ebuild.""" def __init__ ( self, package_info, logger, depres_channel_spawner, create_iuse=True, run_now=True ): + """Initializes an EbuildDepRes. + + arguments: + * package_info -- + * logger -- parent logger + * depres_channel_spawner -- used to get channels to the dep resolver + * create_iuse -- create an IUSE evar (if True) + * run_now -- immediately start after initialization + """ self.logger = logger.getChild ( 'depres' ) self.package_info = package_info @@ -56,10 +66,14 @@ class EbuildDepRes ( object ): def fail ( self ) : return self.status < 0 def get_result ( self ): + """Returns the result of dependency resolution, + as tuple ( <status>, <evars>, <has R suggests> ) + """ return ( self.status, self.result, self.has_suggests ) # --- end of get_result (...) --- def resolve ( self ): + """Try to make/get dependency resolution results. Returns None.""" try: self.result = None self._init_channels() @@ -80,6 +94,7 @@ class EbuildDepRes ( object ): # --- end of resolve (...) --- def _get_channel ( self, dependency_type ): + """Creates and returns a communication channel to the dep resolver.""" if dependency_type not in self._channels: self._channels [dependency_type] = self.request_resolver ( name=dependency_type, @@ -89,6 +104,9 @@ class EbuildDepRes ( object ): # --- end of get_channel (...) --- def _init_channels ( self ): + """Initializes the resolver channels, one for each existing + dependency type. Queues dependencies, too. + """ # collect dep strings and initialize resolver channels if self.request_resolver is None: @@ -125,6 +143,7 @@ class EbuildDepRes ( object ): # --- end of _init_channels (...) --- def _close_channels ( self ): + """Closes the resolver channels.""" if self._channels is None: return for channel in self._channels.values(): channel.close() @@ -132,6 +151,7 @@ class EbuildDepRes ( object ): # --- end of _close_channels (...) --- def _wait_resolve ( self ): + """Wait for dep resolution.""" # True if no channels for c in self._channels.values(): if c.satisfy_request() is None: @@ -140,6 +160,7 @@ class EbuildDepRes ( object ): # --- end of _wait_resolve (...) --- def _make_result ( self ): + """Make evars using the depres result.""" _result = list() for dep_type, channel in self._channels.items(): deplist = list ( filter ( None, channel.collect_dependencies() ) ) diff --git a/roverlay/ebuild/ebuilder.py b/roverlay/ebuild/ebuilder.py index 275c6d2..aa7d8f5 100644 --- a/roverlay/ebuild/ebuilder.py +++ b/roverlay/ebuild/ebuilder.py @@ -1,22 +1,31 @@ -# R Overlay -- ebuild creation, <?> +# R Overlay -- ebuild construction # Copyright 2006-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 class Ebuilder ( object ): + """Used to create ebuilds.""" def __init__ ( self ): self._evars = list() + # newlines \n will be inserted after an evar if the priority + # delta (current evar, next evar) is >= this value. + # <= 0 means newline after each statement + self.min_newline_distance = 20 def sort ( self ): - self._evars.sort ( key=lambda e: e.priority ) + """Sorts the content of the Ebuilder.""" + self._evars.sort ( key=lambda e: ( e.priority, e.name ) ) + #self._evars.sort ( key=lambda e: e.priority ) def get_lines ( self ): + """Creates and returns (ordered) text lines.""" + self.sort() last = len ( self._evars ) - 1 - newline = lambda i, k=1 : \ - abs ( self._evars [i + k].priority - self._evars [i].priority ) >= 20 - + newline = lambda i, k=1 : abs ( + self._evars [i + k].priority - self._evars [i].priority + ) >= self.min_newline_distance lines = list() for index, e in enumerate ( self._evars ): @@ -25,12 +34,17 @@ class Ebuilder ( object ): if index < last and newline ( index ): lines.append ( '' ) return lines + # --- end of get_lines (...) --- - def to_str ( self ): - return '\n'.join ( self.get_lines() ) + def to_str ( self ): return '\n'.join ( self.get_lines() ) __str__ = to_str def use ( self, *evar_list ): + """Adds evars to this Ebuilder. + + arguments: + * *evar_list -- + """ for e in evar_list: - self._evars.append ( e ) + if e is not None: self._evars.append ( e ) diff --git a/roverlay/ebuild/evars.py b/roverlay/ebuild/evars.py index 78a7326..da34c68 100644 --- a/roverlay/ebuild/evars.py +++ b/roverlay/ebuild/evars.py @@ -1,4 +1,4 @@ -# R Overlay -- ebuild creation, <?> +# R Overlay -- ebuild construction, ebuild variables # Copyright 2006-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 @@ -12,24 +12,40 @@ RSUGGESTS_NAME = "R_SUGGESTS" # ignoring case policies here (camel case,..) class DESCRIPTION ( EbuildVar ): - def __init__ ( self, description ): + """A DESCRIPTION="..." statement.""" + def __init__ ( self, description, maxlen=50 ): + """A DESCRIPTION="..." statement. Long values will be truncated. + + arguments: + * description -- description text + * maxlen -- maximum value length (defaults to 50 chars) + """ super ( DESCRIPTION, self ) . __init__ ( 'DESCRIPTION', description, 80 ) + self.maxlen = 50 if maxlen is None else maxlen def __str__ ( self ): return '%s%s="%s"' % ( self.indent, self.name, - shorten_str ( str ( self.value ) , 50, '... (see metadata)' ) + shorten_str ( str ( self.value ) , self.maxlen, '... (see metadata)' ) ) class SRC_URI ( EbuildVar ): + """A SRC_URI="..." statement.""" def __init__ ( self, src_uri ): super ( SRC_URI, self ) . __init__ ( 'SRC_URI', src_uri, 90 ) class IUSE ( EbuildVar ): + """An IUSE="..." statement.""" def __init__ ( self, use_flags=None, using_suggests=False ): + """An IUSE="..." statement. + + arguments: + * use_flags -- IUSE value + * using_suggests -- if True: enable R_Suggests USE flag + """ super ( IUSE, self ) . __init__ ( 'IUSE', ListValue ( use_flags, empty_value='${IUSE:-}' ), @@ -41,6 +57,7 @@ class IUSE ( EbuildVar ): class R_SUGGESTS ( EbuildVar ): + """A R_SUGGESTS="..." statement.""" def __init__ ( self, deps, **kw ): super ( R_SUGGESTS, self ) . __init__ ( RSUGGESTS_NAME, @@ -50,6 +67,7 @@ class R_SUGGESTS ( EbuildVar ): class DEPEND ( EbuildVar ): + """A DEPEND="..." statement.""" def __init__ ( self, deps, **kw ): super ( DEPEND, self ) . __init__ ( 'DEPEND', @@ -59,6 +77,7 @@ class DEPEND ( EbuildVar ): class RDEPEND ( EbuildVar ): + """A RDEPEND="..." statement.""" def __init__ ( self, deps, using_suggests=False, **kw ): super ( RDEPEND, self ) . __init__ ( 'RDEPEND', @@ -68,4 +87,5 @@ class RDEPEND ( EbuildVar ): if using_suggests: self.enable_suggests() def enable_suggests ( self ): + """Adds the optional R_SUGGESTS dependencies to RDEPEND.""" self.value.add ( '%s? ( ${%s} )' % ( IUSE_SUGGESTS, RSUGGESTS_NAME ) ) |