* improve UI concept a bit
- re-introduce the somewhat redundant base class UI (it used to exist!) - improve and factor cli specific stuff into pisi.cli - introduce ack and choose functions, implement choose in cli - get rid of the cli-specific slash-ns, so many of them :/ * work towards doing the list type in autoxml the right way - breaks the unit test, but cleaner than before now - after lists, classes and localized text - that's how i'll implement the component tree, hmmm :) * some more detail on the todo
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
PISI - Packages Installed Succesfully as Intented
|
PISI - Packages Installed Succesfully as Intented
|
||||||
|
|
||||||
PISI is a new package manager implemented in python.
|
PISI is a new package manager implemented in python for the PARDUS
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
Main features
|
||||||
|
|
||||||
|
- Implemented in python.
|
||||||
|
- All specification and intermediate data is in an XML format.
|
||||||
|
- Fast database access implemented with berkeley DB.
|
||||||
|
- Integrates both low-level and high-level package operations.
|
||||||
|
|
||||||
|
|||||||
@@ -77,29 +77,39 @@ Legend:
|
|||||||
/ multiple package repository (eray)
|
/ multiple package repository (eray)
|
||||||
+ decide how to implement
|
+ decide how to implement
|
||||||
+ support repo order
|
+ support repo order
|
||||||
- support medium types
|
? support medium types
|
||||||
- internet: http/ftp
|
- internet: http/ftp
|
||||||
- local repository
|
- local repository
|
||||||
- cdrom dvd
|
- cdrom dvd
|
||||||
/ UI
|
/ UI
|
||||||
- improve interface
|
? pyqt UI class to interface
|
||||||
- ask alternatives to choose from (eray)
|
|
||||||
- pyqt UI class to interface
|
|
||||||
- PISIMAT
|
- PISIMAT
|
||||||
/ pykde GUI (cartman)
|
/ pykde GUI (cartman)
|
||||||
|
+ improve interface
|
||||||
|
+ refactor UI, reintroduce base class
|
||||||
|
+ add an ack interface, start cleaning up a bit
|
||||||
|
+ cli
|
||||||
|
+ ask alternatives to choose from (eray)
|
||||||
|
+ eliminate \n's from infos, what's the point?
|
||||||
+ metaclass coolness for CLI command framework (eray)
|
+ metaclass coolness for CLI command framework (eray)
|
||||||
/ i18n support (those who know how to do it)
|
/ autoxml: automated xml processing
|
||||||
|
+ design
|
||||||
|
+ basic types
|
||||||
|
/ list typ
|
||||||
|
- class typ
|
||||||
|
/ localtext type
|
||||||
/ components
|
/ components
|
||||||
+ requirements
|
+ requirements
|
||||||
- xml format (baris) (bunlarin class'leri yazilmali)
|
- xml format (bunlarin class'leri yazilmali)
|
||||||
- query components
|
- query components: list of components/packages in a component
|
||||||
- install/remove components
|
- install/remove components
|
||||||
|
/ i18n support
|
||||||
|
- configure-pending (eray)
|
||||||
|
/ overhaul installdb (try to merge its use with packagedb) (eray)
|
||||||
+ upgrade (eray)
|
+ upgrade (eray)
|
||||||
+ upgrade operation
|
+ upgrade operation
|
||||||
+ test upgrade op
|
+ test upgrade op
|
||||||
+ system-wide upgrade (upgrade-all) komutu
|
+ system-wide upgrade (upgrade-all) komutu
|
||||||
/ overhaul installdb (try to merge its use with packagedb) (eray)
|
|
||||||
- configure-pending (eray)
|
|
||||||
? ordered configure install thing (eray)
|
? ordered configure install thing (eray)
|
||||||
- partial caching and automatic resume for file download (meren)
|
- partial caching and automatic resume for file download (meren)
|
||||||
- use a separate "partial/" subdir like urpmi
|
- use a separate "partial/" subdir like urpmi
|
||||||
@@ -117,11 +127,11 @@ Legend:
|
|||||||
+ MetaData
|
+ MetaData
|
||||||
+ Files
|
+ Files
|
||||||
- Index (o kadar onemli degil)
|
- Index (o kadar onemli degil)
|
||||||
- implement missing unit tests
|
+ implement missing unit tests
|
||||||
+ sourcedb
|
+ sourcedb
|
||||||
+ package (baris)
|
+ package (baris)
|
||||||
+ configuration file (baris)
|
+ configuration file (baris)
|
||||||
- non-interactive use (baris)
|
? non-interactive use (baris)
|
||||||
+ incremental build (eray)
|
+ incremental build (eray)
|
||||||
+ generate binary release number by comparing MD5s (eray)
|
+ generate binary release number by comparing MD5s (eray)
|
||||||
+ keep track of successfully completed configure, make, install
|
+ keep track of successfully completed configure, make, install
|
||||||
@@ -133,6 +143,10 @@ Legend:
|
|||||||
|
|
||||||
5. Post Release
|
5. Post Release
|
||||||
|
|
||||||
|
- a database of components: faster access
|
||||||
|
- more support for categories:
|
||||||
|
- put categories into a database
|
||||||
|
- fast query for categories
|
||||||
/ make a package and sourcedb for each repo
|
/ make a package and sourcedb for each repo
|
||||||
+ packagedb
|
+ packagedb
|
||||||
- sourceb
|
- sourceb
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ def handle_exception(exception, value, tb):
|
|||||||
import pisi.ui
|
import pisi.ui
|
||||||
from pisi.xmlext import XmlError
|
from pisi.xmlext import XmlError
|
||||||
|
|
||||||
ui = pisi.ui.CLI()
|
ui = pisi.cli.CLI()
|
||||||
|
|
||||||
if exception == exceptions.KeyboardInterrupt:
|
if exception == exceptions.KeyboardInterrupt:
|
||||||
ui.error(_("\nKeyboardInterrupt: Exiting...\n"))
|
ui.error(_("\nKeyboardInterrupt: Exiting...\n"))
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class ConfigureError(pisi.actionsapi.Error):
|
|||||||
def __init__(self, Exception):
|
def __init__(self, Exception):
|
||||||
ctx.ui.error(Exception)
|
ctx.ui.error(Exception)
|
||||||
if can_access_file('config.log'):
|
if can_access_file('config.log'):
|
||||||
ctx.ui.error('\n!!! Please attach the config.log to your bug report:\n%s/config.log\n' % os.getcwd())
|
ctx.ui.error('\n!!! Please attach the config.log to your bug report:\n%s/config.log' % os.getcwd())
|
||||||
|
|
||||||
class MakeError(pisi.actionsapi.Error):
|
class MakeError(pisi.actionsapi.Error):
|
||||||
def __init__(self, Exception):
|
def __init__(self, Exception):
|
||||||
|
|||||||
@@ -35,16 +35,16 @@ def preplib_so(sourceDirectory):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def gnuconfig_update():
|
def gnuconfig_update():
|
||||||
''' copy newest config.* onto source's '''
|
''' copy newest config.* onto source\'s '''
|
||||||
for root, dirs, files in os.walk(os.getcwd()):
|
for root, dirs, files in os.walk(os.getcwd()):
|
||||||
for file in files:
|
for file in files:
|
||||||
if file in ['config.sub', 'config.guess']:
|
if file in ['config.sub', 'config.guess']:
|
||||||
copy('/usr/share/gnuconfig/%s' % file, os.path.join(root, file))
|
copy('/usr/share/gnuconfig/%s' % file, os.path.join(root, file))
|
||||||
ctx.ui.info('GNU Config Update Finished...\n')
|
ctx.ui.info('GNU Config Update Finished.')
|
||||||
|
|
||||||
def libtoolize(parameters = ''):
|
def libtoolize(parameters = ''):
|
||||||
if system('/usr/bin/libtoolize %s' % parameters):
|
if system('/usr/bin/libtoolize %s' % parameters):
|
||||||
raise RunTimeError('!!! Running libtoolize failed...')
|
raise RunTimeError('Running libtoolize failed...')
|
||||||
|
|
||||||
def gen_usr_ldscript(dynamicLib):
|
def gen_usr_ldscript(dynamicLib):
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ def doman(*sourceFiles):
|
|||||||
pageName, pageDirectory = source[:source.rindex('.')], \
|
pageName, pageDirectory = source[:source.rindex('.')], \
|
||||||
source[source.rindex('.')+1:]
|
source[source.rindex('.')+1:]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [doman]: Wrong man page file...\n')
|
ctx.ui.error('\n!!! ActionsAPI [doman]: Wrong man page file...')
|
||||||
|
|
||||||
makedirs(manDIR + '/man%s' % pageDirectory)
|
makedirs(manDIR + '/man%s' % pageDirectory)
|
||||||
system('install -m0644 %s %s' % (source, manDIR + '/man%s' % pageDirectory))
|
system('install -m0644 %s %s' % (source, manDIR + '/man%s' % pageDirectory))
|
||||||
@@ -185,7 +185,7 @@ def dosym(sourceFile, destinationFile):
|
|||||||
try:
|
try:
|
||||||
os.symlink(sourceFile, get.installDIR() + destinationFile)
|
os.symlink(sourceFile, get.installDIR() + destinationFile)
|
||||||
except OSError:
|
except OSError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [dosym]: File exists...\n')
|
ctx.ui.error('\n!!! ActionsAPI [dosym]: File exists...')
|
||||||
|
|
||||||
def insinto(destinationDirectory, sourceFile, destinationFile = ''):
|
def insinto(destinationDirectory, sourceFile, destinationFile = ''):
|
||||||
'''insert a sourceFile into destinationDirectory as a destinationFile with same uid/guid/permissions'''
|
'''insert a sourceFile into destinationDirectory as a destinationFile with same uid/guid/permissions'''
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ def echo(destionationFile, content):
|
|||||||
f.write("%s\n" % content)
|
f.write("%s\n" % content)
|
||||||
f.close()
|
f.close()
|
||||||
except IOError:
|
except IOError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [echo]: Can\'t append to file...\n')
|
ctx.ui.error(' ActionsAPI [echo]: Can\'t append to file...')
|
||||||
|
|
||||||
def chmod(sourceFile, mode = 0755):
|
def chmod(sourceFile, mode = 0755):
|
||||||
'''change the mode of sourceFile to the mode'''
|
'''change the mode of sourceFile to the mode'''
|
||||||
@@ -52,9 +52,9 @@ def chmod(sourceFile, mode = 0755):
|
|||||||
try:
|
try:
|
||||||
os.chmod(file, mode)
|
os.chmod(file, mode)
|
||||||
except OSError:
|
except OSError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [chmod]: Operation not permitted...\n')
|
ctx.ui.error(' ActionsAPI [chmod]: Operation not permitted...')
|
||||||
else:
|
else:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [chmod]: File doesn\'t exists...\n')
|
ctx.ui.error(' ActionsAPI [chmod]: File doesn\'t exists...')
|
||||||
|
|
||||||
def chown(sourceFile, uid = 0, gid = 0):
|
def chown(sourceFile, uid = 0, gid = 0):
|
||||||
'''change the owner and group id of sourceFile to the numeric uid and gid'''
|
'''change the owner and group id of sourceFile to the numeric uid and gid'''
|
||||||
@@ -62,16 +62,16 @@ def chown(sourceFile, uid = 0, gid = 0):
|
|||||||
try:
|
try:
|
||||||
os.chown(sourceFile, uid, gid)
|
os.chown(sourceFile, uid, gid)
|
||||||
except OSError:
|
except OSError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [chown]: Operation not permitted...\n')
|
ctx.ui.error(' ActionsAPI [chown]: Operation not permitted...')
|
||||||
else:
|
else:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [chown]: File doesn\'t exists...\n')
|
ctx.ui.error(' ActionsAPI [chown]: File doesn\'t exists...')
|
||||||
|
|
||||||
def sym(sourceFile, destinationFile):
|
def sym(sourceFile, destinationFile):
|
||||||
'''creates symbolic link'''
|
'''creates symbolic link'''
|
||||||
try:
|
try:
|
||||||
os.symlink(sourceFile, destinationFile)
|
os.symlink(sourceFile, destinationFile)
|
||||||
except OSError:
|
except OSError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [sym]: Permission denied...\n')
|
ctx.ui.error(' ActionsAPI [sym]: Permission denied...')
|
||||||
|
|
||||||
def unlink(sourceFile):
|
def unlink(sourceFile):
|
||||||
'''remove the file path'''
|
'''remove the file path'''
|
||||||
@@ -79,11 +79,11 @@ def unlink(sourceFile):
|
|||||||
try:
|
try:
|
||||||
os.unlink(sourceFile)
|
os.unlink(sourceFile)
|
||||||
except OSError:
|
except OSError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [unlink]: Permission denied...\n')
|
ctx.ui.error(' ActionsAPI [unlink]: Permission denied.')
|
||||||
elif isDirectory(sourceFile):
|
elif isDirectory(sourceFile):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [unlink]: File doesn\'t exists...\n')
|
ctx.ui.error(' ActionsAPI [unlink]: File doesn\'t exists.')
|
||||||
|
|
||||||
def unlinkDir(sourceDirectory):
|
def unlinkDir(sourceDirectory):
|
||||||
'''delete an entire directory tree'''
|
'''delete an entire directory tree'''
|
||||||
@@ -91,11 +91,11 @@ def unlinkDir(sourceDirectory):
|
|||||||
try:
|
try:
|
||||||
shutil.rmtree(sourceDirectory)
|
shutil.rmtree(sourceDirectory)
|
||||||
except OSError:
|
except OSError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [unlinkDir]: Operation not permitted...\n')
|
ctx.ui.error(' ActionsAPI [unlinkDir]: Operation not permitted.')
|
||||||
elif isFile(sourceDirectory):
|
elif isFile(sourceDirectory):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [unlinkDir]: Directory doesn\'t exists...\n')
|
ctx.ui.error(' ActionsAPI [unlinkDir]: Directory doesn\'t exists.')
|
||||||
|
|
||||||
def move(sourceFile, destinationFile):
|
def move(sourceFile, destinationFile):
|
||||||
'''recursively move a sourceFile or directory to destinationFile'''
|
'''recursively move a sourceFile or directory to destinationFile'''
|
||||||
@@ -104,9 +104,9 @@ def move(sourceFile, destinationFile):
|
|||||||
try:
|
try:
|
||||||
shutil.move(file, destinationFile)
|
shutil.move(file, destinationFile)
|
||||||
except OSError:
|
except OSError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [move]: Permission denied...\n')
|
ctx.ui.error(' ActionsAPI [move]: Permission denied.')
|
||||||
else:
|
else:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [move]: File doesn\'t exists...\n')
|
ctx.ui.error(' ActionsAPI [move]: File doesn\'t exists.')
|
||||||
|
|
||||||
def copy(sourceFile, destinationFile):
|
def copy(sourceFile, destinationFile):
|
||||||
'''recursively copy a sourceFile or directory to destinationFile'''
|
'''recursively copy a sourceFile or directory to destinationFile'''
|
||||||
@@ -115,9 +115,9 @@ def copy(sourceFile, destinationFile):
|
|||||||
try:
|
try:
|
||||||
shutil.copy(file, destinationFile)
|
shutil.copy(file, destinationFile)
|
||||||
except IOError:
|
except IOError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [copy]: Permission denied...\n')
|
ctx.ui.error(' ActionsAPI [copy]: Permission denied.')
|
||||||
else:
|
else:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [copy]: File doesn\'t exists...\n')
|
ctx.ui.error(' ActionsAPI [copy]: File doesn\'t exists.')
|
||||||
|
|
||||||
def copytree(source, destination, sym = False):
|
def copytree(source, destination, sym = False):
|
||||||
'''recursively copy an entire directory tree rooted at source'''
|
'''recursively copy an entire directory tree rooted at source'''
|
||||||
@@ -125,9 +125,9 @@ def copytree(source, destination, sym = False):
|
|||||||
try:
|
try:
|
||||||
shutil.copytree(source, destination, sym)
|
shutil.copytree(source, destination, sym)
|
||||||
except OSError:
|
except OSError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [copytree]: Permission denied...\n')
|
ctx.ui.error(' ActionsAPI [copytree]: Permission denied.')
|
||||||
else:
|
else:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [copytree]: Directory doesn\'t exists...\n')
|
ctx.ui.error(' ActionsAPI [copytree]: Directory doesn\'t exists.')
|
||||||
|
|
||||||
def touch(sourceFile):
|
def touch(sourceFile):
|
||||||
'''changes the access time of the 'sourceFile', or creates it if it is not exist'''
|
'''changes the access time of the 'sourceFile', or creates it if it is not exist'''
|
||||||
@@ -139,7 +139,7 @@ def touch(sourceFile):
|
|||||||
f = open(sourceFile, 'w')
|
f = open(sourceFile, 'w')
|
||||||
f.close()
|
f.close()
|
||||||
except IOError:
|
except IOError:
|
||||||
ctx.ui.error('\n!!! ActionsAPI [touch]: Permission denied...\n')
|
ctx.ui.error(' ActionsAPI [touch]: Permission denied.')
|
||||||
|
|
||||||
def cd(directoryName = ''):
|
def cd(directoryName = ''):
|
||||||
'''change directory'''
|
'''change directory'''
|
||||||
@@ -187,12 +187,12 @@ def dirName(sourceFile):
|
|||||||
def system(command):
|
def system(command):
|
||||||
#FIXME: String formatting
|
#FIXME: String formatting
|
||||||
command = command.replace(" ", " ")
|
command = command.replace(" ", " ")
|
||||||
ctx.ui.debug('executing %s\n' % command)
|
ctx.ui.debug('executing %s' % command)
|
||||||
p = os.popen(command)
|
p = os.popen(command)
|
||||||
while 1:
|
while 1:
|
||||||
line = p.readline()
|
line = p.readline()
|
||||||
if not line:
|
if not line:
|
||||||
break
|
break
|
||||||
ctx.ui.debug(line)
|
ctx.ui.debug(line[0:len(line)-1])
|
||||||
|
|
||||||
return p.close()
|
return p.close()
|
||||||
|
|||||||
+29
-28
@@ -7,9 +7,10 @@
|
|||||||
#
|
#
|
||||||
# Please read the COPYING file.
|
# Please read the COPYING file.
|
||||||
#
|
#
|
||||||
|
# Authors: Eray Ozkural <eray@uludag.org.tr>
|
||||||
|
# Baris Metin <baris@uludag.org.tr>
|
||||||
|
|
||||||
# top level PISI interfaces
|
"""Top level PISI interfaces. a facade to the entire PISI system"""
|
||||||
# a facade to the entire PISI system
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@@ -29,11 +30,13 @@ import pisi.packagedb as packagedb
|
|||||||
import pisi.repodb
|
import pisi.repodb
|
||||||
import pisi.installdb
|
import pisi.installdb
|
||||||
from pisi.index import Index
|
from pisi.index import Index
|
||||||
|
import pisi.cli
|
||||||
|
|
||||||
|
|
||||||
class Error(pisi.Error):
|
class Error(pisi.Error):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def init(database = True, options = None, ui = None ):
|
def init(database = True, options = None, ui = None ):
|
||||||
"""Initialize PiSi subsystem"""
|
"""Initialize PiSi subsystem"""
|
||||||
|
|
||||||
@@ -41,11 +44,10 @@ def init(database = True, options = None, ui = None ):
|
|||||||
ctx.config = pisi.config.Config(options)
|
ctx.config = pisi.config.Config(options)
|
||||||
|
|
||||||
if ui is None:
|
if ui is None:
|
||||||
import pisi.ui
|
|
||||||
if options:
|
if options:
|
||||||
pisi.context.ui = pisi.ui.CLI(options.debug)
|
pisi.context.ui = pisi.cli.CLI(options.debug)
|
||||||
else:
|
else:
|
||||||
pisi.context.ui = pisi.ui.CLI()
|
pisi.context.ui = pisi.cli.CLI()
|
||||||
else:
|
else:
|
||||||
pisi.context.ui = ui
|
pisi.context.ui = ui
|
||||||
|
|
||||||
@@ -58,7 +60,6 @@ def init(database = True, options = None, ui = None ):
|
|||||||
# import pisi.sourcedb
|
# import pisi.sourcedb
|
||||||
# pisi.sourcedb.init()
|
# pisi.sourcedb.init()
|
||||||
|
|
||||||
|
|
||||||
def install(packages):
|
def install(packages):
|
||||||
"""install a list of packages (either files/urls, or names)"""
|
"""install a list of packages (either files/urls, or names)"""
|
||||||
|
|
||||||
@@ -73,23 +74,23 @@ def install(packages):
|
|||||||
else:
|
else:
|
||||||
return install_pkg_names(packages)
|
return install_pkg_names(packages)
|
||||||
|
|
||||||
|
#FIXME: As Gurer warns, something's fishy with this exception proc.
|
||||||
except InstallError, e:
|
except InstallError, e:
|
||||||
ctx.ui.error("%s\n" % e)
|
ctx.ui.error("InstallError:%s" % e)
|
||||||
|
|
||||||
except packagedb.Error, e:
|
except packagedb.Error, e:
|
||||||
ctx.ui.error("PackageDBError: (%s)\n" % e)
|
ctx.ui.error("PackageDBError: (%s)" % e)
|
||||||
ctx.ui.error("Package is not installable.\n")
|
ctx.ui.error("Package is not installable.")
|
||||||
|
|
||||||
#except Exception, e:
|
#except Exception, e:
|
||||||
# print e
|
# print e
|
||||||
# ctx.ui.error("Error: %s\n" % e)
|
# ctx.ui.error("Error: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
def install_pkg_files(package_URIs):
|
def install_pkg_files(package_URIs):
|
||||||
"""install a number of pisi package files"""
|
"""install a number of pisi package files"""
|
||||||
from package import Package
|
from package import Package
|
||||||
|
|
||||||
ctx.ui.debug('A = %s\n' % str(package_URIs))
|
ctx.ui.debug('A = %s' % str(package_URIs))
|
||||||
|
|
||||||
for x in package_URIs:
|
for x in package_URIs:
|
||||||
if not x.endswith(ctx.const.package_prefix):
|
if not x.endswith(ctx.const.package_prefix):
|
||||||
@@ -142,7 +143,7 @@ def install_pkg_files(package_URIs):
|
|||||||
A = d_t.keys()
|
A = d_t.keys()
|
||||||
|
|
||||||
if len(A)==0:
|
if len(A)==0:
|
||||||
ctx.ui.info('No packages to install.\n')
|
ctx.ui.info('No packages to install.')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# try to construct a pisi graph of packages to
|
# try to construct a pisi graph of packages to
|
||||||
@@ -186,10 +187,10 @@ def install_pkg_names(A):
|
|||||||
the repository, trying to perform a minimum number of
|
the repository, trying to perform a minimum number of
|
||||||
installs"""
|
installs"""
|
||||||
|
|
||||||
ctx.ui.debug('A = %s\n' % str(A))
|
ctx.ui.debug('A = %s' % str(A))
|
||||||
|
|
||||||
if len(A)==0:
|
if len(A)==0:
|
||||||
ctx.ui.info('No packages to install.\n')
|
ctx.ui.info('No packages to install.')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# try to construct a pisi graph of packages to
|
# try to construct a pisi graph of packages to
|
||||||
@@ -241,7 +242,7 @@ def upgrade_pkg_names(A):
|
|||||||
Ap = []
|
Ap = []
|
||||||
for x in A:
|
for x in A:
|
||||||
if not ctx.installdb.is_installed(x):
|
if not ctx.installdb.is_installed(x):
|
||||||
ctx.ui.info('Package %s is not installed.\n' % x)
|
ctx.ui.info('Package %s is not installed.' % x)
|
||||||
continue
|
continue
|
||||||
(version, release, build) = ctx.installdb.get_version(x)
|
(version, release, build) = ctx.installdb.get_version(x)
|
||||||
pkg = packagedb.get_package(x)
|
pkg = packagedb.get_package(x)
|
||||||
@@ -253,15 +254,15 @@ def upgrade_pkg_names(A):
|
|||||||
else:
|
else:
|
||||||
#ctx.ui.info('Package %s cannot be upgraded. ' % x)
|
#ctx.ui.info('Package %s cannot be upgraded. ' % x)
|
||||||
ctx.ui.info('Package %s is already at its latest version %s,\
|
ctx.ui.info('Package %s is already at its latest version %s,\
|
||||||
release %s, build %s.\n'
|
release %s, build %s.'
|
||||||
% (x, pkg.version, pkg.release, pkg.build))
|
% (x, pkg.version, pkg.release, pkg.build))
|
||||||
A = Ap
|
A = Ap
|
||||||
|
|
||||||
if len(A)==0:
|
if len(A)==0:
|
||||||
ctx.ui.info('No packages to upgrade.\n')
|
ctx.ui.info('No packages to upgrade.')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
ctx.ui.debug('A = %s\n' % str(A))
|
ctx.ui.debug('A = %s' % str(A))
|
||||||
|
|
||||||
# try to construct a pisi graph of packages to
|
# try to construct a pisi graph of packages to
|
||||||
# install / reinstall
|
# install / reinstall
|
||||||
@@ -337,11 +338,11 @@ def remove(A):
|
|||||||
if ctx.installdb.is_installed(x):
|
if ctx.installdb.is_installed(x):
|
||||||
Ap.append(x)
|
Ap.append(x)
|
||||||
else:
|
else:
|
||||||
ctx.ui.info('Package %s does not exist. Cannot remove.\n' % x)
|
ctx.ui.info('Package %s does not exist. Cannot remove.' % x)
|
||||||
A = Ap
|
A = Ap
|
||||||
|
|
||||||
if len(A)==0:
|
if len(A)==0:
|
||||||
ctx.ui.info('No packages to remove.\n')
|
ctx.ui.info('No packages to remove.')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# try to construct a pisi graph of packages to
|
# try to construct a pisi graph of packages to
|
||||||
@@ -377,7 +378,7 @@ def remove(A):
|
|||||||
if ctx.installdb.is_installed(x):
|
if ctx.installdb.is_installed(x):
|
||||||
operations.remove_single(x)
|
operations.remove_single(x)
|
||||||
else:
|
else:
|
||||||
ctx.ui.info('Package %s is not installed. Cannot remove.\n' % x)
|
ctx.ui.info('Package %s is not installed. Cannot remove.' % x)
|
||||||
|
|
||||||
return True # everything went OK :)
|
return True # everything went OK :)
|
||||||
|
|
||||||
@@ -423,11 +424,11 @@ def info_name(package_name):
|
|||||||
|
|
||||||
def index(repo_dir = '.'):
|
def index(repo_dir = '.'):
|
||||||
|
|
||||||
ctx.ui.info('* Building index of PISI files under %s\n' % repo_dir)
|
ctx.ui.info('* Building index of PISI files under %s' % repo_dir)
|
||||||
index = Index()
|
index = Index()
|
||||||
index.index(repo_dir)
|
index.index(repo_dir)
|
||||||
index.write(ctx.const.pisi_index)
|
index.write(ctx.const.pisi_index)
|
||||||
ctx.ui.info('* Index file written\n')
|
ctx.ui.info('* Index file written')
|
||||||
|
|
||||||
|
|
||||||
def add_repo(name, indexuri):
|
def add_repo(name, indexuri):
|
||||||
@@ -438,16 +439,16 @@ def remove_repo(name):
|
|||||||
if ctx.repodb.has_repo(name):
|
if ctx.repodb.has_repo(name):
|
||||||
ctx.repodb.remove_repo(name)
|
ctx.repodb.remove_repo(name)
|
||||||
else:
|
else:
|
||||||
ctx.ui.error('* Repository %s does not exist. Cannot remove.\n'
|
ctx.ui.error('* Repository %s does not exist. Cannot remove.'
|
||||||
% name)
|
% name)
|
||||||
|
|
||||||
def update_repo(repo):
|
def update_repo(repo):
|
||||||
|
|
||||||
ctx.ui.info('* Updating repository: %s\n' % repo)
|
ctx.ui.info('* Updating repository: %s' % repo)
|
||||||
index = Index()
|
index = Index()
|
||||||
index.read(ctx.repodb.get_repo(repo).indexuri.get_uri(), repo)
|
index.read(ctx.repodb.get_repo(repo).indexuri.get_uri(), repo)
|
||||||
index.update_db(repo)
|
index.update_db(repo)
|
||||||
ctx.ui.info('* Package database updated.\n')
|
ctx.ui.info('* Package database updated.')
|
||||||
|
|
||||||
|
|
||||||
# build functions...
|
# build functions...
|
||||||
@@ -513,7 +514,7 @@ def build_until(pspecfile, state, authInfo=None):
|
|||||||
pb.compile_action_script()
|
pb.compile_action_script()
|
||||||
|
|
||||||
last = pb.get_state()
|
last = pb.get_state()
|
||||||
ctx.ui.info("Last state was %s\n"%last)
|
ctx.ui.info("Last state was %s"%last)
|
||||||
|
|
||||||
if not last: last = "none"
|
if not last: last = "none"
|
||||||
|
|
||||||
|
|||||||
+11
-11
@@ -71,7 +71,7 @@ def check_path_collision(package, pkgList):
|
|||||||
# path.pathname: /usr/share/doc
|
# path.pathname: /usr/share/doc
|
||||||
if util.subpath(pinfo.pathname, path.pathname):
|
if util.subpath(pinfo.pathname, path.pathname):
|
||||||
collisions.append(path.pathname)
|
collisions.append(path.pathname)
|
||||||
ctx.ui.error(_('Path %s belongs in multiple packages\n') %
|
ctx.ui.error(_('Path %s belongs in multiple packages') %
|
||||||
path.pathname)
|
path.pathname)
|
||||||
return collisions
|
return collisions
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ class PisiBuild:
|
|||||||
def build(self):
|
def build(self):
|
||||||
"""Build the package in one shot."""
|
"""Build the package in one shot."""
|
||||||
|
|
||||||
ctx.ui.info(_("Building PISI source package: %s\n") % self.spec.source.name)
|
ctx.ui.info(_("Building PISI source package: %s") % self.spec.source.name)
|
||||||
util.xterm_title(_("Building PISI source package: %s\n") % self.spec.source.name)
|
util.xterm_title(_("Building PISI source package: %s\n") % self.spec.source.name)
|
||||||
|
|
||||||
self.compile_action_script()
|
self.compile_action_script()
|
||||||
@@ -178,15 +178,15 @@ class PisiBuild:
|
|||||||
os.environ.update(evn)
|
os.environ.update(evn)
|
||||||
|
|
||||||
def fetch_source_archive(self):
|
def fetch_source_archive(self):
|
||||||
ctx.ui.info(_("Fetching source from: %s\n") % self.spec.source.archiveUri)
|
ctx.ui.info(_("Fetching source from: %s") % self.spec.source.archiveUri)
|
||||||
self.sourceArchive.fetch()
|
self.sourceArchive.fetch()
|
||||||
ctx.ui.info(_("Source archive is stored: %s/%s\n")
|
ctx.ui.info(_("Source archive is stored: %s/%s")
|
||||||
%(ctx.config.archives_dir(), self.spec.source.archiveName))
|
%(ctx.config.archives_dir(), self.spec.source.archiveName))
|
||||||
|
|
||||||
def unpack_source_archive(self):
|
def unpack_source_archive(self):
|
||||||
ctx.ui.info(_("Unpacking archive..."))
|
ctx.ui.info(_("Unpacking archive..."))
|
||||||
self.sourceArchive.unpack()
|
self.sourceArchive.unpack()
|
||||||
ctx.ui.info(_(" unpacked (%s)\n") % self.bctx.pkg_work_dir())
|
ctx.ui.info(_(" unpacked (%s)") % self.bctx.pkg_work_dir())
|
||||||
self.set_state("unpack")
|
self.set_state("unpack")
|
||||||
|
|
||||||
def run_setup_action(self):
|
def run_setup_action(self):
|
||||||
@@ -220,10 +220,10 @@ class PisiBuild:
|
|||||||
buf = open(scriptfile).read()
|
buf = open(scriptfile).read()
|
||||||
exec compile(buf, "error", "exec") in localSymbols, globalSymbols
|
exec compile(buf, "error", "exec") in localSymbols, globalSymbols
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
ctx.ui.error(_("Unable to read Action Script (%s): %s\n") %(scriptfile,e))
|
ctx.ui.error(_("Unable to read Action Script (%s): %s") %(scriptfile,e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except SyntaxError, e:
|
except SyntaxError, e:
|
||||||
ctx.ui.error (_("SyntaxError in Action Script (%s): %s\n") %(scriptfile,e))
|
ctx.ui.error (_("SyntaxError in Action Script (%s): %s") %(scriptfile,e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
self.actionLocals = localSymbols
|
self.actionLocals = localSymbols
|
||||||
@@ -427,17 +427,17 @@ class PisiBuild:
|
|||||||
self.spec.source.version,
|
self.spec.source.version,
|
||||||
self.spec.source.release)
|
self.spec.source.release)
|
||||||
|
|
||||||
ctx.ui.action(_("** Building package %s\n") % package.name);
|
ctx.ui.action(_("** Building package %s") % package.name);
|
||||||
|
|
||||||
ctx.ui.action(_("Generating %s...") % ctx.const.files_xml)
|
ctx.ui.action(_("Generating %s...") % ctx.const.files_xml)
|
||||||
self.gen_files_xml(package)
|
self.gen_files_xml(package)
|
||||||
ctx.ui.info(_(" done.\n"))
|
ctx.ui.info(_(" done."))
|
||||||
|
|
||||||
ctx.ui.action(_("Generating %s...") % ctx.const.metadata_xml)
|
ctx.ui.action(_("Generating %s...") % ctx.const.metadata_xml)
|
||||||
self.gen_metadata_xml(package)
|
self.gen_metadata_xml(package)
|
||||||
ctx.ui.info(_(" done.\n"))
|
ctx.ui.info(_(" done."))
|
||||||
|
|
||||||
ctx.ui.action(_("Creating PISI package %s\n") % name)
|
ctx.ui.action(_("Creating PISI package %s") % name)
|
||||||
|
|
||||||
pkg = Package(name, 'w')
|
pkg = Package(name, 'w')
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
Writing commands:
|
Writing commands:
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
TODO: this is a *bit* out of date now.
|
||||||
|
|
||||||
Subclass from Command.
|
Subclass from Command.
|
||||||
|
|
||||||
Be careful not to import PiSi modules before Command is run, e.g.
|
Be careful not to import PiSi modules before Command is run, e.g.
|
||||||
|
|||||||
@@ -11,10 +11,74 @@
|
|||||||
# pisi.cli package version
|
# pisi.cli package version
|
||||||
__version__ = "0.1"
|
__version__ = "0.1"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
import pisi
|
import pisi
|
||||||
|
from pisi.ui import UI
|
||||||
|
from pisi.cli.colors import colorize
|
||||||
|
|
||||||
|
|
||||||
class Error(pisi.Error):
|
class Error(pisi.Error):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Exception(pisi.Exception):
|
class Exception(pisi.Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CLI(UI):
|
||||||
|
"Command Line Interface"
|
||||||
|
|
||||||
|
def __init__(self, show_debug = False, show_verbose = False):
|
||||||
|
super(CLI, self).__init__(show_debug, show_verbose)
|
||||||
|
|
||||||
|
def output(self, str):
|
||||||
|
sys.stdout.write(str)
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
def info(self, msg, verbose = False):
|
||||||
|
# TODO: need to look at more kinds of info messages
|
||||||
|
# let's cheat from KDE :)
|
||||||
|
if verbose and self.show_verbose:
|
||||||
|
self.output(msg + '\n')
|
||||||
|
elif not verbose:
|
||||||
|
self.output(msg + '\n')
|
||||||
|
|
||||||
|
def warning(self,msg):
|
||||||
|
self.output(colorize('Warning:' + msg + '\n', 'purple'))
|
||||||
|
|
||||||
|
def error(self,msg):
|
||||||
|
self.output(colorize('Error:' + msg + '\n', 'red'))
|
||||||
|
|
||||||
|
def action(self,msg):
|
||||||
|
#TODO: this seems quite redundant?
|
||||||
|
self.output(colorize(msg + '\n', 'green'))
|
||||||
|
|
||||||
|
def choose(self, msg, opts):
|
||||||
|
print msg
|
||||||
|
for i in range(0,len(opts)):
|
||||||
|
print i + 1, opts(i)
|
||||||
|
while True:
|
||||||
|
s = raw_input(msg + colorize('1-%d' % len(opts), 'red'))
|
||||||
|
try:
|
||||||
|
opt = int(s)
|
||||||
|
if 1 <= opt and opt <= len(opts):
|
||||||
|
return opts(opt-1)
|
||||||
|
except (Exception,e):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def confirm(self, msg):
|
||||||
|
if ctx.config.options and ctx.config.options.yes_all:
|
||||||
|
return True
|
||||||
|
while True:
|
||||||
|
s = raw_input(msg + colorize('(yes/no)', 'red'))
|
||||||
|
if s.startswith('y') or s.startswith('Y'):
|
||||||
|
return True
|
||||||
|
if s.startswith('n') or s.startswith('N'):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def display_progress(self, pd):
|
||||||
|
out = '\r%-30.30s %3d%% %12.2f %s' % \
|
||||||
|
(pd['filename'], pd['percent'], pd['rate'], pd['symbol'])
|
||||||
|
self.output(out)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -111,7 +111,7 @@ dependency spec"""
|
|||||||
def satisfies_dependencies(pkg, deps, sat = installed_satisfies_dep):
|
def satisfies_dependencies(pkg, deps, sat = installed_satisfies_dep):
|
||||||
for dep in deps:
|
for dep in deps:
|
||||||
if not sat(dep):
|
if not sat(dep):
|
||||||
ctx.ui.error('Package %s does not satisfy dependency %s\n' %
|
ctx.ui.error('Package %s does not satisfy dependency %s' %
|
||||||
(pkg,dep))
|
(pkg,dep))
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@@ -124,7 +124,7 @@ def installable(pkg):
|
|||||||
"""calculate if pkg is installable currently
|
"""calculate if pkg is installable currently
|
||||||
which means it has to satisfy both install and runtime dependencies"""
|
which means it has to satisfy both install and runtime dependencies"""
|
||||||
if not packagedb.has_package(pkg):
|
if not packagedb.has_package(pkg):
|
||||||
ctx.ui.info("Package " + pkg + " is not present in the package database\n");
|
ctx.ui.info("Package " + pkg + " is not present in the package database");
|
||||||
return False
|
return False
|
||||||
elif satisfies_runtime_deps(pkg):
|
elif satisfies_runtime_deps(pkg):
|
||||||
return True
|
return True
|
||||||
|
|||||||
+2
-1
@@ -37,7 +37,8 @@ def fetch_url(url, dest, progress=None):
|
|||||||
fetch.progress = progress
|
fetch.progress = progress
|
||||||
fetch.fetch()
|
fetch.fetch()
|
||||||
if progress:
|
if progress:
|
||||||
ctx.ui.info('\n')
|
pass
|
||||||
|
#ctx.ui.info('\n')
|
||||||
|
|
||||||
|
|
||||||
class Fetcher:
|
class Fetcher:
|
||||||
|
|||||||
+2
-2
@@ -67,7 +67,7 @@ class Index(XmlFile):
|
|||||||
for root, dirs, files in os.walk(repo_uri):
|
for root, dirs, files in os.walk(repo_uri):
|
||||||
for fn in files:
|
for fn in files:
|
||||||
if fn.endswith(ctx.const.package_prefix):
|
if fn.endswith(ctx.const.package_prefix):
|
||||||
ctx.ui.info('Adding ' + fn + ' to package index\n')
|
ctx.ui.info('Adding ' + fn + ' to package index')
|
||||||
self.add_package(os.path.join(root, fn), repo_uri)
|
self.add_package(os.path.join(root, fn), repo_uri)
|
||||||
|
|
||||||
def update_db(self, repo):
|
def update_db(self, repo):
|
||||||
@@ -93,6 +93,6 @@ class Index(XmlFile):
|
|||||||
md.package.packageURI = util.removepathprefix(repo_uri, path)
|
md.package.packageURI = util.removepathprefix(repo_uri, path)
|
||||||
# check package semantics
|
# check package semantics
|
||||||
if md.has_errors():
|
if md.has_errors():
|
||||||
ctx.ui.error('Package ' + md.package.name + ': metadata corrupt\n')
|
ctx.ui.error('Package ' + md.package.name + ': metadata corrupt')
|
||||||
else:
|
else:
|
||||||
self.packages.append(md.package)
|
self.packages.append(md.package)
|
||||||
|
|||||||
+9
-9
@@ -44,7 +44,7 @@ class Installer:
|
|||||||
|
|
||||||
def install(self, ask_reinstall = True):
|
def install(self, ask_reinstall = True):
|
||||||
"entry point"
|
"entry point"
|
||||||
ctx.ui.info('Installing %s, version %s, release %s, build %s\n' %
|
ctx.ui.info('Installing %s, version %s, release %s, build %s' %
|
||||||
(self.pkginfo.name, self.pkginfo.version,
|
(self.pkginfo.name, self.pkginfo.version,
|
||||||
self.pkginfo.release, self.pkginfo.build))
|
self.pkginfo.release, self.pkginfo.build))
|
||||||
self.ask_reinstall = ask_reinstall
|
self.ask_reinstall = ask_reinstall
|
||||||
@@ -77,7 +77,7 @@ class Installer:
|
|||||||
# check dependencies
|
# check dependencies
|
||||||
if not dependency.installable(self.pkginfo.name):
|
if not dependency.installable(self.pkginfo.name):
|
||||||
ctx.ui.error('Dependencies for ' + self.pkginfo.name +
|
ctx.ui.error('Dependencies for ' + self.pkginfo.name +
|
||||||
' not satisfied\n')
|
' not satisfied')
|
||||||
raise InstallError("Package not installable")
|
raise InstallError("Package not installable")
|
||||||
|
|
||||||
def reinstall(self):
|
def reinstall(self):
|
||||||
@@ -108,14 +108,14 @@ class Installer:
|
|||||||
# is this an upgrade?
|
# is this an upgrade?
|
||||||
# determine and report the kind of upgrade: version, release, build
|
# determine and report the kind of upgrade: version, release, build
|
||||||
if pkg.version > iversion:
|
if pkg.version > iversion:
|
||||||
ctx.ui.info('Upgrading to new upstream version\n')
|
ctx.ui.info('Upgrading to new upstream version')
|
||||||
upgrade = True
|
upgrade = True
|
||||||
elif pkg.release > irelease:
|
elif pkg.release > irelease:
|
||||||
ctx.ui.info('Upgrading to new distribution release\n')
|
ctx.ui.info('Upgrading to new distribution release')
|
||||||
upgrade = True
|
upgrade = True
|
||||||
elif ((not ignore_build) and ibuild and pkg.build
|
elif ((not ignore_build) and ibuild and pkg.build
|
||||||
and pkg.build > ibuild):
|
and pkg.build > ibuild):
|
||||||
ctx.ui.info('Upgrading to new distribution build\n')
|
ctx.ui.info('Upgrading to new distribution build')
|
||||||
upgrade = True
|
upgrade = True
|
||||||
|
|
||||||
# is this a downgrade? confirm this action.
|
# is this a downgrade? confirm this action.
|
||||||
@@ -135,7 +135,7 @@ class Installer:
|
|||||||
def extract_install(self):
|
def extract_install(self):
|
||||||
"unzip package in place"
|
"unzip package in place"
|
||||||
|
|
||||||
ctx.ui.info('Extracting files,\n')
|
ctx.ui.info('Extracting files,')
|
||||||
self.package.extract_dir_flat('install', ctx.config.destdir)
|
self.package.extract_dir_flat('install', ctx.config.destdir)
|
||||||
|
|
||||||
def store_pisi_files(self):
|
def store_pisi_files(self):
|
||||||
@@ -145,14 +145,14 @@ class Installer:
|
|||||||
ctx.ui.info('Storing %s, ' % ctx.const.files_xml)
|
ctx.ui.info('Storing %s, ' % ctx.const.files_xml)
|
||||||
self.package.extract_file(ctx.const.files_xml, self.package.pkg_dir())
|
self.package.extract_file(ctx.const.files_xml, self.package.pkg_dir())
|
||||||
|
|
||||||
ctx.ui.info('%s.\n' % ctx.const.metadata_xml)
|
ctx.ui.info('%s.' % ctx.const.metadata_xml)
|
||||||
self.package.extract_file(ctx.const.metadata_xml, self.package.pkg_dir())
|
self.package.extract_file(ctx.const.metadata_xml, self.package.pkg_dir())
|
||||||
|
|
||||||
for pcomar in self.metadata.package.providesComar:
|
for pcomar in self.metadata.package.providesComar:
|
||||||
fpath = os.path.join(ctx.const.comar_dir, pcomar.script)
|
fpath = os.path.join(ctx.const.comar_dir, pcomar.script)
|
||||||
# comar prefix is added to the pkg_dir while extracting comar
|
# comar prefix is added to the pkg_dir while extracting comar
|
||||||
# script file. so we'll use pkg_dir as destination.
|
# script file. so we'll use pkg_dir as destination.
|
||||||
ctx.ui.info('Storing %s\n' % fpath)
|
ctx.ui.info('Storing %s' % fpath)
|
||||||
self.package.extract_file(fpath, self.package.pkg_dir())
|
self.package.extract_file(fpath, self.package.pkg_dir())
|
||||||
|
|
||||||
def register_comar_scripts(self):
|
def register_comar_scripts(self):
|
||||||
@@ -160,7 +160,7 @@ class Installer:
|
|||||||
|
|
||||||
for pcomar in self.metadata.package.providesComar:
|
for pcomar in self.metadata.package.providesComar:
|
||||||
scriptPath = os.path.join(self.package.comar_dir(),pcomar.script)
|
scriptPath = os.path.join(self.package.comar_dir(),pcomar.script)
|
||||||
ctx.ui.info("Registering COMAR script %s\n" % pcomar.script)
|
ctx.ui.info("Registering COMAR script %s" % pcomar.script)
|
||||||
# FIXME: We must check the result of the command (possibly
|
# FIXME: We must check the result of the command (possibly
|
||||||
# with id?)
|
# with id?)
|
||||||
if comard:
|
if comard:
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class LockedDBShelf(shelve.DBShelf):
|
|||||||
fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
except IOError:
|
except IOError:
|
||||||
import sys
|
import sys
|
||||||
pisi.context.ui.error("Another instance of PISI is running. Try later!\n")
|
pisi.context.ui.error("Another instance of PISI is running. Try later!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
return self.db.open(filename, dbname, filetype, flags, mode)
|
return self.db.open(filename, dbname, filetype, flags, mode)
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -7,8 +7,9 @@
|
|||||||
#
|
#
|
||||||
# Please read the COPYING file.
|
# Please read the COPYING file.
|
||||||
#
|
#
|
||||||
|
#
|
||||||
|
|
||||||
# Package Operations: install/remove/upgrade
|
"Package Operations: install/remove/upgrade"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@@ -46,7 +47,6 @@ def remove_single(package_name):
|
|||||||
if comard:
|
if comard:
|
||||||
# FIXME: (return value)...
|
# FIXME: (return value)...
|
||||||
comard.remove(package_name)
|
comard.remove(package_name)
|
||||||
ctx.ui.info('.\n')
|
|
||||||
|
|
||||||
def install_single(pkg, upgrade = False):
|
def install_single(pkg, upgrade = False):
|
||||||
"""install a single package from URI or ID"""
|
"""install a single package from URI or ID"""
|
||||||
@@ -81,12 +81,12 @@ def install_single_name(name, upgrade = False):
|
|||||||
pkg_path = os.path.join(os.path.dirname(repo.indexuri.get_uri()),
|
pkg_path = os.path.join(os.path.dirname(repo.indexuri.get_uri()),
|
||||||
str(pkg_uri.path()))
|
str(pkg_uri.path()))
|
||||||
|
|
||||||
ctx.ui.debug("Package URI: %s\n" % pkg_path)
|
ctx.ui.debug("Package URI: %s" % pkg_path)
|
||||||
|
|
||||||
# Package will handle remote file for us!
|
# Package will handle remote file for us!
|
||||||
install_single_file(pkg_path, upgrade)
|
install_single_file(pkg_path, upgrade)
|
||||||
else:
|
else:
|
||||||
ctx.ui.error("Package %s not found in any active repository.\n" % pkg)
|
ctx.ui.error("Package %s not found in any active repository." % pkg)
|
||||||
|
|
||||||
# deneme, don't remove ulan
|
# deneme, don't remove ulan
|
||||||
class AtomicOperation(object):
|
class AtomicOperation(object):
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ class PackageDB(object):
|
|||||||
fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
import sys
|
import sys
|
||||||
ctx.ui.error("PackageDB: %s\n" % e)
|
ctx.ui.error("PackageDB: %s" % e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self.d = shelve.open(self.fname)
|
self.d = shelve.open(self.fname)
|
||||||
self.dr = shelve.open(self.fname2)
|
self.dr = shelve.open(self.fname2)
|
||||||
|
|||||||
@@ -9,12 +9,11 @@
|
|||||||
#
|
#
|
||||||
# Please read the COPYING file.
|
# Please read the COPYING file.
|
||||||
#
|
#
|
||||||
|
# Authors: Baris Metin <baris@uludag.org.tr>
|
||||||
|
# Eray Ozkural <eray@uludag.org.tr>
|
||||||
|
|
||||||
# python standard library
|
# python standard library
|
||||||
|
|
||||||
# Authors: Baris Metin <baris@uludag.org.tr
|
|
||||||
# Eray Ozkural <eray@uludag.org.tr>
|
|
||||||
|
|
||||||
from os.path import join
|
from os.path import join
|
||||||
from os import access, R_OK
|
from os import access, R_OK
|
||||||
|
|
||||||
@@ -55,7 +54,7 @@ class SourceArchive:
|
|||||||
# check hash
|
# check hash
|
||||||
if util.check_file_hash(self.archiveFile, self.archiveSHA1):
|
if util.check_file_hash(self.archiveFile, self.archiveSHA1):
|
||||||
if interactive:
|
if interactive:
|
||||||
ctx.ui.info('%s [cached]\n' % self.archiveName)
|
ctx.ui.info('%s [cached]' % self.archiveName)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class SourceFetcher(object):
|
|||||||
def fetch(self, appendDest=""):
|
def fetch(self, appendDest=""):
|
||||||
from fetcher import fetch_url
|
from fetcher import fetch_url
|
||||||
|
|
||||||
ctx.ui.info("Fetching %s\n" % self.url.uri)
|
ctx.ui.info("Fetching %s" % self.url.uri)
|
||||||
dest = join(self.dest, appendDest)
|
dest = join(self.dest, appendDest)
|
||||||
fetch_url(self.url, dest)
|
fetch_url(self.url, dest)
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -9,13 +9,19 @@
|
|||||||
#
|
#
|
||||||
# Please read the COPYING file.
|
# 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>
|
# 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>
|
||||||
|
# History:
|
||||||
|
# Baris wrote the first version, then Baris and Eray did
|
||||||
|
# several revisions of it. It was rewritten in accordance
|
||||||
|
# with Gurer's observations.
|
||||||
|
|
||||||
|
|
||||||
|
"""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."""
|
||||||
|
|
||||||
|
|
||||||
# standard python modules
|
# standard python modules
|
||||||
from os.path import basename
|
from os.path import basename
|
||||||
|
|||||||
+50
-54
@@ -7,63 +7,18 @@
|
|||||||
#
|
#
|
||||||
# Please read the COPYING file.
|
# Please read the COPYING file.
|
||||||
#
|
#
|
||||||
|
|
||||||
# generic user interface
|
# generic user interface
|
||||||
|
#
|
||||||
# Authors: Eray Ozkural <eray@uludag.org.tr>
|
# Authors: Eray Ozkural <eray@uludag.org.tr>
|
||||||
# Murat Eren <meren@uludag.org.tr>
|
# Murat Eren <meren@uludag.org.tr>
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pisi.colors import colorize
|
import pisi
|
||||||
|
import pisi.context as ctx
|
||||||
|
|
||||||
|
class UI(object):
|
||||||
class CLI:
|
"Abstract class for UI operations, derive from this."
|
||||||
"Command Line Interface"
|
|
||||||
def __init__(self, debuggy = False, verbose = False):
|
|
||||||
self.show_debug = debuggy
|
|
||||||
self.show_verbose = verbose
|
|
||||||
|
|
||||||
def set_verbose(self, flag):
|
|
||||||
self.show_verbose = flag
|
|
||||||
|
|
||||||
def set_debug(self, flag):
|
|
||||||
self.show_debug = flag
|
|
||||||
|
|
||||||
def info(self, msg, verbose = False):
|
|
||||||
if verbose and self.show_verbose:
|
|
||||||
sys.stdout.write(colorize(msg, 'blue'))
|
|
||||||
elif not verbose:
|
|
||||||
sys.stdout.write(colorize(msg, 'blue'))
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def debug(self, msg):
|
|
||||||
if self.show_debug:
|
|
||||||
sys.stdout.write(msg)
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def warning(self,msg):
|
|
||||||
sys.stdout.write(colorize('Warning:' + msg, 'purple'))
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def error(self,msg):
|
|
||||||
sys.stdout.write(colorize('Error:' + msg, 'red'))
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def action(self,msg):
|
|
||||||
sys.stdout.write(colorize(msg, 'green'))
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
def confirm(self, msg):
|
|
||||||
from pisi.config import config
|
|
||||||
if config.options and config.options.yes_all:
|
|
||||||
return True
|
|
||||||
while True:
|
|
||||||
s = raw_input(msg + colorize('(yes/no)', 'red'))
|
|
||||||
if s.startswith('y') or s.startswith('Y'):
|
|
||||||
return True
|
|
||||||
if s.startswith('n') or s.startswith('N'):
|
|
||||||
return False
|
|
||||||
|
|
||||||
class Progress:
|
class Progress:
|
||||||
def __init__(self, totalsize):
|
def __init__(self, totalsize):
|
||||||
@@ -81,8 +36,49 @@ class CLI:
|
|||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def display_progress(self, pd):
|
def __init__(self, debuggy = False, verbose = False):
|
||||||
out = '\r%-30.30s %3d%% %12.2f %s' % \
|
self.show_debug = debuggy
|
||||||
(pd['filename'], pd['percent'], pd['rate'], pd['symbol'])
|
self.show_verbose = verbose
|
||||||
self.info(out)
|
|
||||||
|
|
||||||
|
def set_verbose(self, flag):
|
||||||
|
self.show_verbose = flag
|
||||||
|
|
||||||
|
def set_debug(self, flag):
|
||||||
|
self.show_debug = flag
|
||||||
|
|
||||||
|
def info(self, msg, verbose = False):
|
||||||
|
"give an informative message"
|
||||||
|
pass
|
||||||
|
|
||||||
|
def ack(self, msg):
|
||||||
|
"inform the user of an important event and wait for acknowledgement"
|
||||||
|
pass
|
||||||
|
|
||||||
|
def debug(self, msg):
|
||||||
|
"show debugging info"
|
||||||
|
if self.show_debug:
|
||||||
|
self.info('DEBUG: ' + msg)
|
||||||
|
|
||||||
|
def warning(self,msg):
|
||||||
|
"warn the user"
|
||||||
|
pass
|
||||||
|
|
||||||
|
def error(self,msg):
|
||||||
|
"inform a (possibly fatal) error"
|
||||||
|
pass
|
||||||
|
|
||||||
|
def action(self,msg):
|
||||||
|
"uh?"
|
||||||
|
pass
|
||||||
|
|
||||||
|
def choose(self, msg, list):
|
||||||
|
"ask the user to choose from a list of alternatives"
|
||||||
|
pass
|
||||||
|
|
||||||
|
def confirm(self, msg):
|
||||||
|
"ask a yes/no question"
|
||||||
|
pass
|
||||||
|
|
||||||
|
def display_progress(self, pd):
|
||||||
|
"display progress"
|
||||||
|
pass
|
||||||
|
|||||||
+1
-1
@@ -363,7 +363,7 @@ def clean_locks(top = '.'):
|
|||||||
for fn in files:
|
for fn in files:
|
||||||
if fn.endswith('.lock'):
|
if fn.endswith('.lock'):
|
||||||
path = os.path.join(root, fn)
|
path = os.path.join(root, fn)
|
||||||
ctx.ui.info('Removing lock %s\n', path)
|
ctx.ui.info('Removing lock %s', path)
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
|
|||||||
+124
-53
@@ -24,7 +24,8 @@
|
|||||||
in xml.dom :( )
|
in xml.dom :( )
|
||||||
|
|
||||||
autoxml is a metaclass for automatic XML translation, using
|
autoxml is a metaclass for automatic XML translation, using
|
||||||
a miniature type system. (w00t!)
|
a miniature type system. (w00t!) This is based on an excellent
|
||||||
|
high-level XML processing prototype that Gurer prepared.
|
||||||
|
|
||||||
Method names are mixedCase for compatibility with minidom,
|
Method names are mixedCase for compatibility with minidom,
|
||||||
an old library.
|
an old library.
|
||||||
@@ -38,22 +39,23 @@ import codecs
|
|||||||
# PiSi
|
# PiSi
|
||||||
import pisi
|
import pisi
|
||||||
from pisi.xmlext import *
|
from pisi.xmlext import *
|
||||||
|
import pisi.context as ctx
|
||||||
|
|
||||||
|
|
||||||
class Error(pisi.Error):
|
class Error(pisi.Error):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
import types
|
import types
|
||||||
|
|
||||||
mandatory, optional = range(2) # poor man's enum
|
mandatory, optional = range(2) # poor man's enum
|
||||||
|
|
||||||
# basic types
|
# basic types
|
||||||
|
|
||||||
Text = types.StringType
|
Text = types.StringType
|
||||||
Integer = types.IntType
|
Integer = types.IntType
|
||||||
|
|
||||||
class LocalText:
|
class LocalText(object):
|
||||||
"handle tags with localized text"
|
"""Handles XML tags/attributes with localized text"""
|
||||||
|
|
||||||
def __init__():
|
def __init__():
|
||||||
locs = {}
|
locs = {}
|
||||||
@@ -80,17 +82,89 @@ class LocalText:
|
|||||||
if not locs.has_key(L):
|
if not locs.has_key(L):
|
||||||
L = 'en'
|
L = 'en'
|
||||||
if not locs.has_key(L):
|
if not locs.has_key(L):
|
||||||
errs.append("Tag '%s' should have an English version\n" % d[2])
|
#errs.append("Tag '%s' should have an English version\n" % d[2])
|
||||||
return ""
|
return ""
|
||||||
return locs[L]
|
return locs[L]
|
||||||
|
|
||||||
|
|
||||||
class autoxml(type):
|
class autoxml(type):
|
||||||
"high-level automatic XML transformation interface for xmlfile"
|
"""High-level automatic XML transformation interface for xmlfile.
|
||||||
|
The idea is to declare a class for each XML tag. Inside the
|
||||||
|
class the tags and attributes nested in the tag are further
|
||||||
|
elaborated. A simple example follows:
|
||||||
|
|
||||||
|
class Employee:
|
||||||
|
__metaclass__ = autoxml
|
||||||
|
t_Name = [xmlfile.Text, xmlfile.mandatory]
|
||||||
|
a_Type = [xmlfile.Integer, xmlfile.optional]
|
||||||
|
|
||||||
|
This class defines a tag and an attribute nested in Employee
|
||||||
|
class. Name is a string and type is an integer, called basic
|
||||||
|
types.
|
||||||
|
While the tag is mandatory, the attribute may be left out.
|
||||||
|
|
||||||
|
Other basic types supported are: xmlfile.Float, xmlfile.Double
|
||||||
|
and (not implemented yet): xmlfile.Binary
|
||||||
|
|
||||||
|
By default, the class name is taken as the corresponding tag,
|
||||||
|
which may be overridden by defining a tag attribute. Thus,
|
||||||
|
the same tag may also be written as:
|
||||||
|
|
||||||
|
class EmployeeXML:
|
||||||
|
...
|
||||||
|
tag = 'Employee'
|
||||||
|
...
|
||||||
|
|
||||||
|
In addition to basic types, we allow for two kinds of complex
|
||||||
|
types: class types and list types.
|
||||||
|
|
||||||
|
A declared class can be nested in another class as follows
|
||||||
|
|
||||||
|
class Position:
|
||||||
|
__metaclass__ = autoxml
|
||||||
|
t_Name = [xmlfile.Text, xmlfile.mandatory]
|
||||||
|
t_Description = [xmlfile.Text, xmlfile.optional]
|
||||||
|
|
||||||
|
which we can add to our Employee class.
|
||||||
|
|
||||||
|
class Employee:
|
||||||
|
__metaclass__ = autoxml
|
||||||
|
t_Name = [xmlfile.Text, xmlfile.mandatory]
|
||||||
|
a_Type = [xmlfile.Integer, xmlfile.optional]
|
||||||
|
t_Position = [Position, xmlfile.mandatory]
|
||||||
|
|
||||||
|
Note some unfortunate redundancy here with Position; this is
|
||||||
|
justified by the implementation (kidding). Still, you might
|
||||||
|
want to assign a different name than the class name that
|
||||||
|
goes in there, which may be fully qualified.
|
||||||
|
|
||||||
|
There is more! Suppose we want to define a company, with
|
||||||
|
of course many employees.
|
||||||
|
|
||||||
|
class Company:
|
||||||
|
__metaclass__ = autoxml
|
||||||
|
t_Employees = [ Employee, xmlfile.mandatory]
|
||||||
|
|
||||||
|
Logically, inside the Company tag, we will have several Employee
|
||||||
|
tags, which are inserted to the Employees instance variable of
|
||||||
|
Company in order of appearance.
|
||||||
|
The mandatory flag here asserts that at least one such record
|
||||||
|
is to be found.
|
||||||
|
|
||||||
|
It is also possible to change the XML path we expect the tag in,
|
||||||
|
just like with any other tag.
|
||||||
|
|
||||||
|
t_Employees = [ Employee, xmlfile.mandatory, 'Employees/Employee']
|
||||||
|
|
||||||
|
|
||||||
|
You see, it works like magic, when it works of course. All of it
|
||||||
|
done without a single brain exploding.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(cls, name, bases, dict):
|
def __init__(cls, name, bases, dict):
|
||||||
|
|
||||||
# add XmlFile as one of the superclasses
|
# add XmlFile as one of the superclasses, we're smart
|
||||||
bases = list(bases)
|
bases = list(bases)
|
||||||
if not XmlFile in bases:
|
if not XmlFile in bases:
|
||||||
bases.append(XmlFile)
|
bases.append(XmlFile)
|
||||||
@@ -98,7 +172,7 @@ class autoxml(type):
|
|||||||
# standard initialization
|
# standard initialization
|
||||||
super(autoxml, cls).__init__(name, bases, dict)
|
super(autoxml, cls).__init__(name, bases, dict)
|
||||||
|
|
||||||
# initialize class attribute __xml_tags
|
#TODO: initialize class attribute __xml_tags
|
||||||
#setattr(cls, 'xml_variables', [])
|
#setattr(cls, 'xml_variables', [])
|
||||||
|
|
||||||
if not dict.has_key('tag'):
|
if not dict.has_key('tag'):
|
||||||
@@ -119,12 +193,15 @@ class autoxml(type):
|
|||||||
x = autoxml.gen_tag(cls, name)
|
x = autoxml.gen_tag(cls, name)
|
||||||
elif var.startswith('a_'):
|
elif var.startswith('a_'):
|
||||||
x = autoxml.gen_attr(cls, name)
|
x = autoxml.gen_attr(cls, name)
|
||||||
|
ctx.ui.debug(x)
|
||||||
(init, decoder, encoder, formatter) = x
|
(init, decoder, encoder, formatter) = x
|
||||||
inits.append(init)
|
inits.append(init)
|
||||||
decoders.append(decoder)
|
decoders.append(decoder)
|
||||||
encoders.append(encoder)
|
encoders.append(encoder)
|
||||||
formatters.append(formatter)
|
formatters.append(formatter)
|
||||||
|
|
||||||
|
varname = cls.mixed_case(name)
|
||||||
|
|
||||||
setattr(cls, 'initializers', inits)
|
setattr(cls, 'initializers', inits)
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
for init in self.__class__.initializers:
|
for init in self.__class__.initializers:
|
||||||
@@ -134,13 +211,13 @@ class autoxml(type):
|
|||||||
setattr(cls, 'decoders', decoders)
|
setattr(cls, 'decoders', decoders)
|
||||||
def decode(self, node):
|
def decode(self, node):
|
||||||
for decoder in self.__class__.decoders:
|
for decoder in self.__class__.decoders:
|
||||||
decoder(self, node)
|
setattr(self, varname, decoder(self, node))
|
||||||
setattr(cls, 'decode', decode)
|
setattr(cls, 'decode', decode)
|
||||||
|
|
||||||
setattr(cls, 'encoders', encoders)
|
setattr(cls, 'encoders', encoders)
|
||||||
def encode(self, xml):
|
def encode(self, xml):
|
||||||
for encoder in self.__class__.encoders:
|
for encoder in self.__class__.encoders:
|
||||||
encoder(self, xml)
|
encoder(self, xml, getattr(self, varname))
|
||||||
setattr(cls, 'encode', encode)
|
setattr(cls, 'encode', encode)
|
||||||
|
|
||||||
setattr(cls, 'formatters', formatters)
|
setattr(cls, 'formatters', formatters)
|
||||||
@@ -183,7 +260,9 @@ class autoxml(type):
|
|||||||
return identifier_p
|
return identifier_p
|
||||||
|
|
||||||
def gen_basic(cls, token, val, readtext, writetext):
|
def gen_basic(cls, token, val, readtext, writetext):
|
||||||
"generate a basic tag or attribute"
|
"""Generate a basic tag or attribute. This has got
|
||||||
|
to be pretty generic so we can invoke it from the complex
|
||||||
|
types such as Class and List"""
|
||||||
name = cls.mixed_case(token)
|
name = cls.mixed_case(token)
|
||||||
token_type = val[0]
|
token_type = val[0]
|
||||||
req = val[1]
|
req = val[1]
|
||||||
@@ -198,25 +277,23 @@ class autoxml(type):
|
|||||||
try:
|
try:
|
||||||
value = autoxml.basic_cons_map[token_type](text)
|
value = autoxml.basic_cons_map[token_type](text)
|
||||||
except Error:
|
except Error:
|
||||||
return ['Type mismatch']
|
raise Error('Type mismatch')
|
||||||
setattr(self, name, value)
|
setattr(self, name, value)
|
||||||
else:
|
else:
|
||||||
if req == mandatory:
|
if req == mandatory:
|
||||||
return ['Mandatory argument not available']
|
raise Error('Mandatory argument not available')
|
||||||
else:
|
else:
|
||||||
setattr(self, name, None)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def encode(self, xml):
|
def encode(self, xml, value):
|
||||||
node = xml.newNode(cls.tag)
|
node = xml.newNode(cls.tag)
|
||||||
if hasattr(self, name):
|
if hasattr(self, name):
|
||||||
writetext(xml, node, token, str(getattr(self, name)))
|
writetext(xml, node, token, str(value))
|
||||||
else:
|
else:
|
||||||
if req == mandatory:
|
if req == mandatory:
|
||||||
return ['Mandatory argument not available']
|
raise Error('Mandatory argument not available')
|
||||||
|
|
||||||
def format(self):
|
def format(self):
|
||||||
#print 'format:', name
|
|
||||||
if hasattr(self, name):
|
if hasattr(self, name):
|
||||||
return '%s: %s\n' % (token, str(getattr(self, name)))
|
return '%s: %s\n' % (token, str(getattr(self, name)))
|
||||||
else:
|
else:
|
||||||
@@ -226,69 +303,63 @@ class autoxml(type):
|
|||||||
|
|
||||||
return initialize, decode, encode, format
|
return initialize, decode, encode, format
|
||||||
|
|
||||||
def gen_basic_attr(cls, attr, val):
|
def gen_basic_attr(cls, attr, spec):
|
||||||
"""generate an attribute with a basic datatype"""
|
"""generate an attribute with a basic datatype"""
|
||||||
def readtext(node, attr):
|
def readtext(node, attr):
|
||||||
return getNodeAttribute(node, attr)
|
return getNodeAttribute(node, attr)
|
||||||
def writetext(xml, node, attr, value):
|
def writetext(xml, node, attr, value):
|
||||||
node.setAttribute(attr, value)
|
node.setAttribute(attr, value)
|
||||||
return autoxml.gen_basic(cls, attr, val, readtext, writetext)
|
return autoxml.gen_basic(cls, attr, spec, readtext, writetext)
|
||||||
|
|
||||||
def gen_basic_tag(cls, tag, val):
|
def gen_basic_tag(cls, tag, spec):
|
||||||
"""generate a tag with a basic datatype"""
|
"""generate a tag with a basic datatype"""
|
||||||
def readtext(node, tag):
|
def readtext(node, tag):
|
||||||
return getNodeText(getNode(node, tag))
|
return getNodeText(getNode(node, tag))
|
||||||
def writetext(xml, node, tag, value):
|
def writetext(xml, node, tag, value):
|
||||||
xml.addTextNodeUnder(node, tag, value)
|
xml.addTextNodeUnder(node, tag, value)
|
||||||
return autoxml.gen_basic(cls, tag, val, readtext, writetext)
|
return autoxml.gen_basic(cls, tag, spec, readtext, writetext)
|
||||||
|
|
||||||
def gen_class_tag(cls, tag, val):
|
def gen_class_tag(cls, tag, val):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def gen_list_tag(cls, tag, val):
|
def gen_list_tag(cls, tag, val):
|
||||||
name = cls.mixed_case(token)
|
name = cls.mixed_case(tag)
|
||||||
token_type = val[0]
|
tag_type = val[0]
|
||||||
req = val[1]
|
req = val[1]
|
||||||
|
|
||||||
if len(val)>=3:
|
if len(val)>=3:
|
||||||
path = val[2]
|
path = val[2] # an alternative path specified
|
||||||
else:
|
else:
|
||||||
path = tag
|
path = tag # otherwise it's the same name as
|
||||||
if len(token_type!=1):
|
# the tag
|
||||||
raise Error('List type must contain one element')
|
if len(tag_type) != 1:
|
||||||
|
raise Error('List type must contain only one element')
|
||||||
x = autoxml.gen_tag_aux(cls, tag, tag_type, val)
|
x = autoxml.gen_tag_aux(cls, tag, tag_type[0], val)
|
||||||
(x_init, x_decoder, x_encoder, x_formatter) = x
|
(init_item, decode_item, encode_item, format_item) = x
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
varname = cls.mixed_case(name)
|
setattr(self, name, [])
|
||||||
setattr(self, varname, [])
|
|
||||||
|
|
||||||
def decode(self, node):
|
def decode(self, node):
|
||||||
nodes = getAllNodes(node)
|
l = []
|
||||||
if len(nodes) is 0 and req is mandatory:
|
self.nodes = getAllNodes(node, path)
|
||||||
pass
|
print 'F U', self.nodes
|
||||||
#FIXME: add error here
|
if len(self.nodes) is 0 and req is mandatory:
|
||||||
for node in nodes:
|
raise Error('Mandatory list empty')
|
||||||
x_decoder(self, node)
|
for node in self.nodes:
|
||||||
pass
|
l.append(decode_item(self, node))
|
||||||
|
return l
|
||||||
|
|
||||||
def encode(self, xml):
|
def encode(self, xml, value):
|
||||||
node = xml.newNode(cls.tag)
|
pass
|
||||||
if hasattr(self, name):
|
|
||||||
writetext(xml, node, token, str(getattr(self, name)))
|
|
||||||
else:
|
|
||||||
if req == mandatory:
|
|
||||||
return ['Mandatory argument not available']
|
|
||||||
|
|
||||||
def format(self):
|
def format(self):
|
||||||
#print 'format:', name
|
#print 'format:', name
|
||||||
if hasattr(self, name):
|
s = ''
|
||||||
return '%s: %s\n' % (token, str(getattr(self, name)))
|
l = getattr(self, name)
|
||||||
else:
|
for ix in range(len(l)):
|
||||||
if req == mandatory:
|
s += str(ix) + format_item(l[ix])
|
||||||
raise Error('Mandatory variable %s not available' % name)
|
return s
|
||||||
return ""
|
|
||||||
|
|
||||||
return (init, decode, encode, format)
|
return (init, decode, encode, format)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user