Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

beebox / crossover   deb

Repository URL to install this package:

Version: 18.5.0-1 

/ opt / cxoffice / lib / python / cxdiag.py

# (c) Copyright 2012. CodeWeavers, Inc.

"""Provides efficient access to the cxdiag diagnostics."""

import os.path
import time
import re

import cxconfig
import cxlog
import cxutils
import distversion

# for localization
from cxutils import cxgettext as _

import bottlequery
import cxproduct


class CXDiag(object):
    """Stores the cxdiag warnings and properties for the given library path
    setting.

    Once a CXDiag object is created it is never updated. So users should not
    keep references to them but instead systematically call cxdiag.get().

    The warnings are stored in the warnings dictionary in the form of
      (level, title, description) tuples, already localized.
    The properties are stored in the properties dictionary.
    """

    MISSING_RE = re.compile('^Missing 32bit (?P<library>.+) library$')

    def __init__(self, libpath):
        # Set up the library path so cxdiag takes into account the builtin
        # libraries. Note that it is configurable per bottle.
        self.libpath = libpath
        self.warnings = {}
        self.properties = {}

        if not distversion.IS_MACOSX:
            env = os.environ.copy()
            if libpath:
                # Re-run cxdiag with the new library path.
                ldpath_envname = "LD_LIBRARY_PATH"
                if ldpath_envname not in env:
                    env[ldpath_envname] = libpath
                else:
                    env[ldpath_envname] = ':'.join((libpath, env[ldpath_envname]))
                cxlog.log("running cxdiag with %s=%s" % (ldpath_envname, libpath))

            cxdiag = os.path.join(cxutils.CX_ROOT, "bin", "cxdiag")
            retcode, out, _err = cxutils.run((cxdiag, ), env=env,
                                             stdout=cxutils.GRAB)
            if retcode == 0:
                config = cxconfig.Raw()
                config.read_string(out)
                for name, section in config.iteritems():
                    name = name.lower()
                    if name == 'properties':
                        for prop, value in section.iteritems():
                            self.properties[prop.lower()] = value
                    else:
                        match = self.MISSING_RE.match(section['Title'])
                        if match:
                            # Reformat the message so it can be translated
                            title = _('Missing 32bit %s library') % match.group('library')
                        else:
                            title = cxutils.cxgettext(section['Title'])
                        self.warnings[name] = (section['Level'], title, cxutils.cxgettext(section['Description']))
            elif not os.access(cxdiag, os.R_OK | os.X_OK):
                # Consider that cxdiag has been disabled
                cxlog.log("cxdiag is missing / not executable")
            elif retcode == -1:
                cxlog.warn("could not run cxdiag")
                self.warnings['missinglibc'] = \
                    ('Require',
                     _('Missing 32bit C library'),
                     _('Without this library Windows applications cannot run.'))
            else:
                cxlog.warn("cxdiag failed (%d)" % retcode)
                self.warnings['brokencxdiag'] = \
                    ('Require',
                     _('Cxdiag failed'),
                     _('An error (%d) prevented cxdiag from running successfully. The same error is likely to cause some Windows applications to crash.') % retcode)

        self.timestamp = time.time()



#####
#
# The cxdiag cache
#
#####

_CACHE = {}

def get(bottlename):
    """Return a CXDiag object with the results for the specified bottle.

    The results are cached so we don't run cxdiag a dozen times if we have
    half a dozen bottles. However they are also expired after a while so we
    detect configuration changes such as the addition or removal of packages.
    """
    # The cxdiag result depends on the configuration settings, specifically
    # on the LibPath setting.
    if bottlename:
        config = bottlequery.get_config(bottlename)
    else:
        config = cxproduct.get_config()
    libpath = config['Wine'].get('LibPath', None)
    if libpath is not None:
        libpath = bottlequery.expand_unix_string(bottlename, libpath)
    else:
        libpath = os.path.join(cxutils.CX_ROOT, "lib")

    cxdiag = _CACHE.get(libpath, None)
    if cxdiag and time.time()-cxdiag.timestamp > 10:
        # Remove old results in case the user added / removed packages in the
        # meantime
        cxlog.log("cxdiag: pruning obsolete results")
        cxdiag = None
    if cxdiag is None:
        cxdiag = _CACHE[libpath] = CXDiag(libpath)
    return cxdiag