api_common.py revision 3193
1638N/A#!/usr/bin/python
1638N/A#
1638N/A# CDDL HEADER START
1638N/A#
1638N/A# The contents of this file are subject to the terms of the
1638N/A# Common Development and Distribution License (the "License").
1638N/A# You may not use this file except in compliance with the License.
1638N/A#
1638N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1638N/A# or http://www.opensolaris.org/os/licensing.
1638N/A# See the License for the specific language governing permissions
1638N/A# and limitations under the License.
1638N/A#
1638N/A# When distributing Covered Code, include this CDDL HEADER in each
1638N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1638N/A# If applicable, add the following below this CDDL HEADER, with the
1638N/A# fields enclosed by brackets "[]" replaced with your own identifying
1638N/A# information: Portions Copyright [yyyy] [name of copyright owner]
1638N/A#
1638N/A# CDDL HEADER END
1638N/A#
1638N/A
1638N/A#
3158N/A# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
1638N/A#
1638N/A# Visible changes to classes here require an update to
1638N/A# doc/client_api_versions.txt and/or doc/server_api_versions.txt.
1638N/A
1638N/A"""Contains API functions and classes common to both pkg.client.api and
1638N/Apkg.server.api."""
1638N/A
2616N/Aimport pkg.client.pkgdefs as pkgdefs
1638N/Aimport pkg.fmri as fmri
1638N/Aimport pkg.misc as misc
1638N/A
1638N/Aclass LicenseInfo(object):
1638N/A """A class representing the license information a package
1638N/A provides. Not intended for instantiation by API consumers."""
1638N/A
2313N/A def __init__(self, pfmri, act, img=None, text=None, alt_pub=None):
1638N/A self.__action = act
2313N/A self.__alt_pub = alt_pub
1638N/A self.__fmri = pfmri
1638N/A self.__img = img
1638N/A self.__text = text
1638N/A
1638N/A def __str__(self):
1638N/A return self.get_text()
1638N/A
1638N/A def get_text(self):
1638N/A """Retrieves and returns the payload of the license (which
1638N/A should be text). This may require remote retrieval of
1638N/A resources and so this could raise a TransportError or other
1638N/A ApiException."""
1638N/A
1638N/A if not self.__img:
1638N/A return self.__text
2313N/A return self.__action.get_text(self.__img, self.__fmri,
2313N/A alt_pub=self.__alt_pub)
1638N/A
1638N/A @property
1638N/A def fmri(self):
1638N/A """The FMRI of the package this license is for."""
1638N/A
1638N/A return self.__fmri
1638N/A
1638N/A @property
1638N/A def license(self):
1638N/A """The keyword identifying this license within its related
1638N/A package."""
1638N/A
1638N/A return self.__action.attrs["license"]
1638N/A
1638N/A @property
1638N/A def must_accept(self):
1638N/A """A boolean value indicating whether the license requires
1638N/A acceptance."""
1638N/A
1638N/A return self.__action.must_accept
1638N/A
1638N/A @property
1638N/A def must_display(self):
1638N/A """A boolean value indicating whether the license must be
1638N/A displayed during install or update operations."""
1638N/A
1638N/A return self.__action.must_display
1638N/A
1638N/A
1638N/Aclass PackageCategory(object):
1638N/A """Represents the scheme and category of an info.classification entry
1638N/A for a package."""
1638N/A
1638N/A scheme = None
1638N/A category = None
1638N/A
1638N/A def __init__(self, scheme, category):
1638N/A self.scheme = scheme
1638N/A self.category = category
1638N/A
1638N/A def __str__(self, verbose=False):
1638N/A if verbose:
3158N/A return "{0} ({1})".format(self.category, self.scheme)
1638N/A else:
3158N/A return "{0}".format(self.category)
1638N/A
1638N/A
1638N/Aclass PackageInfo(object):
1638N/A """A class capturing the information about packages that a client
1638N/A could need. The fmri is guaranteed to be set. All other values may
1638N/A be None, depending on how the PackageInfo instance was created."""
1638N/A
1970N/A # Possible package states; these constants should match the values used
1970N/A # by the Image class. Constants with negative values are not currently
1970N/A # available.
1638N/A INCORPORATED = -2
1638N/A EXCLUDES = -3
2616N/A KNOWN = pkgdefs.PKG_STATE_KNOWN
2616N/A INSTALLED = pkgdefs.PKG_STATE_INSTALLED
2616N/A UPGRADABLE = pkgdefs.PKG_STATE_UPGRADABLE
2616N/A OBSOLETE = pkgdefs.PKG_STATE_OBSOLETE
2616N/A RENAMED = pkgdefs.PKG_STATE_RENAMED
2616N/A UNSUPPORTED = pkgdefs.PKG_STATE_UNSUPPORTED
2616N/A FROZEN = pkgdefs.PKG_STATE_FROZEN
1638N/A
2493N/A __NUM_PROPS = 13
1970N/A IDENTITY, SUMMARY, CATEGORIES, STATE, SIZE, LICENSES, LINKS, \
2493N/A HARDLINKS, FILES, DIRS, DEPENDENCIES, DESCRIPTION, \
2493N/A ALL_ATTRIBUTES = range(__NUM_PROPS)
1638N/A ALL_OPTIONS = frozenset(range(__NUM_PROPS))
1638N/A ACTION_OPTIONS = frozenset([LINKS, HARDLINKS, FILES, DIRS,
1638N/A DEPENDENCIES])
1638N/A
1638N/A def __init__(self, pfmri, pkg_stem=None, summary=None,
1638N/A category_info_list=None, states=None, publisher=None,
1970N/A version=None, build_release=None, branch=None, packaging_date=None,
2910N/A size=None, csize=None, licenses=None, links=None, hardlinks=None,
2910N/A files=None, dirs=None, dependencies=None, description=None,
3193N/A attrs=None, last_update=None, last_install=None):
1638N/A self.pkg_stem = pkg_stem
1970N/A
1638N/A self.summary = summary
1638N/A if category_info_list is None:
1638N/A category_info_list = []
1638N/A self.category_info_list = category_info_list
1638N/A self.states = states
1638N/A self.publisher = publisher
1638N/A self.version = version
1638N/A self.build_release = build_release
1638N/A self.branch = branch
1638N/A self.packaging_date = packaging_date
1638N/A self.size = size
2910N/A self.csize = csize
1638N/A self.fmri = pfmri
1638N/A self.licenses = licenses
1638N/A self.links = links
1638N/A self.hardlinks = hardlinks
1638N/A self.files = files
1638N/A self.dirs = dirs
1638N/A self.dependencies = dependencies
1638N/A self.description = description
2493N/A self.attrs = attrs or {}
3193N/A self.last_update = last_update
3193N/A self.last_install = last_install
1638N/A
1638N/A def __str__(self):
2500N/A return str(self.fmri)
1638N/A
1638N/A @staticmethod
1638N/A def build_from_fmri(f):
1638N/A if not f:
1638N/A return f
1638N/A pub, name, version = f.tuple()
1638N/A pub = fmri.strip_pub_pfx(pub)
1638N/A return PackageInfo(pkg_stem=name, publisher=pub,
1638N/A version=version.release,
1638N/A build_release=version.build_release, branch=version.branch,
1638N/A packaging_date=version.get_timestamp().strftime("%c"),
2446N/A pfmri=f)
1638N/A
2493N/A def get_attr_values(self, name, modifiers=()):
2493N/A """Returns a list of the values of the package attribute 'name'.
2493N/A
2493N/A The 'modifiers' parameter, if present, is a dict containing
2493N/A key/value pairs, all of which must be present on an action in
2493N/A order for the values to be returned.
2493N/A
2493N/A Returns an empty list if there are no values.
2493N/A """
2493N/A
2493N/A # XXX should the modifiers parameter be allowed to be a subset
2493N/A # of an action's modifiers?
2493N/A if isinstance(modifiers, dict):
2493N/A modifiers = tuple(
2493N/A (k, isinstance(modifiers[k], basestring) and
2493N/A tuple([sorted(modifiers[k])]) or
2493N/A tuple(sorted(modifiers[k])))
2493N/A for k in sorted(modifiers.iterkeys())
2493N/A )
2493N/A return self.attrs.get(name, {modifiers: []}).get(
2493N/A modifiers, [])
2493N/A
1638N/A
1638N/Adef _get_pkg_cat_data(cat, info_needed, actions=None,
1638N/A excludes=misc.EmptyI, pfmri=None):
1638N/A """This is a private method and not intended for
1638N/A external consumers."""
1638N/A
1638N/A # XXX this doesn't handle locale.
1638N/A get_summ = summ = desc = cat_info = deps = None
1638N/A cat_data = []
1638N/A get_summ = PackageInfo.SUMMARY in info_needed
1638N/A if PackageInfo.CATEGORIES in info_needed:
1638N/A cat_info = []
1638N/A if PackageInfo.DEPENDENCIES in info_needed:
1638N/A cat_data.append(cat.DEPENDENCY)
1638N/A deps = []
1638N/A
1638N/A if deps is None or len(info_needed) != 1:
1638N/A # Anything other than dependency data
1638N/A # requires summary data.
1638N/A cat_data.append(cat.SUMMARY)
1638N/A
1638N/A if actions is None:
1638N/A actions = cat.get_entry_actions(pfmri, cat_data,
1638N/A excludes=excludes)
1638N/A
1638N/A for a in actions:
1638N/A if deps is not None and a.name == "depend":
1638N/A deps.append(a.attrs.get(a.key_attr))
1638N/A continue
1638N/A elif a.name != "set":
1638N/A continue
1638N/A
1638N/A attr_name = a.attrs["name"]
1638N/A if attr_name == "pkg.summary":
1638N/A if get_summ:
1638N/A summ = a.attrs["value"]
1735N/A elif attr_name == "description":
1735N/A if get_summ and summ is None:
1735N/A # Historical summary field.
1735N/A summ = a.attrs["value"]
1735N/A elif attr_name == "pkg.description":
1638N/A desc = a.attrs["value"]
1638N/A elif cat_info != None and a.has_category_info():
1638N/A cat_info.extend(a.parse_category_info())
1638N/A
1638N/A if get_summ and summ is None:
1638N/A if desc is None:
1638N/A summ = ""
1638N/A else:
1638N/A summ = desc
1638N/A if not PackageInfo.DESCRIPTION in info_needed:
1638N/A desc = None
1638N/A return summ, desc, cat_info, deps