ÿØÿà JFIF    ÿþ >CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality ÿÛ C     p!ranha?
Server IP : 172.67.171.101  /  Your IP : 216.73.216.123
Web Server : Apache
System : Linux server1.morocco-tours.com 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64
User : zagoradraa ( 1005)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /lib/python2.7/site-packages/yum/

Upload File :
Curr3nt_D!r [ Writeable ] D0cum3nt_r0Ot [ Writeable ]

 
Command :
Current File : /lib/python2.7/site-packages/yum/depsolve.py
#!/usr/bin/python -t
# 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 

"""
Dependency resolution module for yum.
"""

import os.path
import types
import logging

import rpmUtils.transaction
import rpmUtils.miscutils
from rpmUtils.arch import archDifference, canCoinstall
import misc
from misc import unique, version_tuple_to_string
from transactioninfo import TransactionMember
import rpm

from packageSack import ListPackageSack
from packages import PackageEVR
from constants import *
import logginglevels
import Errors
import warnings
warnings.simplefilter("ignore", Errors.YumFutureDeprecationWarning)

from weakref import proxy as weakref

from yum import _, _rpm_ver_atleast

try:
    assert max(2, 4) == 4
except:
    # Python-2.4.x doesn't have min/max ... *sigh*
    def min(x, *args): 
        for y in args:
            if x > y: x = y
        return x
    def max(x, *args):
        for y in args:
            if x < y: x = y
        return x
flags = {"GT": rpm.RPMSENSE_GREATER,
         "GE": rpm.RPMSENSE_EQUAL | rpm.RPMSENSE_GREATER,
         "LT": rpm.RPMSENSE_LESS,
         "LE": rpm.RPMSENSE_LESS | rpm.RPMSENSE_EQUAL,
         "EQ": rpm.RPMSENSE_EQUAL,
         None: 0 }
_rflags = {}
for f in flags:
    _rflags[flags[f]] = f


class _wrap_ayum_getPkgSack:
    """ This is a wrapper for calling YumBase.pkgSack because
        otherwise we take a real reference through the bound method and
        that is d00m (this applies to YumBase and TransactionInfo, hence why
        we have a separate class). """
    def __init__(self, ayum):
        self.ayum = weakref(ayum)
    def __call__(self):
        return self.ayum.pkgSack

class _wrap_ayum_install:
    """ This is a wrapper for calling YumBase.install because
        otherwise we take a real reference through the bound method and
        that is d00m (this applies to YumBase and TransactionInfo, hence why
        we have a separate class). """
    def __init__(self, ayum):
        self.ayum = weakref(ayum)
    def __call__(self, *args, **kwargs):
        return self.ayum.install(*args, **kwargs)
class _wrap_ayum_remove:
    """ This is a wrapper for calling YumBase.remove because
        otherwise we take a real reference through the bound method and
        that is d00m (this applies to YumBase and TransactionInfo, hence why
        we have a separate class). """
    def __init__(self, ayum):
        self.ayum = weakref(ayum)
    def __call__(self, *args, **kwargs):
        return self.ayum.remove(*args, **kwargs)
class _wrap_ayum_update:
    """ This is a wrapper for calling YumBase.update because
        otherwise we take a real reference through the bound method and
        that is d00m (this applies to YumBase and TransactionInfo, hence why
        we have a separate class). """
    def __init__(self, ayum):
        self.ayum = weakref(ayum)
    def __call__(self, *args, **kwargs):
        return self.ayum.update(*args, **kwargs)

