* implement pisi.api.list_upgradable
* improve autoxml stuff a bit - start complex types: class, list - refactor a bit
This commit is contained in:
+21
-1
@@ -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)"""
|
||||
|
||||
|
||||
+21
-16
@@ -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 <eray@uludag.org.tr>
|
||||
# Baris Metin <baris@uludag.org.tr>
|
||||
|
||||
"""
|
||||
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 ]
|
||||
|
||||
+112
-28
@@ -11,7 +11,8 @@
|
||||
#
|
||||
#
|
||||
# Authors: Eray Ozkural <eray@uludag.org.tr>
|
||||
# Baris Metin <baris@uludag.org.tr
|
||||
# Gurer Ozen <gurer@uludag.org.tr>
|
||||
# Baris Metin <baris@uludag.org.tr>
|
||||
|
||||
|
||||
"""
|
||||
@@ -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
|
||||
|
||||
@@ -15,6 +15,7 @@ import sys
|
||||
import os
|
||||
|
||||
sys.path.append('.')
|
||||
sys.path.append('..')
|
||||
|
||||
runTestSuite = lambda(x): unittest.TextTestRunner(verbosity=2).run(x)
|
||||
|
||||
|
||||
@@ -2,4 +2,8 @@
|
||||
<A href="http://www.cs.bilkent.edu.tr/~erayo">
|
||||
<Name>Eray Ozkural</Name>
|
||||
<Number>868</Number>
|
||||
<Projects>
|
||||
<Project>pisi</Project>
|
||||
<Project>noatun</Project>
|
||||
</Projects>
|
||||
</A>
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user