diff --git a/pisi/api.py b/pisi/api.py index 89daaf8b..77d6807b 100644 --- a/pisi/api.py +++ b/pisi/api.py @@ -57,6 +57,7 @@ def init(database = True, options = None, ui = None ): # import pisi.sourcedb # pisi.sourcedb.init() + def install(packages): """install a list of packages (either files/urls, or names)""" @@ -235,7 +236,7 @@ def upgrade_pkg_names(A): ignore_build = ctx.config.options and ctx.config.options.ignore_build_no - # filter packages that are not installed + # filter packages that are not upgradable Ap = [] for x in A: if not ctx.installdb.is_installed(x): @@ -305,6 +306,25 @@ def upgrade_pkg_names(A): return True # everything went OK :) +def list_upgradable(): + A = ctx.installdb.list_installed() + # filter packages that are not upgradable + Ap = [] + for x in A: + if not ctx.installdb.is_installed(x): + continue + (version, release, build) = ctx.installdb.get_version(x) + pkg = packagedb.get_package(x) + if ignore_build or (not build): + if release < pkg.release: + Ap.append(x) + elif build < pkg.build: + Ap.append(x) + else: + pass + #ctx.ui.info('Package %s cannot be upgraded. ' % x) + return Ap + def remove(A): """remove set A of packages from system (A is a list of package names)""" diff --git a/pisi/specfilenew.py b/pisi/specfilenew.py index d6ab0f35..0e775e53 100644 --- a/pisi/specfilenew.py +++ b/pisi/specfilenew.py @@ -9,14 +9,15 @@ # # Please read the COPYING file. # - -# Specfile module is our handler for PSPEC files. PSPEC (PISI SPEC) -# files are specification files for PISI source packages. This module -# provides read and write access to PSPEC files. - # Authors: Eray Ozkural # Baris Metin +""" + Specfile module is our handler for PSPEC files. PSPEC (PISI SPEC) + files are specification files for PISI source packages. This module + provides read and write routines for PSPEC files. +""" + # standard python modules from os.path import basename @@ -28,17 +29,18 @@ from pisi.ui import ui from pisi.dependency import DepInfo from pisi.util import Checks +__metaclass__ = xmlfile.autoxml + class Packager: - __metaclass__ = xmlfile.autoxml t_Name = [types.StringType, xmlfile.mandatory] t_Email = [types.StringType, xmlfile.mandatory] def __str__(self): s = "%s <%s>" % (self.name, self.email) return s + + class AdditionalFileInfo: - __metaclass__ = xmlfile.autoxml - s_Filename = xmlfile.mandatory a_Target = [types.StringType, xmlfile.mandatory] a_Permission = [types.StringType, xmlfile.optional] @@ -49,9 +51,8 @@ class AdditionalFileInfo: s += '(%s)' % self.permission return s + class Patch: - __metaclass__ = xmlfile.autoxml - s_Filename = xmlfile.mandatory a_compressionType = [types.StringType, xmlfile.optional] a_level = [types.StringType, xmlfile.optional] @@ -67,8 +68,8 @@ class Patch: s += ' target:' + self.target return s + class Update: - __metaclass__ = xmlfile.autoxml t_Date = [types.StringType, xmlfile.mandatory] t_Version = [types.StringType, xmlfile.mandatory] @@ -83,10 +84,12 @@ class Update: s += ", type=" + self.type return s + class Path: - __metaclass__ = xmlfile.autoxml + s_Path = xmlfile.mandatory a_fileType = [types.StringType, xmlfile.optional] + def __str__(self): s = self.pathname s += ", type=" + self.fileType @@ -94,17 +97,19 @@ class Path: class ComarProvide: - __metaclass__ = xmlfile.autoxml + s_om = [types.StringType, xmlfile.mandatory] a_script = [types.StringType, xmlfile.mandatory] + def __str__(self): # FIXME: descriptive enough? s = self.script s += ' (' + self.om + ')' return s + class Archive: - __metaclass__ = xmlfile.autoxml + s_uri = [ types.StringType, xmlfile.mandatory ] a_type =[ types.StringType, xmlfile.mandatory ] a_sha1sum =[ types.StringType, xmlfile.mandatory ] @@ -114,7 +119,7 @@ class Archive: class Source: - __metaclass__ = xmlfile.autoxml + t_Name = [types.StringType, xmlfile.mandatory] t_HomePage = [types.StringType, xmlfile.mandatory] t_Packager = [Packager, xmlfile.mandatory] @@ -130,7 +135,7 @@ class Source: class Package: - __metaclass__ = xmlfile.autoxml + t_Name = [ types.StringType, xmlfile.mandatory ] t_Summary = [ types.StringType, xmlfile.mandatory ] t_Description = [ types.StringType, xmlfile.mandatory ] diff --git a/pisi/xmlfile.py b/pisi/xmlfile.py index f5074e72..26adce03 100644 --- a/pisi/xmlfile.py +++ b/pisi/xmlfile.py @@ -11,7 +11,8 @@ # # # Authors: Eray Ozkural -# Baris Metin +# Baris Metin """ @@ -23,10 +24,10 @@ in xml.dom :( ) autoxml is a metaclass for automatic XML translation, using - a miniature type system + a miniature type system. (w00t!) Method names are mixedCase for compatibility with minidom, - an old library + an old library. """ # System @@ -45,9 +46,45 @@ class Error(pisi.Error): import types -mandatory, optional = range(2) +mandatory, optional = range(2) # poor man's enum +# basic types +Text = types.StringType +Integer = types.IntType +class LocalText: + "handle tags with localized text" + + def __init__(): + locs = {} + + def decode(nodes, req): + # flags, tag name, instance attribute + if not nodes: + if req == mandatory: + pass + #errs.append("Tag '%s' should have at least one '%s' tag\n" % (parent.tagName, d[2])) + else: + for node in nodes: + lang = getAttribute(node, "xml:lang") + c = getText(node) + if not c: + #errs.append("Tag '%s' should have some text data\n" % node.tagName) + break + # FIXME: check for dups and 'en' + if not lang: + lang = 'en' + self.locs[lang] = c + # FIXME: return full list too + L = language + if not locs.has_key(L): + L = 'en' + if not locs.has_key(L): + errs.append("Tag '%s' should have an English version\n" % d[2]) + return "" + return locs[L] + + class autoxml(type): "high-level automatic XML transformation interface for xmlfile" @@ -70,7 +107,7 @@ class autoxml(type): root_tag = cls.tag # generate helper routines - initializers = [] + inits = [] decoders = [] encoders = [] formatters = [] @@ -78,27 +115,20 @@ class autoxml(type): if var.startswith('t_') or var.startswith('a_'): name = var[2:] #print 'name', name - # possible python bug, binds var only to t_Email here! -## def initializer(self): -## print 'got', name -## setattr(self, name, None) -## initializers.append(initializer) - initializers.append(autoxml.gen_init(cls, name)) if var.startswith('t_'): x = autoxml.gen_tag(cls, name) elif var.startswith('a_'): x = autoxml.gen_attr(cls, name) - (decoder, encoder, formatter) = x + (init, decoder, encoder, formatter) = x + inits.append(init) decoders.append(decoder) encoders.append(encoder) formatters.append(formatter) - #print initializers - - setattr(cls, 'initializers', initializers) + setattr(cls, 'initializers', inits) def initialize(self): - for initializer in self.__class__.initializers: - initializer(self) + for init in self.__class__.initializers: + init(self) setattr(cls, '__init__', initialize) setattr(cls, 'decoders', decoders) @@ -125,21 +155,21 @@ class autoxml(type): return self.format() setattr(cls, '__str__', string) - def gen_init(cls, name): - def initializer(self): - varname = cls.mixed_case(name) - #print 'init:', varname - setattr(self, varname, None) - return initializer - def gen_tag(cls, tag): # generate readers and writers for the tag val = getattr(cls, 't_' + tag) tag_type = val[0] - if type(tag_type) == type(type): + return autoxml.gen_tag_aux(cls, tag, tag_type, val) + + def gen_tag_aux(cls, tag, tag_type, val): + if type(tag_type) == types.TypeType: # basic types return autoxml.gen_basic_tag(cls, tag, val) - + elif type(tag_type) == types.ClassType: + return autoxml.gen_class_tag(cls, tag, val) + elif type(tag_type) == types.ListType: + return autoxml.gen_list_tag(cls, tag, val) + def gen_attr(cls, tag): "generate readers and writers for an attribute" #print 'attr:', tag @@ -157,6 +187,10 @@ class autoxml(type): name = cls.mixed_case(token) token_type = val[0] req = val[1] + + def initialize(self): + #print 'init:', name + setattr(self, name, None) def decode(self, node): text = readtext(node, token) @@ -181,7 +215,7 @@ class autoxml(type): if req == mandatory: return ['Mandatory argument not available'] - def formatter(self): + def format(self): #print 'format:', name if hasattr(self, name): return '%s: %s\n' % (token, str(getattr(self, name))) @@ -190,7 +224,7 @@ class autoxml(type): raise Error('Mandatory variable %s not available' % name) return "" - return decode, encode, formatter + return initialize, decode, encode, format def gen_basic_attr(cls, attr, val): """generate an attribute with a basic datatype""" @@ -208,6 +242,56 @@ class autoxml(type): xml.addTextNodeUnder(node, tag, value) return autoxml.gen_basic(cls, tag, val, readtext, writetext) + def gen_class_tag(cls, tag, val): + pass + + def gen_list_tag(cls, tag, val): + name = cls.mixed_case(token) + token_type = val[0] + req = val[1] + + if len(val)>=3: + path = val[2] + else: + path = tag + if len(token_type!=1): + raise Error('List type must contain one element') + + x = autoxml.gen_tag_aux(cls, tag, tag_type, val) + (x_init, x_decoder, x_encoder, x_formatter) = x + + def init(self): + varname = cls.mixed_case(name) + setattr(self, varname, []) + + def decode(self, node): + nodes = getAllNodes(node) + if len(nodes) is 0 and req is mandatory: + pass + #FIXME: add error here + for node in nodes: + x_decoder(self, node) + pass + + def encode(self, xml): + node = xml.newNode(cls.tag) + if hasattr(self, name): + writetext(xml, node, token, str(getattr(self, name))) + else: + if req == mandatory: + return ['Mandatory argument not available'] + + def format(self): + #print 'format:', name + if hasattr(self, name): + return '%s: %s\n' % (token, str(getattr(self, name))) + else: + if req == mandatory: + raise Error('Mandatory variable %s not available' % name) + return "" + + return (init, decode, encode, format) + basic_cons_map = { types.StringType : str, types.IntType : int diff --git a/tests/run.py b/tests/run.py index 19c87d28..90e586eb 100755 --- a/tests/run.py +++ b/tests/run.py @@ -15,6 +15,7 @@ import sys import os sys.path.append('.') +sys.path.append('..') runTestSuite = lambda(x): unittest.TextTestRunner(verbosity=2).run(x) diff --git a/tests/sandbox/a.xml b/tests/sandbox/a.xml index 91d3faca..375d2644 100644 --- a/tests/sandbox/a.xml +++ b/tests/sandbox/a.xml @@ -2,4 +2,8 @@ Eray Ozkural 868 + + pisi + noatun + diff --git a/tests/xmlfiletests.py b/tests/xmlfiletests.py index 6f7e330c..312a1ec9 100644 --- a/tests/xmlfiletests.py +++ b/tests/xmlfiletests.py @@ -33,7 +33,7 @@ class XmlFileTestCase(unittest.TestCase): a_href = [types.StringType, xmlfile.mandatory] #t_Projects = [ [types.StringType], xmlfile.mandatory] a = A() - #print a + print a self.assertEqual(a.href, None) dom = mdom.parse('tests/sandbox/a.xml') node = getNode(dom, 'A')