class Depsolve(object):
    """A class for resolving dependencies."""

    def __init__(self):
        self._ts = None
        self._tsInfo = None
        self.dsCallback = None
        # Callback-style switch, default to legacy (hdr, file) mode
        self.use_txmbr_in_callback = False
        self.logger = logging.getLogger("yum.Depsolve")
        self.verbose_logger = logging.getLogger("yum.verbose.Depsolve")

        self.path = []
        self.loops = []

        self.installedFileRequires = None
        self.installedUnresolvedFileRequires = None
        self._missing_requires = False

    def doTsSetup(self):
        """Sets up the transaction set before it is used."""

        warnings.warn(_('doTsSetup() will go away in a future version of Yum.\n'),
                Errors.YumFutureDeprecationWarning, stacklevel=2)
        return self._getTs()
        
    def _getTs(self, remove_only=False):
        """setup all the transaction set storage items we'll need
           This can't happen in __init__ b/c we don't know our installroot
           yet"""
        
        if self._tsInfo != None and self._ts != None:
            if not remove_only and self._tsInfo.pkgSack is None:
                pkgSackCtor = _wrap_ayum_getPkgSack(self)
                self._tsInfo.setDatabases(self.rpmdb, None, pkgSackCtor)
            return
            
        if not self.conf.installroot:
            raise Errors.YumBaseError, _('Setting up TransactionSets before config class is up')
        
        self._getTsInfo(remove_only)
        self.initActionTs()
    
    def _getTsInfo(self, remove_only=False):
        """ remove_only param. says if we are going to do _only_ remove(s) in
            the transaction. If so we don't need to setup the remote repos. """
        if self._tsInfo is None:
            self._tsInfo = self._transactionDataFactory()
            if remove_only:
                pkgSack = None
                pkgSackCtor = None
            else:
                # Don't instant setup, or things like localinstall are screwed.
                pkgSack = None
                pkgSackCtor = _wrap_ayum_getPkgSack(self)
            self._tsInfo.setDatabases(self.rpmdb, pkgSack, pkgSackCtor)
            self._tsInfo.installonlypkgs = self.conf.installonlypkgs # this kinda sucks
            # this REALLY sucks, sadly (needed for group conditionals)
            self._tsInfo.install_method = _wrap_ayum_install(self)
            self._tsInfo.update_method = _wrap_ayum_update(self)
            self._tsInfo.remove_method = _wrap_ayum_remove(self)
        return self._tsInfo

    def _setTsInfo(self, value):
        self._tsInfo = value

    def _delTsInfo(self):
        self._tsInfo = None
        
    def _getActionTs(self):
        if not self._ts:
            self.initActionTs()
        return self._ts
        

    def initActionTs(self):
        """Set up the transaction set that will be used for all the work."""
        
        # LOL, override rpm transaction macro.
        # Must be done before rpmtsCreate()
        if self.conf.override_install_langs:
            old_install_langs = rpm.expandMacro("%_install_langs")
            rpm.expandMacro("%define _install_langs " +
                            self.conf.override_install_langs)

        self._ts = rpmUtils.transaction.TransactionWrapper(self.conf.installroot)
        ts_flags_to_rpm = { 'noscripts': rpm.RPMTRANS_FLAG_NOSCRIPTS,
                            'notriggers': rpm.RPMTRANS_FLAG_NOTRIGGERS,
                            'nodocs': rpm.RPMTRANS_FLAG_NODOCS,
                            'test': rpm.RPMTRANS_FLAG_TEST,
                            'justdb': rpm.RPMTRANS_FLAG_JUSTDB,
                            'repackage': rpm.RPMTRANS_FLAG_REPACKAGE}
        # This is only in newer rpm.org releases
        if hasattr(rpm, 'RPMTRANS_FLAG_NOCONTEXTS'):
            ts_flags_to_rpm['nocontexts'] = rpm.RPMTRANS_FLAG_NOCONTEXTS
        
        self._ts.setFlags(0) # reset everything.
        
        for flag in self.conf.tsflags:
            if flag in ts_flags_to_rpm:
                self._ts.addTsFlag(ts_flags_to_rpm[flag])
            else:
                self.logger.critical(_('Invalid tsflag in config file: %s'), flag)

        if not self.conf.diskspacecheck:
            self._add_prob_flags(rpm.RPMPROB_FILTER_DISKSPACE,
                                 rpm.RPMPROB_FILTER_DISKNODES)

        probfilter = 0
        for flag in self.tsInfo.probFilterFlags:
            probfilter |= flag
        self._ts.setProbFilter(probfilter)

    def whatProvides(self, name, flags, version):
        """Search the packageSacks for what provides the specified
        feature or file.
      
        :param name: a string specifying the file or feature to search
           for
        :param flags: flags related to the search
        :param version: the version to search for
        :return: a :class:`ListPackagaSack` containing the packages
           that match the arguments, and may be empty
        """
        self.verbose_logger.log(logginglevels.DEBUG_1, _('Searching pkgSack for dep: %s'),
            name)
        defSack = ListPackageSack(self.pkgSack.searchProvides((name, flags, version)))
        return defSack
        
    def allowedMultipleInstalls(self, po):
        """Return whether the given package object can be installed
        multiple times with different versions.  For example, this
        would be true of kernels and kernel modules.

        :param po: the package object that this function will
           determine whether can be install multiple times
        :return: a boolean specifying whether *po* can be installed
           multiple times
        """
        iopkgs = set(self.conf.installonlypkgs)
        if po.name in iopkgs:
            return True
        
        for prov in po.provides_names:
            if prov in iopkgs:
                return True
        
        return False

    def populateTs(self, test=0, keepold=1):
        """Populate the transaction set.

        :param test: unused
        :param keepold: whether to keep old packages
        """
        if self.dsCallback: self.dsCallback.transactionPopulation()
        ts_elem = {}
        
        if self.ts.ts is None:
            self.initActionTs()
            
        if keepold:
            for te in self.ts:
                epoch = te.E()
                if epoch is None:
                    epoch = '0'
                pkginfo = (te.N(), te.A(), epoch, te.V(), te.R())
                if te.Type() == 1:
                    mode = 'i'
                elif te.Type() == 2:
                    mode = 'e'
                
                ts_elem[(pkginfo, mode)] = 1
                
        for txmbr in self.tsInfo.getMembers():
            self.verbose_logger.log(logginglevels.DEBUG_3, _('Member: %s'), txmbr)
            if txmbr.ts_state in ['u', 'i']:
                if (txmbr.pkgtup, 'i') in ts_elem:
                    continue
                rpmfile = txmbr.po.localPkg()
                if os.path.exists(rpmfile):
                    hdr = txmbr.po.returnHeaderFromPackage()
                else:
                    self.downloadHeader(txmbr.po)
                    hdr = txmbr.po.returnLocalHeader()

                if txmbr.ts_state == 'u':
                    if self.allowedMultipleInstalls(txmbr.po):
                        self.verbose_logger.log(logginglevels.DEBUG_2,
                            _('%s converted to install'), txmbr.po)
                        txmbr.ts_state = 'i'
                        txmbr.output_state = TS_INSTALL

                # New-style callback with just txmbr instead of full headers?
                if self.use_txmbr_in_callback:
                    cbkey = txmbr
                else:
                    cbkey = (hdr, rpmfile)
                
                self.ts.addInstall(hdr, cbkey, txmbr.ts_state)
                self.verbose_logger.log(logginglevels.DEBUG_1,
                    _('Adding Package %s in mode %s'), txmbr.po, txmbr.ts_state)
                if self.dsCallback:
                    dscb_ts_state = txmbr.ts_state
                    if dscb_ts_state == 'u' and txmbr.downgrades:
                        dscb_ts_state = 'd'
                    self.dsCallback.pkgAdded(txmbr.pkgtup, dscb_ts_state)
            
            elif txmbr.ts_state in ['e']:
                if (txmbr.pkgtup, txmbr.ts_state) in ts_elem:
                    continue
                self.ts.addErase(txmbr.po.idx)
                if self.dsCallback:
                    if txmbr.downgraded_by:
                        continue
                    self.dsCallback.pkgAdded(txmbr.pkgtup, 'e')
                self.verbose_logger.log(logginglevels.DEBUG_1,
                    _('Removing Package %s'), txmbr.po)

    def _dscb_procReq(self, po, niceformatneed):
        """ Call the callback for processing requires, call the nicest one
            available. """
        if not self.dsCallback:
            return

        if hasattr(self.dsCallback, 'procReqPo'):
            self.dsCallback.procReqPo(po, niceformatneed)
        else:
            self.dsCallback.procReq(po.name, niceformatneed)

    def _processReq(self, po, requirement):
        """processes a Requires dep from the resolveDeps functions, returns a tuple
           of (CheckDeps, missingdep, conflicts, errors) the last item is an array
           of error messages"""
        
        errormsgs = []

        needname, flags, needversion = requirement
        niceformatneed = rpmUtils.miscutils.formatRequire(needname, needversion, flags)
        self.verbose_logger.log(logginglevels.DEBUG_1, _('%s requires: %s'), po, niceformatneed)
        self._dscb_procReq(po, niceformatneed)

        try:    
            if po.repo.id != "installed":
                CheckDeps, missingdep = self._requiringFromTransaction(po, requirement, errormsgs)
            else:
                CheckDeps, missingdep = self._requiringFromInstalled(po, requirement, errormsgs)
    
            # Check packages with problems
            if missingdep:
                self.po_with_problems.add((po,self._working_po,errormsgs[-1]))
            
    
        except Errors.DepError,e:
            # FIXME: This is a hack, it don't solve the problem
            # of tries to update to a package the have been removed from the
            # pkgSack because of dep problems.
            # The real solution is to remove the package from the updates, when
            # it is remove from the pkgSack
            self.po_with_problems.add((po,self._working_po,str(e)))
            CheckDeps = 1
            missingdep = 0

        return (CheckDeps, missingdep, errormsgs)

    @staticmethod
    def _prco_req_nfv2req(rn, rf, rv):
        return (rn, flags[rf], version_tuple_to_string(rv))

    def _prco_req2req(self, req):
        return self._prco_req_nfv2req(req[0], req[1], req[2])
            
    def _err_missing_requires(self, reqPo, reqTup):
        self._missing_requires = True
        if hasattr(self.dsCallback, 'format_missing_requires'):
            msg = self.dsCallback.format_missing_requires(reqPo, reqTup)
            if msg is not None: # PK
                return self.dsCallback.format_missing_requires(reqPo, reqTup)
        (needname, needflags, needversion) = reqTup
        ui_req = rpmUtils.miscutils.formatRequire(needname, needversion,
                                                  needflags)
        return _('%s requires %s') % (reqPo, ui_req)

    def _requiringFromInstalled(self, requiringPo, requirement, errorlist):
        """processes the dependency resolution for a dep where the requiring 
           package is installed"""

        checkdeps = 0
        missingdep = 0
        
        if self.tsInfo.getMembersWithState(requiringPo.pkgtup, TS_REMOVE_STATES):
            return checkdeps, missingdep

        name, arch, epoch, ver, rel = requiringPo.pkgtup

        needname, needflags, needversion = requirement
        niceformatneed = rpmUtils.miscutils.formatRequire(needname, needversion, needflags)


        # we must first find out why the requirement is no longer there
        # we must find out what provides/provided it from the rpmdb (if anything)
        # then check to see if that thing is being acted upon by the transaction set
        # if it is then we need to find out what is being done to it and act accordingly
        needmode = None # mode in the transaction of the needed pkg (if any)
        needpo = None
        providers = []
        
        if (needname, needflags, needversion) in self.cheaterlookup:
            self.verbose_logger.log(logginglevels.DEBUG_2, _('Needed Require has already been looked up, cheating'))
            cheater_po = self.cheaterlookup[(needname, needflags, needversion)]
            providers = [cheater_po]
        
        elif self.rpmdb.contains(name=needname):
            txmbrs = self.tsInfo.matchNaevr(name=needname)
            for txmbr in txmbrs:
                providers.append(txmbr.po)

        else:
            self.verbose_logger.log(logginglevels.DEBUG_2, _('Needed Require is not a package name. Looking up: %s'), niceformatneed)
            providers = self.rpmdb.getProvides(needname, needflags, needversion)

        for inst_po in providers:
            self._working_po = inst_po # store the last provider
            inst_str = '%s.%s %s:%s-%s' % inst_po.pkgtup
            (i_n, i_a, i_e, i_v, i_r) = inst_po.pkgtup
            self.verbose_logger.log(logginglevels.DEBUG_2,
                _('Potential Provider: %s'), inst_str)
            thismode = self.tsInfo.getMode(name=i_n, arch=i_a, 
                            epoch=i_e, ver=i_v, rel=i_r)

            if thismode is None and i_n in self.conf.exactarchlist:
                # check for mode by the same name+arch
                thismode = self.tsInfo.getMode(name=i_n, arch=i_a)
            
            if thismode is None and i_n not in self.conf.exactarchlist:
                # check for mode by just the name
                thismode = self.tsInfo.getMode(name=i_n)

            # if this package is being obsoleted, it's just like if it's
            # being upgraded as far as checking for other providers
            if thismode is None:
                if filter(lambda x: x.obsoleted_by,
                          self.tsInfo.matchNaevr(i_n, i_a, i_e, i_v, i_r)):
                    thismode = 'u'

            if thismode is not None:
                needmode = thismode

                self.cheaterlookup[(needname, needflags, needversion)] = inst_po
                self.verbose_logger.log(logginglevels.DEBUG_2, _('Mode is %s for provider of %s: %s'),
                    needmode, niceformatneed, inst_str)
                break
                    
        self.verbose_logger.log(logginglevels.DEBUG_2, _('Mode for pkg providing %s: %s'), 
            niceformatneed, needmode)

        if needmode in ['ud']: # the thing it needs is being updated or obsoleted away 
            # try to update the requiring package in hopes that all this problem goes away :(
            self.verbose_logger.log(logginglevels.DEBUG_2, _('Trying to update %s to resolve dep'), requiringPo)
            # if the required pkg was updated, not obsoleted, then try to
            # only update the requiring po
            origobs = self.conf.obsoletes
            self.conf.obsoletes = 0
            txmbrs = self.update(po=requiringPo, requiringPo=requiringPo)
            self.conf.obsoletes = origobs

            def _check_update_worked(txmbrs, obs=False):
                #  Old code assumed that if there was an update, we were good:
                #    if txmbrs: return True
                # ..however we have a problem when foo-1 and foo-2 both require
                # bar-1, and bar-2 is being installed. If the req. is identical
                # then we'll skip checking it in _checkInstall(), so we need to
                # check it here.
                for txmbr in txmbrs:
                    if obs or txmbr.name == requiringPo.name:
                        n,f,v = requirement
                        creq = (n, _rflags[f],
                                rpmUtils.miscutils.stringToVersion(v))
                        # If it's identical ... checkInstall will skip it.
                        if creq not in txmbr.po.requires:
                            return True
                return False

            if not _check_update_worked(txmbrs):
                txmbrs = self.update(po=requiringPo, requiringPo=requiringPo)
                if not _check_update_worked(txmbrs, obs=True):
                    msg = self._err_missing_requires(requiringPo, requirement)
                    self.verbose_logger.log(logginglevels.DEBUG_2, _('No update paths found for %s. Failure!'), requiringPo)
                    return self._requiringFromTransaction(requiringPo, requirement, errorlist)
            checkdeps = 1

        if needmode in ['od']: # the thing it needs is being updated or obsoleted away 
            # try to update the requiring package in hopes that all this problem goes away :(
            self.verbose_logger.log(logginglevels.DEBUG_2, _('Trying to update %s to resolve dep'), requiringPo)
            txmbrs = self.update(po=requiringPo, requiringPo=requiringPo)
            fixed = False
            if not txmbrs:
                msg = self._err_missing_requires(requiringPo, requirement)
                self.verbose_logger.log(logginglevels.DEBUG_2, _('No update paths found for %s. Failure due to requirement: %s!'), requiringPo, msg)
            else:
                req_lookup = (needname, needflags,
                              rpmUtils.miscutils.stringToVersion(needversion))

            for txmbr in txmbrs:
                #  This works for upgrades, and for obsoletes, on one side.
                # Also catches upgrades that don't work on the other.
                if txmbr.output_state in TS_INSTALL_STATES:
                    if txmbr.po.checkPrco('requires', req_lookup):
                        fixed = False
                        break
                    else:
                        fixed = True
            if txmbrs and not fixed:
                msg = self._err_missing_requires(requiringPo, requirement)
                self.verbose_logger.log(logginglevels.DEBUG_2, _("Update for %s. Doesn't fix requirement: %s!"), requiringPo, msg)

            if not fixed:
                return self._requiringFromTransaction(requiringPo, requirement, errorlist)
            checkdeps = 1
            
        if needmode in ['e']:
            self.verbose_logger.log(logginglevels.DEBUG_2, _('TSINFO: %s package requiring %s marked as erase'),
                requiringPo, needname)
            txmbrs = self.remove(po=requiringPo)
            for txmbr in txmbrs:
                txmbr.setAsDep(po=inst_po)
            checkdeps = 1
        
        if needmode in ['i', 'u']:
            newupdates = self.update(name=name, epoch=epoch, version=ver, release=rel,
                                     requiringPo=requiringPo)
            txmbrs = self.tsInfo.getMembersWithState(requiringPo.pkgtup, TS_REMOVE_STATES)
            if newupdates and txmbrs:
                if txmbrs[0].output_state == TS_OBSOLETED:
                    self.verbose_logger.log(logginglevels.DEBUG_2, _('TSINFO: Obsoleting %s with %s to resolve dep.'),
                                            requiringPo, txmbrs[0].obsoleted_by[0])
                else:
                    self.verbose_logger.log(logginglevels.DEBUG_2, _('TSINFO: Updating %s to resolve dep.'), requiringPo)
                    # If the requirement is still there, try and solve it again
                    # so we don't lose it
                    for pkg in txmbrs[0].updated_by:
                        if requirement in map(self._prco_req2req, pkg.returnPrco('requires')):
                            return True, missingdep + self._requiringFromTransaction(pkg, requirement, errorlist)[1]
                checkdeps = True
                return checkdeps, missingdep
            self.verbose_logger.log(logginglevels.DEBUG_2, _('Cannot find an update path for dep for: %s'), niceformatneed)
            return self._requiringFromTransaction(requiringPo, requirement, errorlist)
            

        if needmode is None:
            reqpkg = (name, ver, rel, None)
            if self.pkgSack is None:
                return self._requiringFromTransaction(requiringPo, requirement, errorlist)
            else:
                msg = self._err_missing_requires(requiringPo, requirement)
                self.verbose_logger.log(logginglevels.DEBUG_2, msg)
                checkdeps = 0
                missingdep = 1
                errorlist.append(msg)

        return checkdeps, missingdep
        
    def _quickWhatProvides(self, name, flags, version):
        if self._last_req is None:
            return False

        if flags == 0:
            flags = None
        if type(version) in (types.StringType, types.NoneType, types.UnicodeType):
            (r_e, r_v, r_r) = rpmUtils.miscutils.stringToVersion(version)
        elif type(version) in (types.TupleType, types.ListType): # would this ever be a ListType?
            (r_e, r_v, r_r) = version
        
        # Quick lookup, lots of reqs for one pkg:
        po = self._last_req
        if po.checkPrco('provides', (name, flags, (r_e, r_v, r_r))):
            self.verbose_logger.debug(_('Quick matched %s to require for %s'), po, name)
            return True
        return False
        
    def _requiringFromTransaction(self, requiringPo, requirement, errorlist):
        """processes the dependency resolution for a dep where requiring 
           package is in the transaction set"""
        
        (name, arch, epoch, version, release) = requiringPo.pkgtup
        (needname, needflags, needversion) = requirement
        checkdeps = 0
        missingdep = 0
        upgraded = {}

        #~ - if it's not available from some repository:
        #~     - mark as unresolveable.
        #
        #~ - if it's available from some repo:
        #~    - if there is an another version of the package currently installed then
        #        - if the other version is marked in the transaction set
        #           - if it's marked as erase
        #              - mark the dep as unresolveable
         
        #           - if it's marked as update or install
        #              - check if the version for this requirement:
        #                  - if it is higher 
        #                       - mark this version to be updated/installed
        #                       - remove the other version from the transaction set
        #                       - tell the transaction set to be rebuilt
        #                  - if it is lower
        #                       - mark the dep as unresolveable
        #                   - if they are the same
        #                       - be confused but continue

        if self._quickWhatProvides(needname, needflags, needversion):
            return checkdeps, missingdep

        provSack = self.whatProvides(needname, needflags, needversion)
        # get rid of things that are already in the rpmdb - b/c it's pointless to use them here

        for pkg in provSack.returnPackages():
            if self.rpmdb.contains(po=pkg): # is it already installed?
                self.verbose_logger.log(logginglevels.DEBUG_2, _('%s is in providing packages but it is already installed, removing.'), pkg)
                provSack.delPackage(pkg)
                continue

            # we need to check to see, if we have anything similar to it (name-wise)
            # installed or in the ts, and this isn't a package that allows multiple installs
            # then if it's newer, fine - continue on, if not, then we're unresolveable
            # cite it and exit

            tspkgs = []
            if not self.allowedMultipleInstalls(pkg):
                # from ts
                tspkgs = self.tsInfo.matchNaevr(name=pkg.name)
                for tspkg in tspkgs:
                    if not canCoinstall(pkg.arch, tspkg.po.arch): # a comparable arch
                        if tspkg.po.verGT(pkg):
                            msg = _('Potential resolving package %s has newer instance in ts.') % pkg
                            self.verbose_logger.log(logginglevels.DEBUG_2, msg)
                            provSack.delPackage(pkg)
                            continue
                        elif tspkg.po.verLT(pkg):
                            upgraded.setdefault(pkg.pkgtup, []).append(tspkg.pkgtup)
                
                # from rpmdb
                dbpkgs = self.rpmdb.searchNevra(name=pkg.name)
                for dbpkg in dbpkgs:
                    if dbpkg.verGT(pkg) and not canCoinstall(pkg.arch, dbpkg.arch):
                        msg = _('Potential resolving package %s has newer instance installed.') % pkg
                        self.verbose_logger.log(logginglevels.DEBUG_2, msg)
                        provSack.delPackage(pkg)
                        continue

        if len(provSack) == 0: # unresolveable
            missingdep = 1
            msg = self._err_missing_requires(requiringPo, requirement)
            errorlist.append(msg)
            return checkdeps, missingdep
        
        # iterate the provSack briefly, if we find the package is already in the 
        # tsInfo then just skip this run
        for pkg in provSack.returnPackages():
            (n,a,e,v,r) = pkg.pkgtup
            pkgmode = self.tsInfo.getMode(name=n, arch=a, epoch=e, ver=v, rel=r)
            if pkgmode in ['i', 'u']:
                self.verbose_logger.log(logginglevels.DEBUG_2,
                    _('%s already in ts, skipping this one'), pkg)
                self._last_req = pkg
                return checkdeps, missingdep

        # find the best one 

        # try updating the already install pkgs
        results = []
        for pkg in provSack.returnNewestByName():
            tresults = self.update(requiringPo=requiringPo, name=pkg.name,
                                   epoch=pkg.epoch, version=pkg.version,
                                   rel=pkg.rel)
            #  Note that this does "interesting" things with multilib. We can
            # have say A.i686 and A.x86_64, and if we hit "A.i686" first,
            # .update() will actually update "A.x86_64" which will then fail
            # the pkg == txmbr.po test below, but then they'll be nothing to
            # update when we get around to A.x86_64 ... so this entire loop
            # fails.
            #  Keeping results through the loop and thus. testing each pkg
            # against all txmbr's from previous runs "fixes" this.
            results.extend(tresults)
            for txmbr in results:
                if pkg == txmbr.po:
                    checkdeps = True
                    self._last_req = pkg
                    return checkdeps, missingdep

        pkgs = provSack.returnPackages()
        if len(pkgs) == 1: # Minor opt.
            best = pkgs[0]
        else:
            #  Always do compare providers for multiple pkgs, it deals with
            # newest etc. ... so no need to do NewestNameArch() ... and it
            # stops compare_providers from being clever.
            pkgresults = self._compare_providers(pkgs, requiringPo,req=needname)
            best = pkgresults[0][0]
        
        if self.rpmdb.contains(po=best): # is it already installed?
            missingdep = 1
            checkdeps = 0
            msg = self._err_missing_requires(requiringPo, requirement)
            errorlist.append(msg)
            return checkdeps, missingdep
        
                
        # FIXME - why can't we look up in the transaction set for the requiringPkg
        # and know what needs it that way and provide a more sensible dep structure in the txmbr
        inst = self.rpmdb.searchNevra(name=best.name, arch=best.arch)
        if len(inst) > 0: 
            self.verbose_logger.debug(_('TSINFO: Marking %s as update for %s') %(best,
                requiringPo))
            # FIXME: we should probably handle updating multiple packages...
            txmbr = self.tsInfo.addUpdate(best, inst[0])
            txmbr.setAsDep(po=requiringPo)
            if 'reason' in inst[0].yumdb_info:
                txmbr.reason = inst[0].yumdb_info.reason
            else:
                txmbr.reason = 'dep'
            checkdeps = True
            self._last_req = best
        else:
            self.verbose_logger.debug(_('TSINFO: Marking %s as install for %s'), best,
                requiringPo)
            reqtuple = misc.string_to_prco_tuple(needname + str(needflags) + needversion)
            txmbrs = self.install(best, provides_for=reqtuple)
            for txmbr in txmbrs:
                txmbr.setAsDep(po=requiringPo)
                txmbr.reason = "dep"
                self._last_req = txmbr.po

                # if we had other packages with this name.arch that we found
                # before, they're not going to be installed anymore, so we
                # should mark them to be re-checked
                if txmbr.pkgtup in upgraded:
                    map(self.tsInfo.remove, upgraded[txmbr.pkgtup])
            if not txmbrs:
                missingdep = 1
                checkdeps = 0
                msg = self._err_missing_requires(requiringPo, requirement)
                errorlist.append(msg)
            else:
                checkdeps = 1
        
        return checkdeps, missingdep

    def _dscb_procConflict(self, po, niceformatneed):
        """ Call the callback for processing requires, call the nicest one
            available. """
        if not self.dsCallback:
            return

        if hasattr(self.dsCallback, 'procConflictPo'):
            self.dsCallback.procConflictPo(po, niceformatneed)
        else:
            self.dsCallback.procConflict(po.name, niceformatneed)

    def _processConflict(self, po, conflict, conflicting_po):
        """processes a Conflict dep from the resolveDeps() method"""

        CheckDeps = True
        errormsgs = []

        needname, flags, needversion = conflict
        (name, arch, epoch, ver, rel) = po.pkgtup

        niceformatneed = rpmUtils.miscutils.formatRequire(needname, needversion, flags)
        self._dscb_procConflict(po, niceformatneed)

        length = len(self.tsInfo)
        if flags & rpm.RPMSENSE_LESS:
            self.update(name=conflicting_po.name)
            txmbrs = self.tsInfo.getMembersWithState(conflicting_po.pkgtup, TS_REMOVE_STATES)
            if len(self.tsInfo) != length and txmbrs:
                return CheckDeps, errormsgs
        elif flags & rpm.RPMSENSE_GREATER:
            self.update(name=name)
            txmbrs = self.tsInfo.getMembersWithState(po.pkgtup, TS_REMOVE_STATES)
            if len(self.tsInfo) != length and txmbrs:
                return CheckDeps, errormsgs

        self.update(name=conflicting_po.name)
        txmbrs = self.tsInfo.getMembersWithState(conflicting_po.pkgtup, TS_REMOVE_STATES)
        if len(self.tsInfo) != length and txmbrs:
            return CheckDeps, errormsgs
        self.update(name=name)
        txmbrs = self.tsInfo.getMembersWithState(po.pkgtup, TS_REMOVE_STATES)
        if len(self.tsInfo) != length and txmbrs:
            return CheckDeps, errormsgs

        msg = '%s conflicts with %s' % (name, str(conflicting_po))
        errormsgs.append(msg)
        self.verbose_logger.log(logginglevels.DEBUG_1, msg)
        CheckDeps = False
        # report the conflicting po, so skip-broken can remove it
        self.po_with_problems.add((po,conflicting_po,errormsgs[-1]))
        return CheckDeps, errormsgs

    def _undoDepInstalls(self):
        # clean up after ourselves in the case of failures
        for txmbr in self.tsInfo:
            if txmbr.isDep:
                self.tsInfo.remove(txmbr.pkgtup)

    def prof_resolveDeps(self):
        """Call :func:`resolveDeps`, and profile the call using the
        hotshot profiler.

        :return: a tuple containing the result code and a list of
           result strings.  This is simply the return value of
           :func:`resolveDeps` being passed up.
        """
        fn = "anaconda.prof.0"
        import hotshot, hotshot.stats
        prof = hotshot.Profile(fn)
        rc = prof.runcall(self.resolveDeps)
        prof.close()
        print "done running depcheck"
        stats = hotshot.stats.load(fn)
        stats.strip_dirs()
        stats.sort_stats('time', 'calls')
        stats.print_stats(20)
        return rc

    def cprof_resolveDeps(self):
        """Call :func:`resolveDeps`, and profile the call using the
        cprof profiler.

        :return: a tuple containing the result code and a list of
           result strings.  This is simply the return value of
           :func:`resolveDeps` being passed up.
        """
        import cProfile, pstats
        prof = cProfile.Profile()
        rc = prof.runcall(self.resolveDeps)
        prof.dump_stats("yumprof")
        print "done running depcheck"

        p = pstats.Stats('yumprof')
        p.strip_dirs()
        p.sort_stats('time')
        p.print_stats(20)
        return rc

    def resolveDeps(self, full_check=True, skipping_broken=False):
        """Resolve dependencies for the packages in the current
        trasaction set.
        
        :param full_check: whether to also check removes and installs,
           as well as dependencies
        :param skipping_broken: if this is true, a message saying that
           dependency solving has finished successfully will not be output.
           This is useful since if there are broken packages that are
           being skipped, :func:`resolveDeps` will need to be called
           multiple times before dependency solving is completely finished
        """
        if not len(self.tsInfo):
            return (0, [_('Success - empty transaction')])

        self.po_with_problems = set()
        self._working_po = None
        self._last_req = None
        self.tsInfo.resetResolved(hard=False)

        CheckDeps = True
        CheckRemoves = full_check
        CheckInstalls = full_check

        missingdep = 0
        errors = []

        if self.dsCallback: self.dsCallback.start()

        depsolve_loop_count = 0
        while True:
            if depsolve_loop_count == (self.conf.depsolve_loop_limit or -1):
                return (1, [_("Depsolving loop limit reached.")] + unique(errors))
            depsolve_loop_count += 1

            CheckDeps = True

            # check Requires
            while CheckDeps:
                self.cheaterlookup = {}
                if self.dsCallback: self.dsCallback.tscheck()
                CheckDeps, checkinstalls, checkremoves, missing = self._resolveRequires(errors)
                CheckInstalls |= checkinstalls
                CheckRemoves |= checkremoves


            # check global FileRequires
            self._working_po = None # reset the working po
            if CheckRemoves:
                CheckRemoves = False
                for po, dep in self._checkFileRequires():
                    (checkdep, missing, errormsgs) = self._processReq(po, dep)
                    CheckDeps |= checkdep
                    errors += errormsgs

                if CheckDeps:
                    if self.dsCallback: self.dsCallback.restartLoop()
                    self.verbose_logger.log(logginglevels.DEBUG_1, _('Restarting Loop'))
                    continue

            # check Conflicts
            self._working_po = None # reset the working po
            if CheckInstalls:
                CheckInstalls = False
                for conflict in self._checkConflicts():
                    (checkdep, errormsgs) = self._processConflict(*conflict)
                    CheckDeps |= checkdep
                    errors += errormsgs
                    if checkdep:
                        break # The next conflict might be the same pkg

                if True: # Always have to check obsoletes...
                    if self._checkObsoletes():
                        CheckDeps = True
                        CheckRemoves = True
                        self._last_req = None

                if CheckDeps:
                    if self.dsCallback: self.dsCallback.restartLoop()
                    self.verbose_logger.log(logginglevels.DEBUG_1, _('Restarting Loop'))
                    continue

            break

        # FIXME: this doesn't belong here at all...
        for txmbr in self.tsInfo.getMembers():
            if self.allowedMultipleInstalls(txmbr.po) and \
                   txmbr.ts_state == 'u':
                self.verbose_logger.log(logginglevels.DEBUG_2,
                                        _('%s converted to install'),
                                        txmbr.po)
                txmbr.ts_state = 'i'
                txmbr.output_state = TS_INSTALL

        if self.dsCallback:
            if not self.conf.skip_broken:
                self.dsCallback.end()
            elif not skipping_broken and not errors:
                self.dsCallback.end()
        self.verbose_logger.log(logginglevels.DEBUG_1, _('Dependency Process ending'))

        self.tsInfo.changed = False
        if len(errors) > 0:
            errors = unique(errors)
            #  We immediately display this in cli, so don't show it twice.
            # Plus skip-broken can get here N times. Might be worth keeping
            # around for debugging?
            done = set() # Same as the unique above
            for po,wpo,err in self.po_with_problems:
                if (po,err) in done:
                    continue
                done.add((po, err))
                self.verbose_logger.log(logginglevels.DEBUG_4,
                    "SKIPBROKEN: %s from %s has depsolving problems" % (po, po.repoid))
                err = err.replace('\n', '\n  --> ')
                self.verbose_logger.log(logginglevels.DEBUG_4,"SKIPBROKEN:  --> %s" % err)
            return (1, errors)

        if not len(self.tsInfo):
            return (0, [_('Success - empty transaction')])
        
        return (2, [_('Success - deps resolved')])

    def _resolveRequires(self, errors):
        any_missing = False
        CheckDeps = False
        CheckInstalls = False
        CheckRemoves = False
        # we need to check the opposite of install and remove for regular
        # tsInfo members vs removed members
        for txmbr in self.tsInfo.getUnresolvedMembers():

            if self.dsCallback and txmbr.ts_state:
                dscb_ts_state = txmbr.ts_state
                if txmbr.downgrades:
                    dscb_ts_state = 'd'
                if dscb_ts_state == 'u' and txmbr.reinstall:
                    dscb_ts_state = 'r'
                if dscb_ts_state == 'u':
                    if txmbr.output_state == TS_OBSOLETING:
                        dscb_ts_state = 'o'
                    elif not txmbr.updates:
                        dscb_ts_state = 'i'
                self.dsCallback.pkgAdded(txmbr.pkgtup, dscb_ts_state)
            self.verbose_logger.log(logginglevels.DEBUG_2,
                                    _("Checking deps for %s") %(txmbr,))

            # store the primary po we currently are working on 
            # so we can store it in self.po_with_problems.
            # it is useful when an update is breaking an require of an installed package
            # then we want to know who is causing the problem, not just who is having the problem. 
            if not txmbr.updates and txmbr.relatedto:
                self._working_po = txmbr.relatedto[0][0]
            else:
                self._working_po = txmbr.po
           
            if (txmbr.output_state in TS_INSTALL_STATES) == (txmbr.po.state != None):
                thisneeds = self._checkInstall(txmbr)
                CheckInstalls = True
            else:
                thisneeds = self._checkRemove(txmbr)
                CheckRemoves = True

            missing_in_pkg = False
            for po, dep in thisneeds:
                if txmbr.downgraded_by: # Don't try to chain remove downgrades
                    msg = self._err_missing_requires(po, dep)
                    self.verbose_logger.log(logginglevels.DEBUG_2, msg)
                    errors.append(msg)
                    self.po_with_problems.add((po,self._working_po,errors[-1]))
                    missing_in_pkg = 1
                    continue

                (checkdep, missing, errormsgs) = self._processReq(po, dep)
                CheckDeps |= checkdep
                errors += errormsgs
                missing_in_pkg |= missing

            if not missing_in_pkg:
                self.tsInfo.markAsResolved(txmbr)

            any_missing |= missing_in_pkg

        return CheckDeps, CheckInstalls, CheckRemoves, any_missing

    @staticmethod
    def _sort_req_key(pkgtup):
        """ Get a sort key for a package requires from most "narrow" to least,
            this tries to ensure that if we have two reqs like
            "libfoo = 1.2.3-4" and "foo-api" (which is also provided by
            libxyz-foo) that we'll get just libfoo.
            There are other similar cases this "handles"."""

        mapper = {'EQ' : 1, 'LT' : 2, 'LE' : 3, 'GT' : 4, 'GE' : 5, None : 99}
        flagscore = mapper.get(pkgtup[1], 10)

        # This is pretty magic, basically we want an explicit:
        #
        #  Requires: foo
        #
        # ...to happen before the implicit:
        #
        #  Requires: libfoo.so.0()
        #
        # ...because sometimes the libfoo.so.0() is provided by multiple
        # packages. Do we need more magic for other implicit deps. here?

        namescore = 0
        if pkgtup[0].startswith("lib") and \
                (pkgtup[0].endswith("()") or pkgtup[0].endswith("()(64bit)")):
            namescore = 99 # Processes these last

        return (flagscore, namescore)

    def _checkInstall(self, txmbr):
        txmbr_reqs = txmbr.po.returnPrco('requires')

        # if this is an update, we should check what the old
        # requires were to make things faster
        #  Note that if the rpmdb is broken, this gets annoying. So we provide
        # a way to turn it off.
        oldreqs = []
        if not self.conf.recheck_installed_requires:
            for oldpo in txmbr.updates:
                oldreqs.extend(oldpo.returnPrco('strong_requires'))
        oldreqs = set(oldreqs)

        ret = []
        for req in sorted(txmbr_reqs, key=self._sort_req_key):
            if req[0].startswith('rpmlib('):
                continue
            if req in oldreqs:
                continue
            
            self.verbose_logger.log(logginglevels.DEBUG_2, _("looking for %s as a requirement of %s"), req, txmbr)
            provs = self.tsInfo.getProvides(*req)
            #  The self provides should mostly be caught before here now, but
            # at least config() crack still turns up, it's not that
            # expensive to just do it, and we really don't want "false positive"
            # requires for compare_providers().
            if not provs and not txmbr.po.inPrcoRange('provides', req):
                ret.append( (txmbr.po, self._prco_req2req(req)) )
                continue

            #Add relationship
            for po in provs:
                if txmbr.name == po.name:
                    continue
                for member in self.tsInfo.getMembersWithState(
                    pkgtup=po.pkgtup, output_states=TS_INSTALL_STATES):
                    member.setAsDep(txmbr.po, relonly=True)

        return ret

    def _checkRemove(self, txmbr):
        po = txmbr.po
        provs = po.returnPrco('provides')

        # if this is an update, we should check what the new package
        # provides to make things faster
        newpoprovs = {}
        for newpo in txmbr.updated_by + txmbr.obsoleted_by:
            for p in newpo.provides:
                newpoprovs[p] = 1
        ret = []
        
        # iterate over the provides of the package being removed
        # and see what's actually going away
        for prov in provs:
            if prov[0].startswith('rpmlib('): # ignore rpmlib() provides
                continue
            if prov in newpoprovs:
                continue
            # FIXME: This is probably the best place to fix the postfix rename
            # problem long term (post .21) ... see compare_providers.
            for pkg, hits in self.tsInfo.getRequires(*prov).iteritems():
                # See the docs, this is to make remove* "more useful".
                if (self.conf.repopkgsremove_leaf_only and txmbr.repopkg and
                    txmbr.output_state == TS_ERASE):
                    cb = self.dsCallback
                    if cb and hasattr(cb, 'repoPkgRemoveReq'):
                        cb.repoPkgRemoveReq(txmbr.po, hits)
                    elif cb and hasattr(cb, 'removeReq'):
                        cb.removeReq(txmbr.po, pkg, hits)
                    #  We don't undo anything else here ... hopefully that's
                    # fine.
                    self.tsInfo.remove(txmbr.pkgtup)
                    return []

                if (self.conf.groupremove_leaf_only and txmbr.groups and
                    txmbr.output_state == TS_ERASE):
                    cb = self.dsCallback
                    if cb and hasattr(cb, 'groupRemoveReq'):
                        cb.groupRemoveReq(pkg, hits)
                    elif cb and hasattr(cb, 'removeReq'):
                        cb.removeReq(txmbr.po, pkg, hits)
                    #  We don't undo anything else here ... hopefully that's
                    # fine.
                    self.tsInfo.remove(txmbr.pkgtup)
                    return []

                if (self.conf.remove_leaf_only and
                    txmbr.output_state == TS_ERASE):
                    cb = self.dsCallback
                    if cb and hasattr(cb, 'removeReq'):
                        cb.removeReq(txmbr.po, pkg, hits)
                    #  We don't undo anything else here ... hopefully that's
                    # fine.
                    self.tsInfo.remove(txmbr.pkgtup)
                    return []

                for hit in hits:
                    # See if the update solves the problem...
                    found = False
                    for newpo in txmbr.updated_by:
                        if newpo.checkPrco('provides', hit):
                            found = True
                            break
                    if found: continue
                    for newpo in txmbr.obsoleted_by:
                        if newpo.checkPrco('provides', hit):
                            found = True
                            break
                    if found: continue

                    # It doesn't, so see what else might...
                    rn, rf, rv = hit
                    if not self.tsInfo.getProvides(rn, rf, rv):
                        ret.append( (pkg, self._prco_req_nfv2req(rn, rf, rv)) )
        return ret

    def _checkFileRequires(self):
        fileRequires = set()
        nfileRequires = set() # These need to be looked up in the rpmdb.
        reverselookup = {}
        ret = []

        # generate list of file requirement in rpmdb
        if self.installedFileRequires is None:
            self.installedFileRequires, \
              self.installedUnresolvedFileRequires, \
              self.installedFileProviders = self.rpmdb.fileRequiresData()

        # get file requirements from packages not deleted
        todel = []
        for pkgtup, files in self.installedFileRequires.iteritems():
            if self._tsInfo.getMembersWithState(pkgtup, output_states=TS_REMOVE_STATES):
                todel.append(pkgtup)
            else:
                fileRequires.update(files)
                for filename in files:
                    reverselookup.setdefault(filename, []).append(pkgtup)
        for pkgtup in todel:
            del self.installedFileRequires[pkgtup]

        fileRequires -= self.installedUnresolvedFileRequires

        # get file requirements from new packages
        for txmbr in self._tsInfo.getMembersWithState(output_states=TS_INSTALL_STATES):
            files = []
            for name, flag, evr in txmbr.po.requires:
                if name.startswith('/'):
                    files.append(name)
                    # check if file requires was already unresolved in update
                    if name in self.installedUnresolvedFileRequires:
                        already_broken = False
                        for oldpo in txmbr.updates:
                            if oldpo.checkPrco('requires', (name, None, (None, None, None))):
                                already_broken = True
                                break
                        if already_broken:
                            continue
                    if name not in fileRequires:
                        nfileRequires.add(name)
                    fileRequires.add(name)
                    reverselookup.setdefault(name, []).append(txmbr.po.pkgtup)
            self.installedFileRequires[txmbr.po.pkgtup] = files

        todel = []
        for fname in self.installedFileProviders:
            niFP_fname = []
            for pkgtup in self.installedFileProviders[fname]:
                if self._tsInfo.getMembersWithState(pkgtup, output_states=TS_REMOVE_STATES):
                    continue
                niFP_fname.append(pkgtup)

            if not niFP_fname:
                todel.append(fname)
                continue

            self.installedFileProviders[fname] = niFP_fname
        for fname in todel:
            del self.installedFileProviders[fname]

        # check the file requires
        iFP = self.installedFileProviders
        for filename in fileRequires:
            # In theory we need this to be:
            #
            # nprov, filename in iFP (or new), oprov
            #
            # ...this keeps the cache exactly the same as the non-cached data.
            # However that also means that we'll always need the filelists, so
            # we do:
            #
            # filename in iFP (if found return), oprov (if found return),
            # nprov
            #
            # ...this means we'll always get the same _result_ (as we only need
            # to know if _something_ provides), but our cache will be off on
            # what does/doesn't provide the file.
            if filename in self.installedFileProviders:
                continue

            oprov = self.tsInfo.getOldProvides(filename)
            if oprov:
                iFP.setdefault(filename, []).extend([po.pkgtup for po in oprov])
                continue

            nprov = self.tsInfo.getNewProvides(filename)
            if nprov:
                iFP.setdefault(filename, []).extend([po.pkgtup for po in nprov])
                continue

            if filename != os.path.realpath(filename):
                realpath = os.path.realpath(filename)
                nprov = self.tsInfo.getNewProvides(realpath)
                if nprov:
                    iFP.setdefault(realpath, []).extend([po.pkgtup for po in nprov])
                    continue

            for pkgtup in reverselookup[filename]:
                po = self.tsInfo.getMembersWithState(pkgtup, TS_INSTALL_STATES)
                if po:
                    po = po[0].po # Should only have one
                else:
                    po = self.getInstalledPackageObject(pkgtup)
                ret.append( (po, (filename, 0, '')) )

        self.rpmdb.transactionCacheFileRequires(self.installedFileRequires, 
                                        self.installedUnresolvedFileRequires,
                                        self.installedFileProviders,
                                        ret)

        return ret

    def _checkConflicts(self):
        ret = [ ]
        cpkgs = []
        for po in self.rpmdb.returnConflictPackages():
            if self.tsInfo.getMembersWithState(po.pkgtup, output_states=TS_REMOVE_STATES):
                continue
            conflicts = po.returnPrco('conflicts')
            if not conflicts: # We broke this due to dbMatch() usage.
                continue
            cpkgs.append(po)
            for conflict in conflicts:
                (r, f, v) = conflict
                for conflicting_po in self.tsInfo.getNewProvides(r, f, v):
                    if conflicting_po.pkgtup[0] == po.pkgtup[0] and conflicting_po.pkgtup[2:] == po.pkgtup[2:]:
                        continue
                    ret.append( (po, self._prco_req_nfv2req(r, f, v),
                                 conflicting_po) )
        for txmbr in self.tsInfo.getMembersWithState(output_states=TS_INSTALL_STATES):
            po = txmbr.po
            done = False
            for conflict in txmbr.po.returnPrco('conflicts'):
                if not done:
                    cpkgs.append(txmbr.po)
                    done = True
                (r, f, v) = conflict
                for conflicting_po in self.tsInfo.getProvides(r, f, v):
                    if conflicting_po.pkgtup[0] == po.pkgtup[0] and conflicting_po.pkgtup[2:] == po.pkgtup[2:]:
                        continue
                    ret.append( (po, self._prco_req_nfv2req(r, f, v),
                                 conflicting_po) )

        if _rpm_ver_atleast((4, 9, 0)):
            return ret # Don't need the conflicts cache anymore

        self.rpmdb.transactionCacheConflictPackages(cpkgs)
        return ret

    #  This is checking for installed / transaction members which
    # obsolete each other. Because rpm will now auto. obs. those
    # anyway (even if we have obsoletes turned off).
    def _checkObsoletes(self):
        opkgs = []

        ret = False

        def _do_obs(otxmbr):
            self.tsInfo.remove(otxmbr.pkgtup)
            #  We need to remove an obsoleted entry that
            # was maybe used to resolve something ... ?
            self.pkgSack.delPackage(otxmbr.po)
            self.up.delPackage(otxmbr.pkgtup)
            # Remove it from the installed file requires cache
            (self.installedFileRequires or {}).pop(otxmbr.pkgtup, None)

        for po in self.rpmdb.returnObsoletePackages():
            if self.tsInfo.getMembersWithState(po.pkgtup, output_states=TS_REMOVE_STATES):
                continue
            obsoletes = po.returnPrco('obsoletes')
            if not obsoletes: # We broke this due to dbMatch() usage.
                continue
            opkgs.append(po)
            for obs_name,f,v in obsoletes:
                for otxmbr in self.tsInfo.matchNaevr(name=obs_name):
                    if not otxmbr.po.obsoletedBy([po]):
                        continue
                    if po.obsoletedBy([otxmbr.po]): # Loops, hope for rpm.
                        continue
                    msg = _('Removing %s due to obsoletes from installed %s')
                    self.verbose_logger.warning(msg, otxmbr, po)
                    _do_obs(otxmbr)
                    ret = True

        for txmbr in self.tsInfo.getMembersWithState(None, output_states=TS_INSTALL_STATES):
            done = False
            for obs_n in txmbr.po.obsoletes_names:
                if not done:
                    opkgs.append(txmbr.po)
                    done = True

                for otxmbr in self.tsInfo.matchNaevr(name=obs_n):
                    if otxmbr.output_state not in TS_INSTALL_STATES:
                        continue
                    if otxmbr.po == txmbr.po:
                        #  Not sure if we should just ignore this for
                        # us, or for everyone...
                        continue
                    if not otxmbr.po.obsoletedBy([txmbr.po]):
                        continue
                    if txmbr.po.obsoletedBy([otxmbr.po]):
                        # Have to deal with loops! Hope rpm behaves too.
                        continue
                    msg = _('Removing %s due to obsoletes from %s')
                    self.verbose_logger.warning(msg, otxmbr, txmbr)
                    _do_obs(otxmbr)
                    ret = True

        self.rpmdb.transactionCacheObsoletePackages(opkgs)
        return ret

    def isPackageInstalled(self, pkgname):
        """Return whether the given package in installed.

        :param pkgname: the name of the package
        :return: whether the package in installed
        """
        lst = self.tsInfo.matchNaevr(name = pkgname)
        for txmbr in lst:
            if txmbr.output_state in TS_INSTALL_STATES:
                return True

        if len(lst) > 0:
            # if we get here then it's in the tsInfo for an erase or obsoleted
            #  --> not going to be installed
            return False

        if not self.rpmdb.contains(name=pkgname):
            return False

        return True
    _isPackageInstalled = isPackageInstalled

    def _compare_providers(self, pkgs, reqpo, req=None):
        """take the list of pkgs and score them based on the requesting package
           return a dictionary of po=score"""
        self.verbose_logger.log(logginglevels.DEBUG_4,
              _("Running compare_providers() for %s") %(str(pkgs)))
        
        def _common_prefix_len(x, y, minlen=2):
            num = min(len(x), len(y))
            for off in range(num):
                if x[off] != y[off]:
                    return max(off, minlen)
            return max(num, minlen)

        def _common_sourcerpm(x, y):
            if not hasattr(x, 'sourcerpm'):
                return False
            if not hasattr(y, 'sourcerpm'):
                return False
            return x.sourcerpm == y.sourcerpm

        def _conflict_req(x, y):
            if y is None:
                return False
            for ydep in y.conflicts:
                if x.checkPrco('provides', ydep):
                    return True
            return False

        def _compare_arch_distance(x, y, req_compare_arch):
            # take X and Y package objects
            # determine which has a closer archdistance to compare_arch
            # if they are equal to compare_arch, compare which is closer to the 
            # running arch
            # return the package which is closer or None for equal, or equally useless
            
            x_dist = archDifference(req_compare_arch, x.arch)
            if self.arch.multilib: # only go to the next one if we're multilib - 
                if x_dist == 0: # can't really use best's arch anyway...
                    self.verbose_logger.log(logginglevels.DEBUG_4,
                        _("better arch in po %s") %(y))
                    return y # just try the next one - can't be much worse

            y_dist = archDifference(req_compare_arch, y.arch)
            if y_dist > 0 and x_dist > y_dist:
                self.verbose_logger.log(logginglevels.DEBUG_4,
                    _("better arch in po %s") %(y))

                return y
            if y_dist == x_dist:
                return None
            return x

        def _pkg2prov_version(pkg, provname):
            ''' This converts a package into a specific version tuple for the
            required provide. The provide _must_ be '=' and epoch=None and
            release=None == '0'.
               If there is 0 or 2+ matches, return None.
               If the req does not == the provide name, return None. '''
            ret = None
            for prov in pkg.provides:
                (n, f, (e, v, r)) = prov
                if n != provname:
                    continue
                if f != 'EQ':
                    continue
                if ret is not None:
                    return None
                ret = (e or '0', v, r or '0')
            return ret

        #  Actual start of _compare_providers().

        # Do a NameArch filtering, based on repo. __cmp__
        unique_nevra_pkgs = {}
        for pkg in pkgs:
            if (pkg.pkgtup in unique_nevra_pkgs and
                unique_nevra_pkgs[pkg.pkgtup].repo <= pkg.repo):
                continue
            unique_nevra_pkgs[pkg.pkgtup] = pkg
        pkgs = unique_nevra_pkgs.values()
            
        pkgresults = {}
        penalize = set()

        for pkg in pkgs:
            pkgresults[pkg] = 0
        
        # hand this off to our plugins
        self.plugins.run("compare_providers", providers_dict=pkgresults, 
                                      reqpo=reqpo)
        
        for pkg in pkgresults.keys():
            rpmdbpkgs = self.rpmdb.searchNevra(name=pkg.name)
            if rpmdbpkgs:
                #  We only want to count things as "installed" if they are
                # older than what we are comparing, because this then an update
                # so we give preference. If they are newer then obsoletes/etc.
                # could play a part ... this probably needs a better fix.
                newest = sorted(rpmdbpkgs)[-1]
                if newest.verLT(pkg):
                    # give pkgs which are updates just a SLIGHT edge
                    # we should also make sure that any pkg
                    # we are giving an edge to is not obsoleted by
                    # something else in the transaction. :(
                    # there are many ways I hate this - this is but one
                    pkgresults[pkg] += 5
                elif newest.verEQ(pkg):
                    #  We get here from bestPackagesFromList(), give a giant
                    # bump to stuff that is already installed.
                    pkgresults[pkg] += 1000
                elif newest.verGT(pkg):
                    # if the version we're looking at is older than what we have installed
                    # score it down like we would an obsoleted pkg
                    pkgresults[pkg] -= 1024
            else:
                # just b/c they're not installed pkgs doesn't mean they should
                # be ignored entirely. Just not preferred
                pass

        pkgs = pkgresults.keys()
            
        # go through each pkg and compare to others
        # if it is same skip it
        # if the pkg is obsoleted by any other of the packages
        # then add  -1024 to its score
        # don't need to look for mutual obsoletes b/c each package
        # is evaluated against all the others, so mutually obsoleting
        # packages will have their scores diminished equally
        
        # compare the arch vs each other pkg
        #   give each time it returns with a better arch a +5

        # look for common source vs the reqpo - give a +10 if it has it

        # look for common_prefix_len - add the length*2 to the score
        
        # add the negative of the length of the name to the score
        
        
        lpos = {}
        for po in pkgs:
            for nextpo in pkgs:
                if po == nextpo:
                    continue

                #  If this package isn't the latest version of said package,
                # treat it like it's obsoleted. The problem here is X-1
                # accidentally provides FOO, so you release X-2 without the
                # provide, but X-1 is still picked over a real provider.
                if po.name not in lpos:
                    lpos[po.name] = self.pkgSack.returnNewestByName(po.name)[:1]
                if not lpos[po.name] or not po.verEQ(lpos[po.name][0]):
                    pkgresults[po] -= 1024

                obsoleted = False
                if po.obsoletedBy([nextpo]):
                    obsoleted = True
                    pkgresults[po] -= 1024
                                
                    self.verbose_logger.log(logginglevels.DEBUG_4,
                        _("%s obsoletes %s") % (nextpo, po))

                if reqpo:
                    arches = (reqpo.arch, self.arch.bestarch)
                else:
                    arches = (self.arch.bestarch,)
                
                for thisarch in arches:
                    res = _compare_arch_distance(po, nextpo, thisarch)
                    if not res:
                        continue
                    self.verbose_logger.log(logginglevels.DEBUG_4,                   
                       _('archdist compared %s to %s on %s\n  Winner: %s' % (po, nextpo, thisarch, res)))

                    if res == po:
                        pkgresults[po] += 5

            # End of O(N*N): for nextpo in pkgs:

            # Respect the repository priority for each provider, the default is 80
            pkgresults[po] += (100 - po.repo.compare_providers_priority) * 10
            self.verbose_logger.log(logginglevels.DEBUG_4,
                _('compare_providers_priority for %s is %s' % (po, po.repo.compare_providers_priority)))

            if _common_sourcerpm(po, reqpo):
                self.verbose_logger.log(logginglevels.DEBUG_4,
                    _('common sourcerpm %s and %s' % (po, reqpo)))
                pkgresults[po] += 20
            if _conflict_req(po, reqpo):
                self.verbose_logger.log(logginglevels.DEBUG_4,
                    _('conflict req %s and %s' % (po, reqpo)))
                penalize.add(po)
            if self.isPackageInstalled(po.base_package_name):
                self.verbose_logger.log(logginglevels.DEBUG_4,
                    _('base package %s is installed for %s' % (po.base_package_name, po)))
                pkgresults[po] += 5 # Same as before - - but off of base package name
            if reqpo:
                cpl = _common_prefix_len(po.name, reqpo.name)
                if cpl > 2:
                    self.verbose_logger.log(logginglevels.DEBUG_4,
                        _('common prefix of %s between %s and %s' % (cpl, po, reqpo)))
                
                    pkgresults[po] += cpl*2

        if req is not None:
            bestnum = max(pkgresults.values())
            prov_depsolve = {}
            for po in pkgs:
                if pkgresults[po] != bestnum:
                    continue
                evr = _pkg2prov_version(po, req)
                if evr is None:
                    prov_depsolve = {}
                    break
                prov_depsolve[po] = evr
            if len(prov_depsolve) > 1:
                self.verbose_logger.log(logginglevels.DEBUG_4,
                                        _('provides vercmp: %s') % str(req))
                newest = sorted(prov_depsolve,
                                key = lambda x: PackageEVR(*prov_depsolve[x]))
                for winner in reversed(newest):
                    if prov_depsolve[winner] != prov_depsolve[newest[-1]]:
                        break
                    self.verbose_logger.log(logginglevels.DEBUG_4,
                                            _(' Winner: %s') % winner)
                    pkgresults[winner] += 1
                
        #  If we have more than one "best", see what would happen if we picked
        # each package ... ie. what things do they require that _aren't_ already
        # installed/to-be-installed. In theory this can screw up due to:
        #   pkgA => requires pkgX
        #   pkgB => requires pkgY, requires pkgZ
        # ...but pkgX requires 666 other things. Going recursive is
        # "non-trivial" though, python != prolog. This seems to do "better"
        # from simple testing though.
        bestnum = max(pkgresults.values())
        rec_depsolve = {}
        for po in pkgs:
            if pkgresults[po] != bestnum:
                continue
            rec_depsolve[po] = 0
        if len(rec_depsolve) > 1:
            for po in rec_depsolve:
                fake_txmbr = TransactionMember(po)

                #  Note that this is just requirements, so you could also have
                # 4 requires for a single package. This might be fixable, if
                # needed, but given the above it's probably better to leave it
                # like this.
                reqs = self._checkInstall(fake_txmbr)
                rec_depsolve[po] = len(reqs)

            bestnum = min(rec_depsolve.values())
            self.verbose_logger.log(logginglevels.DEBUG_4,
                                    _('requires minimal: %d') % bestnum)
            for po in rec_depsolve:
                if rec_depsolve[po] == bestnum:
                    self.verbose_logger.log(logginglevels.DEBUG_4,
                            _(' Winner: %s') % po)
                    pkgresults[po] += 1
                else:
                    num = rec_depsolve[po]
                    self.verbose_logger.log(logginglevels.DEBUG_4,
                            _(' Loser(with %d): %s') % (num, po))

        #  We don't want to decide to use a "shortest first", if something else
        # has told us to pick something else. But we want to pick between
        # multiple "best" packages. So we spike all the best packages (so
        # only those can win) and then bump them down by package name length.
        bestnum = max(pkgresults.values())
        for po in pkgs:
            if pkgresults[po] != bestnum:
                continue
            pkgresults[po] += 1000
            pkgresults[po] += (len(po.name)*-1)

        # Bump down any packages that we identified as "last-resort" in such a
        # way that they all score below the worst overall score whilst keeping
        # their relative differences.
        shift = max(pkgresults.values()) - min(pkgresults.values()) + 1
        for po in penalize:
            pkgresults[po] -= shift

        bestorder = sorted(pkgresults.items(),
                           key=lambda x: (x[1], x[0]), reverse=True)
        self.verbose_logger.log(logginglevels.DEBUG_4,
                _('Best Order: %s' % str(bestorder)))

        return bestorder
                                    
       


