#! /usr/bin/python -tt
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2005 Duke University
import types
import sys
from constants import *
from Errors import CompsException
#FIXME - compsexception isn't caught ANYWHERE so it's pointless to raise it
# switch all compsexceptions to grouperrors after api break
import fnmatch
import re
from yum.i18n import to_unicode
from misc import get_my_lang_code
from yum.misc import cElementTree_iterparse as iterparse
lang_attr = '{http://www.w3.org/XML/1998/namespace}lang'
def parse_boolean(strng):
return BOOLEAN_STATES.get(strng.lower(), False)
def parse_number(strng):
return int(strng)
class CompsObj(object):
""" Group/Category helper object. """
# Could be the same as ui_name?
def __str__(self):
""" Return the "name" of the object for the C locale. """
return self.name
@property
def ui_name(self):
""" Return the "name" of the object for the current locale. """
return self.nameByLang(get_my_lang_code())
@property
def ui_description(self):
""" Return the "description" of the object for the current locale. """
return self.descriptionByLang(get_my_lang_code())
def __cmp__(self, other):
if other is None:
return 1
if self.display_order > other.display_order:
return 1
if self.display_order < other.display_order:
return -1
return cmp(self.ui_name, other.ui_name)
def _expand_languages(self, lang):
import gettext
languages = [lang]
if 'C' not in languages:
languages.append('C')
# now normalize and expand the languages
nelangs = []
for lang in languages:
for nelang in gettext._expand_lang(lang):
if nelang not in nelangs:
nelangs.append(nelang)
return nelangs
def nameByLang(self, lang):
for langcode in self._expand_languages(lang):
if langcode in self.translated_name:
return to_unicode(self.translated_name[langcode])
return to_unicode(self.name)
def descriptionByLang(self, lang):
for langcode in self._expand_languages(lang):
if langcode in self.translated_description:
return to_unicode(self.translated_description[langcode])
return to_unicode(self.description)
class Group(CompsObj):
""" Group object parsed from group data in each repo. and merged. """
def __init__(self, elem=None):
self.user_visible = True
self.default = False
self.selected = False
self.name = ""
self.description = ""
self.translated_name = {}
self.translated_description = {}
self.mandatory_packages = {}
self.optional_packages = {}
self.default_packages = {}
self.conditional_packages = {}
self.langonly = None ## what the hell is this?
self.groupid = None
self.display_order = 1024
self.installed = False
self.toremove = False
if elem:
self.parse(elem)
def _packageiter(self):
# Gah, FIXME: real iterator/class
lst = self.mandatory_packages.keys() + \
self.optional_packages.keys() + \
self.default_packages.keys() + \
self.conditional_packages.keys()
return lst
packages = property(_packageiter)
def parse(self, elem):
for child in elem:
if child.tag == 'id':
myid = child.text
if self.groupid is not None:
raise CompsException
self.groupid = myid
elif child.tag == 'name':
text = child.text
if text:
text = text.encode('utf8')
lang = child.attrib.get(lang_attr)
if lang:
self.translated_name[lang] = text
else:
self.name = text
elif child.tag == 'description':
text = child.text
if text:
text = text.encode('utf8')
lang = child.attrib.get(lang_attr)
if lang:
self.translated_description[lang] = text
else:
if text:
self.description = text
elif child.tag == 'uservisible':
self.user_visible = parse_boolean(child.text)
elif child.tag == 'display_order':
self.display_order = parse_number(child.text)
elif child.tag == 'default':
self.default = parse_boolean(child.text)
elif child.tag in ['langonly', 'lang_only']:
text = child.text
if self.langonly is not None:
raise CompsException
self.langonly = text
elif child.tag == 'packagelist':
self.parse_package_list(child)
def parse_package_list(self, packagelist_elem):
for child in packagelist_elem:
if child.tag == 'packagereq':
genre = child.attrib.get('type')
if not genre:
genre = u'mandatory'
if genre not in ('mandatory', 'default', 'optional', 'conditional'):
# just ignore bad package lines
continue
package = child.text
if genre == 'mandatory':
self.mandatory_packages[package] = 1
elif genre == 'default':
self.default_packages[package] = 1
elif genre == 'optional':
self.optional_packages[package] = 1
elif genre == 'conditional':
self.conditional_packages[package] = child.attrib.get('requires')
def add(self, obj):
"""Add another group object to this object"""
# we only need package lists and any translation that we don't already
# have
for pkg in obj.mandatory_packages:
self.mandatory_packages[pkg] = 1
for pkg in obj.default_packages:
self.default_packages[pkg] = 1
for pkg in obj.optional_packages:
self.optional_packages[pkg] = 1
for pkg in obj.conditional_packages:
self.conditional_packages[pkg] = obj.conditional_packages[pkg]
# Handle cases where a comps.xml without name & decription tags
# has been setup first, so the name & decription for this object is blank.
if self.name == '' and obj.name != '':
self.name = obj.name
if self.description == '' and obj.description != '':
self.description = obj.description
# name and description translations
for lang in obj.translated_name:
if lang not in self.translated_name:
self.translated_name[lang] = obj.translated_name[lang]
for lang in obj.translated_description:
if lang not in self.translated_description:
self.translated_description[lang] = obj.translated_description[lang]
def xml(self):
"""write out an xml stanza for the group object"""
msg ="""