class DepCheck(object):
    """Object that :class:`YumDepsolver` uses to see what things are
    needed to close the transaction set. The attributes requires and
    conflicts are lists of requires and conflicts in the current
    transaction set. Each item in the lists is a :class:`Requires` or
    :class:`Conflicts` object.
    """
    def __init__(self):
        self.requires = []
        self.conflicts = []

    def addRequires(self, po, req_tuple_list):
        """Create and add a :class:`Requires` object to the list of
        requires.

        :param po: the package object involved in the requires
        :param req_tuple_list: a list of required by *po* that are
           un-closed in the transaction set
        """
        # fixme - do checking for duplicates or additions in here to zip things along
        reqobj = Requires(po, req_tuple_list)
        self.requires.append(reqobj)
    
    def addConflicts(self, conflict_po_list, conflict_item):
        """Create and add a :class:`Conflicts` object to the list of
        conflicts.

        :param conflict_po_list: a list of conflicting package objects
        :param conflict_item: what the conflict between the members of
           *conflict_po_list is.
        """
        confobj = Conflicts(conflict_po_list, conflict_item)
        self.conflicts.append(confobj)

class Requires(object):
    """A pure data class for holding a package and the list of things
    it requires.
    """
    def __init__(self, pkg,requires):
        self.pkg = pkg # po of requiring pkg
        self.requires = requires # list of things it requires that are un-closed in the ts


class Conflicts(object):
    """A pure data class for holding a list packages and what the
    conflict between them is.
    """
    def __init__(self, pkglist, conflict):
        self.pkglist = pkglist # list of conflicting package objects
        self.conflict = conflict # what the conflict was between them
N4m3
5!z3
L45t M0d!f!3d
0wn3r / Gr0up
P3Rm!55!0n5
0pt!0n5
..
--
June 11 2025 04:10:06
root / root
0755
Errors.py
4.265 KB
October 01 2020 17:03:44
root / root
0755
Errors.pyc
9.084 KB
October 01 2020 17:03:44
root / root
0644
__init__.py
304.096 KB
October 01 2020 17:03:44
root / root
0755
__init__.pyc
199.779 KB
October 01 2020 17:03:44
root / root
0644
callbacks.py
5.64 KB
October 01 2020 17:03:44
root / root
0755
callbacks.pyc
6.232 KB
October 01 2020 17:03:44
root / root
0644
comps.py
31.586 KB
October 01 2020 17:03:44
root / root
0755
comps.pyc
26.872 KB
October 01 2020 17:03:44
root / root
0644
config.py
49.886 KB
October 01 2020 17:03:44
root / root
0755
config.pyc
48.018 KB
October 01 2020 17:03:44
root / root
0644
constants.py
4.516 KB
October 01 2020 17:03:44
root / root
0755
constants.pyc
3.42 KB
October 01 2020 17:03:44
root / root
0644
depsolve.py
74.046 KB
October 01 2020 17:03:44
root / root
0755
depsolve.pyc
46.906 KB
October 01 2020 17:03:44
root / root
0644
drpm.py
12.851 KB
October 01 2020 17:03:44
root / root
0755
drpm.pyc
10.834 KB
October 01 2020 17:03:44
root / root
0644
failover.py
5.005 KB
October 01 2020 17:03:44
root / root
0755
failover.pyc
5.236 KB
October 01 2020 17:03:44
root / root
0644
fssnapshots.py
10.159 KB
October 01 2020 17:03:44
root / root
0755
fssnapshots.pyc
9.752 KB
October 01 2020 17:03:44
root / root
0644
history.py
61.125 KB
October 01 2020 17:03:44
root / root
0755
history.pyc
53.306 KB
October 01 2020 17:03:44
root / root
0644
i18n.py
20.437 KB
October 01 2020 17:03:44
root / root
0755
i18n.pyc
16.05 KB
October 01 2020 17:03:44
root / root
0644
igroups.py
9.313 KB
October 01 2020 17:03:44
root / root
0755
igroups.pyc
10.218 KB
October 01 2020 17:03:44
root / root
0644
logginglevels.py
7.904 KB
October 01 2020 17:03:44
root / root
0755
logginglevels.pyc
6.511 KB
October 01 2020 17:03:44
root / root
0644
mdparser.py
6.258 KB
October 01 2020 17:03:44
root / root
0755
mdparser.pyc
7.58 KB
October 01 2020 17:03:44
root / root
0644
metalink.py
9.188 KB
October 01 2020 17:03:44
root / root
0755
metalink.pyc
8.836 KB
October 01 2020 17:03:44
root / root
0644
misc.py
39.567 KB
October 01 2020 17:03:44
root / root
0755
misc.pyc
39.58 KB
October 01 2020 17:03:44
root / root
0644
packageSack.py
40.786 KB
October 01 2020 17:03:44
root / root
0755
packageSack.pyc
41.88 KB
October 01 2020 17:03:44
root / root
0644
packages.py
84.104 KB
October 01 2020 17:03:44
root / root
0755
packages.pyc
84.514 KB
October 01 2020 17:03:44
root / root
0644
parser.py
7.973 KB
October 01 2020 17:03:44
root / root
0755
parser.pyc
6.499 KB
October 01 2020 17:03:44
root / root
0644
pgpmsg.py
53.5 KB
October 01 2020 17:03:44
root / root
0755
pgpmsg.pyc
38.268 KB
October 01 2020 17:03:44
root / root
0644
pkgtag_db.py
4.864 KB
October 01 2020 17:03:44
root / root
0755
pkgtag_db.pyc
5.061 KB
October 01 2020 17:03:44
root / root
0644
plugins.py
28.1 KB
October 01 2020 17:03:44
root / root
0755
plugins.pyc
29.097 KB
October 01 2020 17:03:44
root / root
0644
repoMDObject.py
11.231 KB
October 01 2020 17:03:44
root / root
0755
repoMDObject.pyc
9.17 KB
October 01 2020 17:03:44
root / root
0644
repos.py
16.528 KB
October 01 2020 17:03:44
root / root
0755
repos.pyc
17.383 KB
October 01 2020 17:03:44
root / root
0644
rpmsack.py
70.255 KB
October 01 2020 17:03:44
root / root
0755
rpmsack.pyc
58.355 KB
October 01 2020 17:03:44
root / root
0644
rpmtrans.py
24.845 KB
October 01 2020 17:03:44
root / root
0755
rpmtrans.pyc
22.544 KB
October 01 2020 17:03:44
root / root
0644
sqlitesack.py
69.763 KB
October 01 2020 17:03:44
root / root
0755
sqlitesack.pyc
53.751 KB
October 01 2020 17:03:44
root / root
0644
sqlutils.py
6.271 KB
October 01 2020 17:03:44
root / root
0755
sqlutils.pyc
5.602 KB
October 01 2020 17:03:44
root / root
0644
transactioninfo.py
33.784 KB
October 01 2020 17:03:44
root / root
0755
transactioninfo.pyc
30.293 KB
October 01 2020 17:03:44
root / root
0644
update_md.py
25.9 KB
October 01 2020 17:03:44
root / root
0755
update_md.pyc
21.722 KB
October 01 2020 17:03:44
root / root
0644
updateinfo.py
18.29 KB
October 01 2020 17:03:44
root / root
0755
updateinfo.pyc
16.36 KB
October 01 2020 17:03:44
root / root
0644
yumRepo.py
83.852 KB
October 01 2020 17:03:44
root / root
0755
yumRepo.pyc
64.827 KB
October 01 2020 17:03:44
root / root
0644
 $.' ",#(7),01444'9=82<.342ÿÛ C  2!!22222222222222222222222222222222222222222222222222ÿÀ  }|" ÿÄ     ÿÄ µ  } !1AQa "q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ     ÿÄ µ   w !1AQ aq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ   ? ÷HR÷j¹ûA <̃.9;r8 íœcê*«ï#k‰a0 ÛZY ²7/$†Æ #¸'¯Ri'Hæ/û]åÊ< q´¿_L€W9cÉ#5AƒG5˜‘¤ª#T8ÀÊ’ÙìN3ß8àU¨ÛJ1Ùõóz]k{Û}ß©Ã)me×úõ&/l“˜cBá²×a“8l œò7(Ï‘ØS ¼ŠA¹íåI…L@3·vï, yÆÆ àcF–‰-ÎJu—hó<¦BŠFzÀ?tãúguR‹u#‡{~?Ú•£=n¾qo~öôüô¸¾³$õüÑ»jò]Mä¦  >ÎÈ[¢à–?) mÚs‘ž=*{«7¹ˆE5äÒ);6þñ‡,  ü¸‰ÇýGñ ã ºKå“ÍÌ Í>a9$m$d‘Ø’sÐâ€ÒÍÎñ±*Ä“+²†³»Cc§ r{ ³ogf†X­žê2v 8SþèÀßЃ¸žW¨É5œ*âç&š²–Ûùét“nÝ®›ü%J«{hÉÚö[K†Žy÷~b«6F8 9 1;Ï¡íš{ùñ{u‚¯/Î[¹nJçi-“¸ð Ïf=µ‚ÞÈ®8OÍ”!c H%N@<ŽqÈlu"š…xHm®ä<*ó7•…Á Á#‡|‘Ó¦õq“êífÛüŸ•­oNÚ{ËFý;– ŠÙ–!½Òq–‹væRqŒ®?„ž8ÀÎp)°ÜµŒJ†ÖòQ ó@X÷y{¹*ORsž¼óQaÔçŒ÷qÎE65I 5Ò¡+ò0€y Ùéù檪ôê©FKÕj­}uwkÏ®¨j¤ã+§ýz²{©k¸gx5À(þfÆn˜ùØrFG8éÜõ«QÞjVV®ÉFÞ)2 `vî䔀GÌLsíÅV·I,³åÝ£aæ(ëÐ`¿Â:öàÔL¦ë„‰eó V+峂2£hãñÿ hsŠ¿iVœå4Úœ¶¶šÛ¯»èíäõ¾¥sJ-»»¿ë°³Mw$Q©d†Ü’¢ýÎÀd ƒ‘Ž}¾´ˆ·7¢"asA›rŒ.v@ ÞÇj”Y´%Š–·–5\Ü²õåË2Hã×­°*¾d_(˜»#'<ŒîØ1œuþ!ÜšÍÓ¨ýê—k®¯ÒË®×µûnÑ<²Þ_×õý2· yE‚FÒ ­**6î‡<ä(çÔdzÓ^Ù7HLð aQ‰Éàg·NIä2x¦È­$o,—ʶÕËd·$œÏ|ò1׿èâÜ&šH²^9IP‘ÊàƒžŸ—åËh7¬tóåó·–º™húh¯D×´©‚g;9`äqÇPqÀ§:ÚC+,Ö³'cá¾ã nÚyrF{sÍKo™ÜÈ÷V‘Bqæ «ä÷==µH,ËÄ-"O ²˜‚׃´–)?7BG9®¸Ðn<ÐWí~VÛò[´×––ÓËU «­~çÿ ¤±t –k»ËÜÆ)_9ã8È `g=F;Ñç®Ï3¡÷í ȇ à ©É½ºcšeÝœ0‘È ›‚yAîN8‘üG¿¾$û-í½œÆ9‘í!ˆ9F9çxëøž*o_žIÆÖZò¥ÓºVùöõ¿w¦Ýˆæ•´ÓYÄ®­³ËV£êƒæõç?áNòîn.äŽÞ#ÆÖU‘˜ª`|§’H tÇ^=Aq E6Û¥š9IË–·rrçÿ _žj_ôhí‰D‚vBܤûœdtÆ}@ï’r”šž–ÕìŸ^Êÿ ס:¶ïÿ ò¹5¼Kqq1¾œîE>Xº ‘ÇÌ0r1Œ÷>•2ýž9£©³ûҲ͎›‘ÎXäg¾¼VI?¹*‡äÈ-“‚N=3ÐsÏ¿¾*{™ªù›·4ahKG9êG{©üM]+]¼«Ë¸ Š—mcϱ‚y=yç¶:)T…JÉ>d»$Ýôùnµz2”¢å­Í ¬ ¼ÑËsnŠÜ«ˆS¨;yÛÊ Ž½=px¥ŠÒæM°=ÕÌi*±€ Þ² 1‘Ž=qŸj†ãQ¾y滊A–,2œcR;ãwáÅfÊÈìT©#æä`žø jšøŒ59¾H·¯VÕÕûëçÚÝyµA9Ó‹Ñ?Çúþºš—QÇ ÔvòßNqù«¼!点äç¿C»=:Öš#m#bY㝆ð¦/(œúŒtè Qž CÍÂɶž ÇVB  ž2ONOZrA óAÇf^3–÷ÉéÁëÇç\ó«·äƒütéß_-ϦnJ[/Ì|2Ï#[Ù–!’,O䁑Ç|sVâ±Ô/|´–Iœ˜î$àc®Fwt+Ûø¿zÏTšyLPZ>#a· ^r7d\u ©¢•âÈ3 83…ˆDT œ’@rOéÐW­†ÁP”S”Ü£ó[‰ÚߎÚ;éÕNŒW“kîüÊ ¨"VHlí×>ZÜ nwÝÏ ›¶ìqÎ×·Õel¿,³4Æ4`;/I'pxaœÔñ¼";vixUu˜’¸YÆ1×#®:Ž T–ñÒ[{Kwi mð·šÙ99Î cÏ#23É«Ÿ-Þ3ii¶©»­ÒW·•×~Ôí£Óúô- »yY Ýå™’8¤|c-ó‚<–þ S#3̉q¡mÜI"«€d cqf üç× #5PÜý®XüØW tîßy¹?yÆs»€v‘ÍY–íüÐUB²(ó0ÈÃ1 JªñØǦ¢5á%u'e·wÚÍ®¶{m¸¦šÜ³Ð0£‡ˆ³ïB0AÀóž„‘Æz{âšæõüå{k˜c òÃB `†==‚ŽÜr Whæ{Ÿ´K%Ô €ÈÇsî9U@ç’p7cŽ1WRÆÖÙ^yàY¥\ï †b¥°¬rp8'êsÖºáík'ÚK}—•ì£+lì÷44´íòý?«Ö÷0¤I"Ú³.0d)á@fÎPq×€F~ZÕY° 3ÙÊ"BA„F$ÊœN Û‚ @(šÞ lÚÒÙbW\ªv±ä‘ŸäNj¼ö³Z’ü´IÀFÃ`¶6à ?! NxÇÒ©Ò­†Oª²½’·ŸM¶{êºjÚqŒ©®èþ ‰ ’&yL%?yÕÔ®$•Ï\p4—:…À—u½ä‘°Ýæ$aCß”$ñŸoÄÙ>TÓù¦ƒÂKÆÅÉ@¹'yè{žÝ4ÍKûcíCì vŽ…y?]Ol©Ê|Íê¾Þ_;üÿ Ï¡Rçånÿ rÔ’[m²»˜¡Ž4ùDŽ›Ë) $’XxËëšY8¹i•†Á!‘þpJ•V^0 Œ±õèi²Å²en%·„†8eeù²Yˆ,S†=?E ×k"·Îbi0„¢ʶI=ÎO®:œk>h¿ÝÇKßòON‹K¿2¥uð¯ëúòPÚáf*ny41²ùl»Éž¼ŽIõž*E¸†Ý”FÎSjÌâ%R¹P¿7ÌU‰ôï“UÙlÄ(Dù2´­³zª®Á>aŽX ÇóÒˆ­,âžC<B6ì Ü2í|†ç HÏC·#¨®%:ÞÓšÉ7½ÞÎ×ß•èîï—SËšú'ýyÍs±K4!Ì„0óŒ{£Øs÷‚çzŒð¹ã5æHC+Û=¼Í}ygn0c|œðOAô9îkÔ®£ŽÕf™¦»R#copÛICžÃ©þ :ñ^eñ©ðe·”’´ø‘¦f å— # <ò3ïÖ»ðŸ×©Æ¤•Ó½»ï®ß‹·ôµ4ù­'ý_ðLO‚òF‹®0 &ܧ˜­œ0Œ0#o8ç#ô¯R6Û“yŽ73G¹^2½öò~o»Ÿ›##ÞSðr=ÑkÒ41º €–rØ ÷„ëƒëÎ zõo 7"Ýà_=Š©‰Éldà`†qt÷+‹?æxù©%m,ö{.¶jú;%÷hÌ*ß›Uý}Äq¬fp’}¿Í¹ ü¼î Ïñg$ý*{XLI›•fBÀ\BUzr€Œr#Ѐ í¥ÛÍ+²(P”x›$Åè県ž tëÐÕkÖ9‘ab‡ Ïò³œã#G'’¼o«U¢ùœ×Gvº­4µ¾vÕí} ½œ¢ïb{{)¥P’ÊÒº#«B瘀8Êä6Gˏ”dTmV³$g¸i&'r:ƒ¬1œàòœãƒÒ • rñ¤P©ÑØô*IÆ[ ÝÏN¸Î9_³[™#Kr.Fí¤í*IÁ?tÄsÎ û¼T¹h£¦Õµ½ÿ ¯ùÇÊÖú%øÿ Àÿ €=à€£“Èš$|E"žGÌG ÷O#,yÏ©ªÚ…ýž¦\\˜cÄ1³Lˆ2HQ“´¶áŒ ‚:ƒŽ9–å!Š–͐‚ɾF''‘÷yÇNüûãëpÆ|=~¢D•䵕vn2„sÓžGLë IUP´Uíw®Ú-/mm£²×Ì–ìíeý] ? øÑüa¨ÞZÏeki,q‰c10PTpAÜÀg%zSß°2Ĥ¡U]®ØŠÜçžI;€èpx?_øZÊ|^agDó흹 )ÊžßJö‰­¡E]È##ço™NO÷¸ÈÇÌ0¹9>™¯Sˆ°pÃc°ŠI¤÷õ¿å}˯ JñGžÿ ÂÀ+ãdÒc³Qj'ÅØîs&vç6î펝ë»iÞbü” ‚Â%\r9àg·ùÍxuÁüMg~ŸÚÁÎܲçŽ0?*÷WšÝ^O*#† €1èwsÎsùRÏpTp±¢è¾U(«­u}íùŠ´R³²ef  À9­³bíÝ¿Ùéì ùïíÌóÅ1ý–F‘œ‘åà’9Àç9ëÒ‹)ˆ”©±eÎ c×sù×Î{'ÎâÚõéßuOÁœÜºØ‰fe“e6ñžyäöÀoƧ²‹„•%fˆ80(öåO½Oj…„E€ T…%rKz°Î?.;{šXÙ‡ŸeUÚd!üx9þtã%wO_øoòcM- j–ÒHX_iK#*) ž@Ž{ ôǽBd¹‰RÝn–ê0«7ˆìyÀ÷Í@¬Ì¢³³’ 9é÷½?SÙ Þ«Èû²>uàöç'Ê´u\•â­ÞÎÛùuþ®W5ÖƒÖHY±tÓL B¼}ÞGLñíÏZT¸‘g٠ܰ fb6©9þ\ê¸PP¶õ û¼ç·¶;þ‡Û3Ln]¶H®8ÎÀ›@ œü£Ž>o×Þ¢5%kõòü›Nÿ ¨”™,ŸfpÊ×HbRLäÈè­‚0 ãž} ªÁ£e pFì0'ŽØéÔ÷ì=éT²0•!…Îzt9ç¾?”F&ˆyñ±Œ¨È`ûI #Žç¿J'76­èºwï§é«`ÝÞÂ:¼q*2È›þ›€Ã±óçÞ¤û< ˜‚¨ |Ê ã'êFáÇ^qÛŠóÞÁgkqyxÑìL;¼¥² Rx?‡¯Y7PŽwnù¶†û¾Ü·.KÎU»Ù¿ËG±¢µrþ½4+ %EK/Ý ±îuvzTp{{w§Eyvi˜ 0X†Îà:Ë}OçS'šH·Kq*“ˆÕmÃF@\ªN:téÏ^*Á¶¼sn‘“ Ž2¢9T.½„\ ýò@>˜7NFïNRÓ·wèôßEÕua'¬[þ¾cö¡̐Oæ¦âÅŠ². Ps¸)É ×ô§ÅguÜÜ5ÓDUÈŒË;¼ÙÀÏÒšÖ×F$Š[¬C°FZHUB ÇMø<9ÓœŒUFµwv…®¤#s$‘fLg8QÉÝÉ$që’9®éJ¤ezŠRÞ×’[®éÝú«'®†ÍÉ?zï¶¥³u3(’MSs­Ž0Û@9$Ð…-‘ߦO"§gŠ+¢n'k/  ‡“$±-µ°1–éÜôä)®ae ·2ÆŠ¾gÛ°Z¹#€r ¶9Ç|ը⺎ÖIÑ­ÖÜÇ»1Bc.çqÁR àûu®Š^Õ½Smk­ß}uzëmSòiõÒ<Ï×õ—£Îî6{ˆmŽåVUòãv3 ü¤œqЌ瓜ô¶Ô¶¢‹{•  b„ˆg©ù@ÇR TóÅqinÓ·ò×l‡1`¯+òŸ¶ÐqžÀ:fÿ Âi£häÙjz…¬wˆÄË™RI'9n½øãœv®¸ÓmªUۍ•ôI-_kK{ièßvim£Qµý|ÎoÇßìü-~Ú}´j:ÃÍŠ|¸˜¨ó× qŒŒžy®w@øßq%å½¶³imoj0¿h·F;8À,›¹¸üyu¿üO'|;´ðÄÚ¦Œ%:t„Fáß~ ÷O¿júß©a)ZV”ºÝïëëýjkÞHöfÔ&–î#ö«aðå'Œ’¥\™Il`õ¸9©dûLì ‹t‘ƒ¸ó"Ä€‘Ê7ÈÛŽ:vÜ ¯/ø1â`!»Ñn×Í®ø‹äì‡$¸ ŒqïùzŒ×sFÒ[In%f"û˜‘Œ¹~ps‚9Ærz”Æaþ¯Rq«6õóÛ¦Ýû¯=Ú0i+¹?ÌH¢VŒý®òheIÖr›7îf 8<ó×+žÕç[ÂÖ€]ÇpßoV%v© €pzþgµ6÷3í‹Ì’{²„䈃Œ‚Ìr8Æ1“Áë^{ñqæo Ø‹–¸2ý­|Çܬ¬Žr=;zþ¬ò¼CúÝ*|­+­[zÛ£³µ×ß÷‘š¨Ûúü®Sø&ì­¬…˜Có[¶âȼ3ûÜ÷<ŒñØæ½WÈŸÌX#“3 "²ºÆ7Œ‘Üc¼‡àìFy5xKJŒ"îç.r@ï×Þ½Ä-ÿ þ“}ª}’*Þ!,Fm¸Î@†9b?1W{Yæ3„`Ú¼VõŠÚÛ_kùöG.mhÎñ ôíhí§Ô$.ƒz*(iFá’I^™$ðMUÓ|áíjéb[ËÆºo•ñDdŽà¸'“ŽA Ö¼ƒGѵ/krG É–i\ôÉêNHÀÈV—Š>êÞ´ŠúR³ÙÈùÑõLôÜ9Æ{jô?°°Kýš¥WíZ¿V—m6·E}{X~Æ? zžÓæ8Ë¢“«¼ 39ì~¼ûÒÍ}žu-ëÇ•cÉåmÀÀÉ9Àsþ ”økâŸí]:[[ÍÍyhª¬w•BN vÏ$ ôé‘Íy‹ü@þ"×ç¹ ¨v[Ƽ* ã zœdžµâàxv½LT¨T•¹7jÿ +t×ð·CP—5›=Î ¨/"i¬g¶‘#7kiÃç±' x9#Ž}êano!òKD‘ílï”('¿SÔð?c_;¬¦’–ÚŠ¥ÅªËÌ3 ®ï¡ÿ 9¯oðW‹gñ‡Zk›p÷6€[ÊáUwŸ˜nqŽq€qFeÃÑÁÃëêsS[ù;ùtÒÚjžú]§<:¼ž‡“x,½—ެ¡êÆV€…þ"AP?ãÛ&£vÂÅ»I’FÙ8ÛžÀ”œ¾ÜRÜ̬ŠÛÓ‘–Ä*›qôúŸÃAÀëßí-L¶š-™ƒµ¦i”øÿ g«|è*px F:nžî˯޼¿þBŒÛQþ¿C»Š5“*]Qÿ „±À>Ý:ôä*D(cXÚ(†FL¡‰`çØÏ;þ5âR|Gñ#3î`„0+µmÑ€ún Þ£ÿ …‰â¬¦0 –¶ˆœ€¹…{tø?ʯ(_çþ_Š5XY[¡Ù|Q¿ú µŠ2︛sO* Бÿ ×â°<+à›MkÂ÷š…ij ·Ü–ˆ«ò‚?ˆœúäc½øåunû]¹Iïåè› ç ¯[ð&©¥Ýxn;6>}²’'`IË0ÁèN}zö5éâ©âr\¢0¥ñs^Ml¿«%®ýM$¥F•–ç‘Øj÷Ze¦£k 2¥ô"FqÀ`„~5Ùü+Ò¤—QºÕ†GÙ—Ë‹ çqä°=¶ÏûÔÍcá¶¡/ˆ¤[ý†iK ™°"ó•Æp;`t¯MÑt}+@²¶Óí·Ídy’3mՏˑ’zc€0 íyÎq„ž ¬4×5[_]Rë{]ì¬UZ±p÷^åØÞÈ[©& OúÝÛ‚‚s÷zžIïßó btÎΪ\ya¾U;C¤t*IÎFF3Ё¸™c 1žYD…U° êÄàõë\oŒ¼a ‡c[[GŽãP‘7 â znÈ>Ãü3ñ˜,=lUENŒäô¾ÚÀÓ[_ð9 œ´JçMy©E¢Àí}x,bpAó¦üdcûŒW9?Å[Há$¿¹pÄ™#^9O88©zO=«Ë!µÖüY¨³ªÍy9ûÒ1 úôÚ»M?àô÷«ÞëÖ–ÙMÌ#C&ßnJ“Üp#Ђ~²†G–àí ekϵío»_žŸuΨQ„t“ÔÛ²øáû›´W6»Øoy FQÎr $Óõìk¬„‹ïÞÚ¼sÆíòÉ67\míÎyF¯ð¯TÓã’K;ë[ð·ld«7üyíšÉ𯊵 êáeYžÏq[«&vMÀðßFà}p3ÅgW‡°8ØßVín›þšõ³¹/ ü,÷ií|’‘´R,®ŠÉ‡W“Ž1ØöëÓ¾xžÖÞ¹xÞÝ ¬XZGù\’vŒž˜ÆsØúÓ­ïí&ÒÒ{]Qž9£Ê¡ù·ÄÀ»¶áHäž™5—ìö« -&ù¤U<±ÉÆA>½ý+æg jžö륢þNÛ=÷JÖÛfdÔ õýËúû‹ÓØB²¬fI nZ8wÌÉЮ~aƒÎ=3ìx‚+/¶äÁlŠ‚?™Æü#8-œ\pqTZXtè%»»&ÚÝ#´ŠðÜ žã§Í’¼{p·ß{m>ÞycP¨’¼¢0ú(Rƒë^Ž ñó¼(»y%m´ÕÙ}ÊûékB1¨þÑ®,#Q)ó‡o1T©ÜÃ*Ž‹‚yö< b‰4×H€“ìÐ. ¤²9ÌŠ>„Žãøgšñ ¯Š~)¸ßå\ÛÛoBŒa·L²œg$‚Iã¯ZÈ—Æ~%”äë—È8â)Œcƒ‘Âàu9¯b%)ÞS²¿Ïïÿ 4Öºù}Z/[H%¤vÉ#Ì’x§†b © ³´tÜ{gn=iï%õªÇç]ܧ—! åw„SÓp ·VÈÏ¡?5Âcâb¥_ĤŠz¬—nàþÖΟñKÄöJé=ÌWèêT‹¸÷qÎჟ•q’zWUN«N/ØO^Ÿe|í¾©k{üõ4öV^ïù~G¹êzÂèº|·÷×[’Þ31†rpjg·n Æ0Ý}kåË‹‰nîe¹ËÍ+™ÏVbrOç]'‰¼o®xÎh`¹Ç*±ÙÚ!T$d/$žN>¼WqᯅZ9ÑÒO\ÜÛê1o&,-z ~^NCgNÕéá)ÒÊ©7‰¨¯'Õþ¯þ_¿Ehîþóâ €ï¬uÛûý*ÎK9ä.â-öv<²‘×h$àãúW%ö¯~«g-ÕõÀàG~>Zú¾Iš+(šM³ Û#9äl%ðc¬ ûÝ xÖKG´x®|¸¤Ï™O:Ê8Ã’qÉcÔä‚yÇNJyËŒTj¥&µOmztjÿ ?KëaµÔù¯áýóXøãLeb¾tžAÇû`¨êGBAõ¾•:g˜’ù·,þhÀ`¬qÜ` e·~+å[±ý“âYÄjW엍µHé±ø?Nõô>½âX<5 Ç©ÏѼM¶8cܪXŽÉ^r?¼IróÈS•ZmÇ›™5»òÚÚ7ïu«&|·÷•Ά >[©ÞXHeS$Œyà€ ÷ù²:ò2|óãDf? Z¼PD¶ÓßC(xÆ0|©ßR;ôMsÿ µ´ÔVi¬,͹›Ìxâi˜`¹,GAéÇlV§ÄýF×Yø§ê–‘:Ã=ò2³9n±ÉžØÏ@yÎWžæ±Ãàe„ÄÒN ]ïòêìú_Go'¦ŽÑ’_×õЯðR66þ!›ÑÄ gFMÙ— äžäqôÈ;ÿ eX<#%»Aö‰ãR¤ Í”Ž¹È G&¹Ÿƒ&á?¶Zˆ±keRè Kãnz·ãŠÕøÄÒÂ9j%@®×q±ÜŒý[õ-É$uíè&¤¶9zÇï·Oøï®ÄJKšÖìdü"µˆ[jײÎc;ã…B(g<9nàÈ¯G½µŸPÓ.´Éfâ¼FŽP 31 ‘ÏR}<3šä~ Ã2xVöî Dr Ç\›}Ý#S÷ÈÀëŽHÆI®à\OçKuäI¹†ó(”—GWî ñ³¹¸æ2¨›‹ºÚû%¾ýÖ_3ºNú¯ëúì|ÕÅÖ‰}y lM’ZËîTÿ á[ðÐñ/ˆ9Àû ¸ón3 Mòd‘÷ döª^.Êñް›BâîNp>cëÏçÍzïíôÏ YÍ%ª¬·ãÏ-*9Ü­ÂãhéŒc¾dÈêú¼Ë,. VŠ÷çeÿ n/¡¼äãõâ=‹xGQKx”|¹bÌŠD@2Œ 8'Ž àúƒŽ+áDÒ&¡¨"Œ§–Žr22 Ç·s]ŸÄ‹«ð%ÚÄ<¹ä’(×{e›HÀqÁç©Ç½`üŽÚõK饚9ƒÄ±€< –úƒú~ çðñO#­Í%iKKlµ¦¾F)'Iê¬Î+Ç(`ñ¾£œdÈ’` ™ºcßéé^ÿ i¸”Û\ý¡æhÔB«aq¸}ãÀÆ:ÜWƒ|FÛÿ BŒÇÀeaŸ-sÊ€:úW½ÜÝÜ<%$µ†%CóDªÀí%IÈÏʤ…ôäñÞŒ÷‘a0“ôŽÚë¤nŸoW÷0«e¶y'Å»aΗ2r’# Û°A^ý9ÉQÔõ=ù5¬£Öü.(Þ’M$~V«=éSÄFN½®©ÔWô»ÿ þHžkR‹ìÏ+µµžöê;khÚI¤m¨‹Ôš–âÖçJ¾_Z•’6 a”Èô> ÕÉaÕ<%®£2n bQŠå\tÈõUÿ ø»þ‹k15‚ÃuCL$ݹp P1=Oøýs¯^u éEJ”–éêŸê½5ýzy›jÛ³á›Ûkÿ ÚOcn±ÛÏîW;boºz{ãžüVÆ¡a£a5½äÎÂks¸J@?1è¿{$䑐=k”øsÖ^nŒ¦)ÝåXÃíùN1ØõÚOJë–xF÷h¸ Œ"Ž?x䜚ü³ì¨c*Fœ¯i;7~ñí׫Ðó¥Ë»3Ãü púw ‰°<Á%»ñž ÿ P+Û^ ¾Ye£ŽCÄŒ„/>˜>•á¶Ìm~&&À>M[hÈÈÿ [Ž•íd…RO@3^Ç(ʽ*¶ÖQZyßþ 1Vº}Ñç?¼O4Rh6R€ª£í¡ûÙ a‚3ß·Õ ü=mRÍ/µ9¤‚0ÑC¼Iè:cŽsÛ¾™x£ÆÐ¬ªÍöˢ샒W$•€Å{¨ÀPG ÀÀàŸZìÍ1RÉ0´ðxEË9+Éÿ ^rEÕ—±Š„70l¼áË@û.' ¼¹Žz€N3úUÉ<3á×*?²¬‚ä†"Ùc=p íÛ'¡ª1ñ"økJ†HÒ'»Ÿ+ oÏN¬Ã9 dÙãÜדÏâÍ~æc+j·Jzâ7(£ðW]•晍?nê´º6åwéåç÷N•ZŠíž›¬|?Ðõ?Ñ-E…®³ÇV$~X¯/…õ x‘LˆÑÜÚÈ7¦pzãÜüë½ðÄ^õtÝYËÍ7ÉÖÕ8ÏUe# #€r=sU¾/é’E§jRC4mxNÝ´9†íuá»›V‘ ZI€­×cr1Ÿpzsøf»¨åV‹ìû`qËLÊIã?\~¼³áËC©êhªOîO»‘ÃmçÛçút×¢x“Z}?Üê#b-¤X7õ Äò gž zzbº3œm*qvs·M=íúéw}¿&Úª°^Ö×µÏ(ø‡â†Öµƒenñý†×åQáYûœ÷ÇLœôÎNk¡ð‡¼/µ¸n0æÉ0¬ƒ‚üîÉÆvŒw®Sáö”š¯‹-üÕVŠØÙ[$`(9cqƒÔ_@BëqûÙ`Ýæ­0;79È?w<ó |ÙÜkßÌ1±Ëã ¿ìÒ»ðlìï«ÓnªèèrP´NÏš&Žéö Ù¸÷æ°~-_O'‰`°!RÚÚÝ%]Ø%þbß1'¿ÿ X՝áOöÎŒ·‹¬+Åæ*ÛÛ™0¤ƒOÍÔ `u¯¦ÂaèÐÃÓ«‹¨Ô¥µœ¿¯ÉyÅÙ.oÔôŸ Úx&(STðݽ¦õ] ’ÒNóÁäÈùr3í·žÚ[™ƒ¼veÈ÷ÞIõÎGlqÎ=M|«gsªxÅI6 ]Z·Îªä,¨zŒŽÄ~#ØŠúFñiÉqc©éÐD>S딑 GñŽ1éÐ^+ Ëi;Ô„µVÕú»i¯ÈÒ-ZÍ]òܘ®ì` bÛÙ¥_/y(@÷qÐúg Ô÷W0.Ø› 6Ò© r>QƒŒ0+Èîzb¨É+I0TbNñ"$~)ÕÒ6Þ‹{0VÆ27œWWñcÄcX×íôûyKZéðªc'iQ¿¯LaWŠŸS\·Š“źʸ…ôÙÂí|öÀÇåV|!¤ÂGâÛ[[’ï 3OrÙËPY¹=Î1õ5öåTžÑè Ú64/üö?Zëžk}¬¶éào፾á}3“ü]8Éæ¿´n²Žš_6¾pœ)2?úWÓÚ¥¾¨iWúdŽq{*ª1rXŒd…m»‰äcô¯–dâ•ã‘Jº¬§¨#¨® §,df«8ÉÅßN¾hˆ;îÓ=7áùpën®É 6ûJžO2^œÐò JÖø¥²ã›Ò6Ü·‰!wbÍ‚¬O©»õ¬ÿ ƒP=Ä:â¤-&ÙŽ ` È9 r9íϧzë> XÅ7ƒ5X–krÑ¢L 7€ìw}ÑŸNHëŒüþ:2†á¼+u·á÷N/Û'Ðç~ߘô«ëh!ónRéeQ´6QÛÿ èEwëÅÒ|¸Yqó1uêyùzð8 ƒŠù¦Ò;¹ä6öi<'ü³„[íZhu½ ùÍ¡g‚>r¯׊îÌx}bñ2“­k꣧oø~›hTèóËWò4|ki"xßQ˜Ï6øÀLnß‚0 ¹Æ{±–¶Öe#¨27È@^Ìß.1N¾œyç€õ†ñeé·Õã†çQ°€=­Ì©ºB€Ø8<‚ÃSõ®ùcc>×Ú .Fr:žÝGæ=kÁâ,^!Fž ¬,àµ}%¶«îõ¹†"r²ƒGœüYÕd?aÑÍY®49PyU ÷þ!žxÅm|/‚ãNð˜¼PcûTÒ,¹/Ý=FkÏ|u¨¶«â녏{¤m¢]Û¾ïP>®XãÞ½iÓÁ¾ ‰'¬–6ß¼(„ï— í!úÙäzôë^–:œ¨å|,_¿&š×]uÓѵÛô4’j”bž§x‘Æ©ã›á,‚[Ô ÎÞ= ŒËæ ÀùYÁ?ŽïÚ¼?ÁªxºÕÛ,°1¸‘¿ÝäãØ¯v…@¤åq½ºã œàûââ·z8Xýˆþz~—û»™âµj=Ž â~ãáh@'h¼F#·Üp?ŸëQü-løvépx»cŸø…lxâÃûG·‰¶ø”L£©%y?¦úõÆü-Õ¶¥y`Òl7>q’2üA?•F}c‡jB:¸Jÿ +§¹¿¸Q÷°ív=VÑìu[Qml%R7a×IèTõéŽx¬ ?†š7 1†îã-ˆã’L¡lŽ0OÓ=ÅuˆpÇ•¼3ÛùÒ¶W/!|’wŽw^qÔ×Ïaó M8Q¨ãÑ?ëï0IEhÄa¸X•`a ?!ÐñùQ!Rä ÂžqŽžÝO`I0ÿ J“y|ñ!Îã@99>þ8–+éáu…!ù—ä ʰ<÷6’I®z ÅS„¾)Zþ_Öýµ×ËPåOwø÷þ*üïænÖùmØÝûþ¹=>¦½öî×Jh]¼ç&@§nTŒ6IT Àõ^Fxð7Å3!Ö·aÛ$þÿ ¹ã5îIo:ȪmËY[’8ÇӾlj*òû¢¥xõ¾¼ú•åk+\ð¯ HÚoŽl•Ûk,¯ ç²²cõÅ{²Z\ ´ìQ åpzŽ3Ôð}ÿ Jð¯XO¡øÎé€hÙ¥ûLdŒ`““ù6Gá^ÃáÝ^Ë[Ñb¾YåŒÊ»dŽ4 †2§,;ÿ CQÄ´¾°¨c–±”mºV{«ßÕýÄW\ÖŸ‘çŸ,çMRÆí“l-ƒn~ë©ÉÈê Ü?#Ž•¹ðãSÒ¥ÐWNíà½;ãž)™ÎSÈ9cóLj뵿Å«iÍk¨ió­¶X‚7÷ƒ€yãnyÏŽëÞ Öt`×À×V's$È9Ú:ä{wÆEk€«†Çàc—â$éÎ.éí~Ýëk}ÅAÆpörÑ¢‡Šl¡ÑüSs‹¨‰IÝ„óÀ×wñ&eºðf™pŒÆ9gŽTø£lñëÀçŽ NkÊUK0U’p ï^¡ãÈ¥´ø{£ÙHp`’ØåbqÏ©äó^Æ: Ž' ÊóM«õz+ß×ó5Ÿ»('¹­ð¦C„$˜Å¢_ºÈI?»^äã'ñêzž+ë€ñ-½»´}¡Ë*õ?.xÇ^1ŽMyǸ&“—L–îëöâ7…' bqéÎGé]˪â1$o²¸R8Ã`.q€}sÖ¾C9­8cêÆÞíïóòvÓòùœÕfÔÚéýu­èÖ·Ú Å‚_¤³ÜۺƑߝ”àרý:׃xPþÅÕî-/üØmnQìïGΊÙRqê=>¢½õnæ·r!—h`+’;ò3È<“Û©éšóŸx*÷V¹¸×tÈiˆßwiÔÿ |cŒñÏ®3Ö½̰‰Ë Qr©ö½®¼ÛoÑÙZÅÑ«O൯ýw8;k›ÿ x†;ˆJa;‘º9÷÷R+¡ñgŽí|Iáë{ôáo2ʲ9 029ÉÏLí\‰¿¸Ÿb˜ "Bv$£&#ßiê>=ªª©f  ’N ëí>¡N­XW­~5×úíø\‰»½Ï^ø(—wÖú¥¤2íŽÞXæÁ$ °eÈ888^nÝë²ñÝÔ^ ÖÚ9Q~Ëå7ï DC¶ÑµƒsËÇè9®Wáþƒ6‡£´·°2\Ý:ÈÑ?(#¨'$õèGJ¥ñW\ÿ ‰E¶—¸™g˜ÌÀ¹;Pv ú±ÎNs·ëŸ’–"Ž/:té+ûË]öJöÓM»ëø˜*‘•^Uý—êd|‰åñMæÔÝ‹23å™6æHùÛ‚ëüñ^…ñ1¢oêûÑEØ.õ7*ÅHtÎp{g<·Á«+¸c¿¿pÓ¾Æby=8É_ÄsÆk¬ñB\jÞÔì••Ë[9Píb‹Bヅ =9­3§ð§LšÛáÖšÆæXÌÞdÛP.0\ãïÛ0?™úJ¸™Ë ”•œº+=<µI£¦í¯õêt¬d‹T¬P=ËFêT>ÍØØ@Ï9<÷AQÌ×»Õ¡xùk",JÎæù±Éç$œŽŸZWH®¯"·UÌQ ’ÙÈ]ÅXg<ã ߨg3-Üqe€0¢¨*Œ$܃ ’Sû 8㎼_/e'+Ï–-èÓ¶¶Õíß[·ÙÙ½î쏗¼sk%§µxä‰â-pÒeÆCrú ôσžû=”šÅô(QW‚Õd\ƒæ. \àö¹¯F½°³½0M>‘gr÷q+œ¶NïºHO— ¤ ܥݭ”n·J|ÆP6Kµc=Isó}Ò çGš)a=—#vK›åoK§ßóٍ¤¶¿õú…ÄRÚ[Ësöټˏ•Ë ópw®qœŒ·Ø ùÇâ‹ý‡ãKèS&ÞvûD Aù‘É9 ŒîqÅ} $SnIV[]ѐ´Ó}ØÜ¾A Ü|½kÅþÓ|E Mu R¼.I¼¶däò‚ÃkÆ}ðy¹vc iUœZ…­Õõ»z¾÷¿n¦*j-É­/àœHã\y5 Û ß™ó0— äŸnzôã#Ô¯,†¥ÚeÔ÷ÜÅ´„“'c…<íÝ€<·SŠ¥k§Ã¢éÆÆÙna‚8–=«ʪ[Ÿ™°pNî02z“ÔÙ–K8.È’Þî(vƒ2®@ äÈûãçžxäÇf¯ˆu¹yUÕîýWšÙ|›ëÒ%Q^í[æ|éo5ZY•^{96ˆY‚§v*x>âº_|U¹Ö´©tûMÒÂ9PÇ#«£#€ éÉñ‘ƒÍz/‰´-į¹°dd,Б›p03ƒœ{ç9=+ Ûᧇ¬¦[‡‚ê婺¸#±ß=³ý¿•Õµjñ½HÙh›Û[§ÚýÊöô÷{˜?ô÷·Ô.u©–_%còcAÀ˜’ }0x9Î>žñÇáÍ9,ahï¦Ì2òÓ ñÛAäry$V²Nð ]=$Ž ‚#Ù‚1ƒƒødõMax‡ÂÖ^!±KkÛ‘ «“Çó²FN8+ëÎ{Ò¼oí§[«ÕMRoËeç×[_m/¦¦k.kôgŽxsSÓ´ý`êzªÜÜKo‰cPC9ÎY‰#§^üý9¹âïÞx£Ë·Ú`±‰‹¤;³–=ÏaôÕAð‚÷kêÁNBéÎælcõö®£Fð†ô2Ò¬]ßÂK$ÓÜ®•”/ÊHàã$ä ¸÷ëf¹Oµúâ“”’²ø­è´µþöjçNü÷üÌ¿ xNïFÒd»¼·h®îT9ŽAµÖ>qÁçÔœtïÒ»\ȶÎîcÞäîó3¶@#ÉIÎ ÔñW.<´’¥–ÑÑ€ÕšA‚ ;†qÓë‚2q ÒÂó$# Çí‡ !Ë}Õ9ÈÎÑÉã=;ŒÇÎuñ+ÉûÏ¥öíeÙ+$úíÜ娯'+êZH4ƒq¶FV‹gïŒ208ÆÌ)íб>M|÷âÍã¾"iì‹¥£Jd´™OÝç;sÈúr+ÜäˆË)DŒ¥šF°*3Õ”d {zÔwºQ¿·UžÉf†~>I+ŒqÔ`ð3œ“Ü×f]œTÁÔn4“ƒø’Ýßõ_«*5šzGCÊ,þ+ê1ò÷O¶¸cœºb2yÇ;cùÕ£ñh¬›áÑŠr¤ÝäNBk¥—á—†gxšX/쑘hŸ*Tçn =û㦠2|(ð¿e·ºÖ$ ýìŸ!'åΰyîî+×öœ=Y:²¦ÓÞ×iü’—ü -BK™£˜›âÆ¡&véðõ-ûÉY¹=Onj¹ø¯¯yf4·±T Pó`çœ7={×mÃ/ ¢˜ZÚòK…G½¥b„’G AãÜœ*í¯Ã¿ IoæI¦NU8‘RwÈã;·€ Û×ëÒ”1Y •£E»ÿ Oyto¢<£Áö·šï,䉧ûA¼sû»Nò}¹üE{ÜÖªò1’õÞr0â}ÎØ#>à/8ïéÎ~—áÍ#ñÎlí§³2f'h”?C÷YËdð:qëõÓ·‚ïeÄ© ÔÈØÜRL+žAÎ3¼g=åšó³Œt3 ÑQ¦ùRÙßE®¼±w_;þhš’Sirÿ ^ˆã¼iੇ|RòO„m°J/“$·l“ ÇÓ¿ÿ [ÑŠÆ“„†Õø>cFÆ6Ø1ƒ– àz7Ldòxäüwá‹ÝAXùO•Úý’é®ähm­ •NÀ±ÌTÈç ƒ‘I$pGž:‚ÄbêW¢®œ´|­¦­nÍ>¶ÖÏ¢§ÎÜ¢ºö¹•%ÄqL^öÛ KpNA<ã¡ …î==ª¸óffËF‡yÌcÉ ©ç$ð=ñÏ­YþÊ’Ú]—¥‚¬‚eDïÎH>Ÿ_ÌTP™a‰ch['çÆÜò7a‡?w°Ïn§âÎ5”’¨¹uÚÛ|´ÓÓc§{O—ü1•ªxsÃZ…ÊÏy¡Ã3¸Ë2Èé» ‘ƒÎ äžÜðA§cáOéúÛ4ý5-fŒï„ù¬ûô.Ç Üsž•Ò¾•wo<¶Ÿ"¬¡º|£ î2sÇ¡éE²ÉFѱrU°dÜ6œ¨ mc†Îxë׺Þ'0²¡Rr„{j¾í·è›µ÷)º·å–‹î2|I®Y¼ºÍË·–ÃÆà㍣'óÆxƒOÆÞ&>\lóÌxP Xc¸ì Sþ5§qà/ê>#žÞW¸if$\3 ® ûÄ“ùŽÕê¾ð<Ó‹H¶óÏ" å·( á‘€:ã†8Ï=+ꨬUA×ÃËÚT’ÑÞöù¥¢]{»ms¥F0\ÑÕ—ô}&ÛB´ƒOŽÚ+›xíÄÀ1 ,v± žIëíZ0ǧ™3 í2®0ทp9öÝÔž)ÓZËoq/Ú“‘L ²ŒmùŽÓ9§[Û#Ä‘\ÞB¬Çs [;à à«g‚2ôòªœÝV§»·¯/[uó½õÛï¾ /šÍ}öüÿ «=x»HŸÂÞ.™ ÌQùŸh´‘#a$‚'¡u<Š›Æ>2>+ƒLSiöwµFó1!eg`£åœ ÷ëÛö}Á¿ÛVÙêv $¬ƒ|,s÷z€ð΃¨x÷ÅD\ÜŒÞmåÔ„ ˆ o| :{ÇÓ¶–òÁn!´0Ål€, ƒ ( ÛŒŒ c¶rsšæ,4‹MÛOH!@¢ ÇŽ„`å²9ÝÃw;AÍt0®¤¡…¯ØÄ.Àì클ƒ‘ßñ5Í,Óëu-ÈÔc¢KÃÓ£òÖ̺U.õL¯0…%2È—"~x ‚[`có±nHàŽyàö™¥keˆìŒÛFç{(Ø©†`Jã#Žwg<“:ÚÉ;M ^\yhûX‡vB·÷zrF?§BÊÔ/s<ÐÈB)Û± ·ÍÔwç5Âã:så§e{mѤï«Òíh—]Wm4âí¿ùþW4bC3¶ª¾Ùr$ pw`àädzt!yŠI„hÂîàM)!edŒm'æ>Ç?wzºK­ìcŒ´¯Ìq6fp$)ãw¡éUl`µ»ARAˆÝÕgr:äŒgƒéé[Ôö±”iYs5Ýï«ÙG—K=þF’æMG«óÿ `ŠKɦuOQ!ÕåŒ/ÎGÞ`@ËqÕzdõâ«Ê/Ö(ƒK´%ŽbMü åÜŸö—>¤óŒŒV‘°„I¢Yž#™¥ùÏÊ@8 œgqöö5ª4vד[¬(q cò¨À!FGaÁõõ¯?§†¥ÏU½í¿WªZ$úyú½Žz×§Éþ?>Ã×È•6°{™™ŽÙ.$`­ÎUœ…çè ' ¤r$1Ø(y7 ðV<ž:È  ÁÎMw¾Â'Øb§øxb7gãО½óÉÊë²,i„Fȹ£§8ãä½k¹¥¦ê/ç{ïê驪2œ/«ü?¯Ô›ìñÜ$þeýœRIåŒg9Ác’zrrNO bÚi¢ ѺË/$,“ª¯Ýä;Œ× ´<ÛÑn³IvŸb™¥ nm–ÄŸ—nÝÀãŽ3ëÍG,.öó³˜Ù£¹u ÊÌrŠ[<±!@Æ:c9ÅZh ì’M5ÄìÌ-‚¼ëÉùqŽGì9¬á ;¨A-ž—évþÖ–^ON·Ô”ŸEý}ú×PO&e[]ÒG¸˜Ûp ƒÃà/Ë·8ûÀ€1ž@¿ÚB*²­¼ñì8@p™8Q“žÆH'8«I-%¸‚ F»“åó6°Uù|¶Ú¸ã ò^Äw¥ŠÖK–1ÜÝK,Žddlí²0PÀü“×ükG…¯U«·¶–´w¶ŽÍ¾©yÞú[Zös•¯Á[™6° ¨¼ÉVæq·,# ìãï‘×8îry®A››¨,ãc66»Ë´ã'æÉù?t}¢æH--Òá"›|ˆ¬[í  7¶ö#¸9«––‹$,+Ëqœ\Êø c€yê^ݸÄa°«™B-9%«×®‹V´w~vÜTéꢷþ¼ˆ%·¹• ’[xç•÷2gØS?6åÀÚ õ9É#š@÷bT¸º²C*3Bá¤òÎA9 =úU§Ó"2Ãlá0iÝIc‚2Î@%öç94ùô»'»HÄ¥Ô¾@à Tp£šíx:úÊ:5eºßMý×wµ›Ó_+šº3Ýyvÿ "ºÇ<ÂI>Õ 1G·Ë«È«É# àÈÇ øp Jv·šæDûE¿›†Ë’NFr2qŸ½ÇAÜšu•´éí#Ħ8£2”Ú2Ã/€[ÎTr;qŠz*ý’Îþ(≠;¡TÆâ›;ºÿ àçœk‘Þ­8¾Uª¾íé{^×IZéwÓkXÉûÑZo¯_øo×È¡¬ â–ÞR§2„‚Àœü½ùç® SVa†Âüª¼±D‘ŒísŸàä|ä2 æ[‹z”¯s{wn„ÆmáóCO+†GO8Ïeçåº`¯^¼ðG5f{Xžä,k‰<á y™¥voÆ éÛõëI=œ1‹éíÔÀÑ)R#;AÂncäŽ:tÏ#¶TkB.0Œ-ÖÞZÛgumß}fÎJÉ+#2êÔP£žùÈÅi¢%œ3P*Yƒò‚Aì“Ž2r:ƒÐúñi­RUQq‰H9!”={~¼ “JŽV¥»×²m.ÛߺiYl¾òk˜gL³·rT• ’…wHÁ6ä`–Î3ùÌ4Øe³†&òL‘•%clyîAÂäà0 žüç$[3uŘpNOÀÉ=† cï{rYK ååä~FÁ •a»"Lär1Ó¯2Äõæ<™C•.fÕ»è¥~½-¿g½Â4¡{[ør¨¶·Žõäx¥’l®qpwÇ»8ärF \cޏܯÓ-g‚yciÏÀ¾rÎwèØÈ#o°Á9ã5¢šfÔxÞæfGusÏÌJÿ µ×œ/LtãÅT7²¶w,l ɳ;”eúà·¨çîŒsÜgTÃS¦­^ '~‹®›¯+k÷ZÖd©Æ*Ó[Ü«%Œk0ŽXƒ”$k#Ȩ P2bv‘ƒŸáÇ™ÆÕb)m$É*8óLE‘8'–ÜN Úyàúô­+{uº±I'wvš4fÜr íì½=úuú sFlìV$‘ö†Hсù€$§ õ=½¸«Ž] :Ž+•¦ïmRþ½l´îÊT#nkiøÿ _ðÆT¶7Ò½ºÒ£Î¸d\ã8=yãŽÜäR{x]ZâÚé#¸r²#»ÎHÆ6õ ç® ÎFkr;sºÄ.&;só± Ç9êH÷ýSšÕ­tÐU¢-n­ Ì| vqœ„{gŒt§S.P‹’މ_[;m¥Þ­ZýRûÂX{+¥úü¼ú•-àÓ7!„G"“´‹žƒnrYXã¸îp éœ!Ó­oP̏tÑ (‰Þ¹é€sÓ#GLçÕšÑnJý¡!‘Tä#“ß?îýp}xÇ‚I¥Õn#·¸–y'qó@r[ Êô÷<ÔWÃÓ¢áN¥4ԝ’I&ݼ¬¬¼ÞºvéÆ FQV~_ÒüJÖÚt¥¦Xá3BÄP^%ÈÎW-×c¡ú©¤·Iþèk¥š?–UQåIR[’O 5x\ÉhÆI¶K4«2ùªŠŒ<¼óœçØ`u«‚Í.VHä € Ëgfx''9ÆI#±®Z8 sISºku¢ßÞ]úk»Jößl¡B.Ü»ÿ MWe °·Ž%šêɆ¼»Âù³´œ O¿cÐÓÄh©"ÛÜÏ.ÖV ’3nüÄmnq[ŒòznšÖ>J¬òˆæ…qýØP Ž:ä7^0yëWšÍ_79äoaÈ °#q0{ää×mœy”R{vÒÞ¶ÚÏe¥“ÚÆÐ¥Ì®—õýjR •íç›Ìb„+J yÜØÙ•Ç]¿Ôd þËOL²”9-Œ—õÃc'æÝלçÚ²ìejP“½ âù°¨†ðqòädЃÉäÖÜj÷PÇp“ÍšŠå«‘î <iWN­smª»¶vÓz5»ûì:Rs\Ðßôû×uÔÿÙ