home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / python2.6 / dist-packages / jockey / handlers.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  23.1 KB  |  662 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''Define some common abstract basic handler types.
  5.  
  6. These provide the common functionality for concrete handlers of different
  7. classes, like handlers for a kernel module, a driver package, a handler group,
  8. etc.
  9.  
  10. Custom concrete handlers need to fulfill the following requirements:
  11.  - __init__(self, backend) must take exactly one argument (a reference to a
  12.    Backend instance). All othe properties must be detected by the
  13.    constructor or changed with methods. These classes are instantiated
  14.    automatically, which is not possible with constructors which need more
  15.    arguments.
  16.  
  17.  - All handler types in this module have some abstract functions which need to
  18.    be implemented (see the documentation of the particular classes).
  19. '''
  20. import subprocess
  21. import os.path as os
  22. import sys
  23. import logging
  24. from gettext import gettext as _
  25. import detection
  26. from oslib import OSLib
  27.  
  28. class Handler:
  29.     '''Abstract basic handler.'''
  30.     
  31.     def __init__(self, backend, name, description = None, rationale = None):
  32.         '''Create a handler with given (human readable) name.
  33.         
  34.         Every handler should have a human readable name. A custom rationale and
  35.         a multi-line description can be given, too. Every handler gets a
  36.         reference to the currently used Backend so that it can request
  37.         installation of packages and other system changes.
  38.  
  39.         By default, available handlers are announced in
  40.         AbstractUI.check(). If you want to have a handler which is
  41.         available, but not announced that way, set self.annonuce to False.
  42.         '''
  43.         self._hwids = []
  44.         self._changed = False
  45.         self.backend = backend
  46.         self._name = name
  47.         self._description = description
  48.         self._rationale = rationale
  49.         self.license = None
  50.         self.announce = True
  51.         if not hasattr(self, '_free'):
  52.             self._free = None
  53.         
  54.         if hasattr(self, 'package') and self.package:
  55.             self._package_defaults()
  56.         else:
  57.             self.package = None
  58.         self.driver_vendor = None
  59.         self.version = None
  60.         self.repository = None
  61.         self._recommended = False
  62.  
  63.     
  64.     def _package_defaults(self):
  65.         '''Set fallback name/description/freeness from package.'''
  66.         if self.package:
  67.             if not (self._name) or self._description is None:
  68.                 (distro_name, distro_desc) = OSLib.inst.package_description(self.package)
  69.                 if not self._name:
  70.                     self._name = distro_name
  71.                 
  72.                 if self._description is None:
  73.                     self._description = distro_desc
  74.                 
  75.             
  76.         if self.package and self._free is None:
  77.             
  78.             try:
  79.                 self._free = OSLib.inst.is_package_free(self.package)
  80.             except (KeyError, ValueError):
  81.                 pass
  82.             except:
  83.                 None<EXCEPTION MATCH>(KeyError, ValueError)
  84.             
  85.  
  86.         None<EXCEPTION MATCH>(KeyError, ValueError)
  87.  
  88.     
  89.     def name(self):
  90.         '''Return one-line name of the handler (for human consumption).'''
  91.         self._package_defaults()
  92.         return self._name
  93.  
  94.     
  95.     def description(self):
  96.         '''Return multi-line description of the handler.'''
  97.         self._package_defaults()
  98.         return self._description
  99.  
  100.     
  101.     def id(self):
  102.         '''Return an unique identifier of the handler.
  103.  
  104.         This is used for specifying a handler with --enable/--disable on the
  105.         command line, and is mentioned in the --list output.
  106.         '''
  107.         if self.package:
  108.             i = 'pkg:' + self.package
  109.         else:
  110.             i = '%s:%s' % (str(self.__class__).split('.')[-1], self.name())
  111.         if self.driver_vendor:
  112.             i += ':' + self.driver_vendor.replace(' ', '_')
  113.         
  114.         return i
  115.  
  116.     
  117.     def rationale(self):
  118.         '''Return rationale as to why this driver might be enabled.
  119.         
  120.         Might return None if no rationale is available.
  121.         '''
  122.         return self._rationale
  123.  
  124.     
  125.     def changed(self):
  126.         '''Return if the module has been enabled/disabled at least once.'''
  127.         return self._changed
  128.  
  129.     
  130.     def can_change(self):
  131.         '''Check whether we can actually modify settings of this handler.
  132.  
  133.         This might not be the case if e. g. the user manually modified a
  134.         configuration file. Return an explanatory text if settings can not be
  135.         changed, or None if changing is ok.
  136.         '''
  137.         pass
  138.  
  139.     
  140.     def __str__(self):
  141.         if not self.free() or 'free':
  142.             pass
  143.         if not self.enabled() or 'enabled':
  144.             pass
  145.         return '%s([%s, %s, %s] %s)' % (self.id(), str(self.__class__).split('.')[-1], 'nonfree', 'disabled', self.name())
  146.  
  147.     
  148.     def free(self):
  149.         '''Return if the handler represents a free software driver.'''
  150.         if self._free is not None:
  151.             return self._free
  152.         raise NotImplementedError, 'subclasses need to implement this'
  153.  
  154.     
  155.     def enabled(self):
  156.         """Return if the handler is enabled.
  157.         
  158.         'Enabled' means that the user agreed to use this driver if it is
  159.         applicable.
  160.         """
  161.         if self.package:
  162.             return OSLib.inst.package_installed(self.package)
  163.         return True
  164.  
  165.     
  166.     def used(self):
  167.         '''Return if the handler is currently in use.'''
  168.         raise NotImplementedError, 'subclasses need to implement this'
  169.  
  170.     
  171.     def recommended(self):
  172.         '''Return if the version of a certain driver is recommended over others
  173.         when more than one driver flavour supports the same device.
  174.         
  175.         This method should return True only for the recommended version while
  176.         it will return False for any other compatible version. If only one
  177.         version of a driver is provided, then it should return False.
  178.         '''
  179.         return self._recommended
  180.  
  181.     
  182.     def available(self):
  183.         '''Return if the conditions to use this handler on the system are met.
  184.  
  185.         This usually means that the hardware for this driver is available, but
  186.         there might be hardware independent drivers, too.
  187.         
  188.         If this returns True or False, the answer is definitive and no further
  189.         detection, db querying, etc is performed. If this returns None, then
  190.         the handler cannot decide availability on its own; in that case it is
  191.         merely available in the handler pool, and an external driver database
  192.         (detection.DriverDB) is queried.
  193.         '''
  194.         if self.package:
  195.             if not (self.repository) or OSLib.inst.repository_enabled(self.repository):
  196.                 
  197.                 try:
  198.                     OSLib.inst.package_description(self.package)
  199.                     return None
  200.                 except ValueError:
  201.                     return False
  202.                 
  203.  
  204.             None<EXCEPTION MATCH>ValueError
  205.             return None
  206.         self.package
  207.         raise NotImplementedError, 'subclasses need to implement this'
  208.  
  209.     
  210.     def enable(self):
  211.         '''Allow the OS to use it if the hardware is available.
  212.         
  213.         If possible, the handler should be loaded, too. Return True if
  214.         immediately successful, or False if the system needs to be rebooted for
  215.         the changes to become effective.
  216.         '''
  217.         if self.repository:
  218.             OSLib.inst.add_repository(self.repository)
  219.         
  220.         if self.package:
  221.             self.backend.install_package(self.package)
  222.             if not OSLib.inst.package_installed(self.package):
  223.                 return True
  224.         
  225.         self._changed = True
  226.         return True
  227.  
  228.     
  229.     def disable(self):
  230.         '''Prevent the OS from using it even if the hardware is available.
  231.  
  232.         If possible, the handler should be unloaded, too. Return True if
  233.         immediately successful, or False if the system needs to be rebooted for
  234.         the changes to become effective.
  235.  
  236.         '''
  237.         if self.repository:
  238.             OSLib.inst.remove_repository(self.repository)
  239.         
  240.         if self.package:
  241.             self.backend.remove_package(self.package)
  242.             if OSLib.inst.package_installed(self.package):
  243.                 return None
  244.         
  245.         self._changed = True
  246.         return True
  247.  
  248.  
  249.  
  250. class HandlerGroup(Handler):
  251.     '''Perform operations on a group of handlers.
  252.  
  253.     A group should be provided if it makes little sense to present several very
  254.     similar handlers in the UI. For example, the three VMWare or the dozens of
  255.     commercial OSS drivers should be grouped.
  256.     '''
  257.     
  258.     def __init__(self, backend, name, id, description = None, rationale = None):
  259.         Handler.__init__(self, backend, name, description, rationale)
  260.         self._id = id
  261.         self.subhandlers = []
  262.  
  263.     
  264.     def id(self):
  265.         '''Return an unique identifier of the handler.'''
  266.         return self._id
  267.  
  268.     
  269.     def add(self, handler):
  270.         '''Add a subhandler.'''
  271.         self.subhandlers.append(handler)
  272.  
  273.     
  274.     def free(self):
  275.         '''Return if all subhandlers represent free software drivers.'''
  276.         for h in self.subhandlers:
  277.             if not h.free():
  278.                 return False
  279.         
  280.         return True
  281.  
  282.     
  283.     def enabled(self):
  284.         '''Return if all subhandlers are enabled.'''
  285.         for h in self.subhandlers:
  286.             if not h.enabled():
  287.                 return False
  288.         
  289.         return True
  290.  
  291.     
  292.     def used(self):
  293.         '''Return if any subhandler is used.'''
  294.         for h in self.subhandlers:
  295.             if h.used():
  296.                 return True
  297.         
  298.         return False
  299.  
  300.     
  301.     def available(self):
  302.         '''Return if the hardware for any subhandler is available.
  303.         
  304.         If all subhandlers return False, this returns False. If any subhandler
  305.         returns True, this returns True. Otherwise this returns None.
  306.         '''
  307.         all_false = True
  308.         for h in self.subhandlers:
  309.             a = h.available()
  310.             if a:
  311.                 return True
  312.             if a == None:
  313.                 all_false = False
  314.                 continue
  315.             a
  316.             if not a == False:
  317.                 raise AssertionError
  318.         
  319.         if all_false:
  320.             return False
  321.         return None
  322.  
  323.     
  324.     def enable(self):
  325.         '''Enable all subhandlers.'''
  326.         result = True
  327.         for h in self.subhandlers:
  328.             if h.enable():
  329.                 pass
  330.             result = result
  331.         
  332.         return result
  333.  
  334.     
  335.     def disable(self):
  336.         '''Disable all subhandlers.'''
  337.         result = True
  338.         for h in self.subhandlers:
  339.             if h.disable():
  340.                 pass
  341.             result = result
  342.         
  343.         return result
  344.  
  345.     
  346.     def changed(self):
  347.         '''Return if at least one subhandler has been enabled/disabled at
  348.         least once.'''
  349.         for h in self.subhandlers:
  350.             if h.changed():
  351.                 return True
  352.         
  353.         return False
  354.  
  355.     
  356.     def can_change(self):
  357.         '''Check whether we can actually modify settings of this handler.'''
  358.         if not self.subhandlers:
  359.             raise AssertionError
  360.         for h in self.subhandlers:
  361.             c = h.can_change()
  362.             if c:
  363.                 return c
  364.         
  365.  
  366.  
  367.  
  368. class KernelModuleHandler(Handler):
  369.     '''Handler for a kernel module.
  370.     
  371.     This class can be used as a standard handler for kernel modules (and in
  372.     fact detection.get_handlers() uses this as a default handler if there is no
  373.     custom one). Subclasses have to implement __init__() at least.
  374.     '''
  375.     _loaded_modules = None
  376.     
  377.     def __init__(self, backend, kernel_module, name = None, description = None, rationale = None):
  378.         """Create handler for a kernel module.
  379.         
  380.         If not given explicitly, the name is read from modinfo's 'description'
  381.         field.
  382.         """
  383.         self.module = kernel_module
  384.         self._modinfo = detection.get_modinfo(self.module)
  385.         if not name:
  386.             if not self._modinfo:
  387.                 raise AssertionError, 'kernel module %s exists' % self.module
  388.             name = '\n'.join(self._modinfo.get('description', [
  389.                 self.module]))
  390.         
  391.         Handler.__init__(self, backend, name, description, rationale)
  392.         self._do_rebind = True
  393.  
  394.     
  395.     def id(self):
  396.         '''Return an unique identifier of the handler.'''
  397.         i = 'kmod:' + self.module
  398.         if self.driver_vendor:
  399.             i += ':' + self.driver_vendor.replace(' ', '_')
  400.         
  401.         return i
  402.  
  403.     
  404.     def free(self):
  405.         '''Return if the handler represents a free software driver.'''
  406.         if self._free is not None:
  407.             return self._free
  408.         if not self._modinfo:
  409.             raise AssertionError, 'kernel module %s exists' % self.module
  410.         for l in self._modinfo.get('license', [
  411.             'unknown']):
  412.             if l in ('GPL', 'GPL v2', 'GPL and additional rights', 'Dual BSD/GPL', 'Dual MIT/GPL', 'Dual MPL/GPL', 'BSD'):
  413.                 return True
  414.         
  415.         return False
  416.  
  417.     
  418.     def enabled(self):
  419.         """Return if the handler is enabled.
  420.         
  421.         'Enabled' means that the user agreed to use this driver if it is
  422.         applicable.
  423.         """
  424.         if not OSLib.inst.module_blacklisted(self.module) and self._modinfo is not None:
  425.             pass
  426.         return Handler.enabled(self)
  427.  
  428.     
  429.     def used(self):
  430.         '''Return if the handler is currently in use.'''
  431.         if not self.module_loaded(self.module) and self.package is None:
  432.             pass
  433.         return OSLib.inst.package_installed(self.package)
  434.  
  435.     
  436.     def available(self):
  437.         '''Return if the conditions to use this handler on the system are met
  438.         (e. g. hardware for this driver is available).
  439.  
  440.         This defaults to None, because we usually want to delegate this to the
  441.         driver db. Subclasses are welcome to override this, of course.
  442.         '''
  443.         
  444.         try:
  445.             if Handler.available(self) == False:
  446.                 return False
  447.         except NotImplementedError:
  448.             pass
  449.  
  450.  
  451.     
  452.     def enable(self):
  453.         '''Allow the OS to use it if the hardware is available.
  454.         
  455.         This removes the module from the modprobe blacklist.
  456.         '''
  457.         Handler.enable(self)
  458.         OSLib.inst.blacklist_module(self.module, False)
  459.         subprocess.call([
  460.             OSLib.inst.modprobe_path,
  461.             self.module])
  462.         self._modinfo = detection.get_modinfo(self.module)
  463.         self.read_loaded_modules()
  464.         if self._do_rebind:
  465.             return self.rebind(self.module)
  466.  
  467.     
  468.     def disable(self):
  469.         '''Prevent the OS from using it even if the hardware is available.
  470.  
  471.         This adds the module to the modprobe blacklist.
  472.         '''
  473.         Handler.disable(self)
  474.         OSLib.inst.blacklist_module(self.module, True)
  475.         self._modinfo = detection.get_modinfo(self.module)
  476.         return False
  477.  
  478.     
  479.     def rebind(klass, module):
  480.         '''Re-bind all devices using the module.
  481.         
  482.         This is necessary for example to reload firmware. Return True on
  483.         success, or False if rebind failed for any device.
  484.         '''
  485.         drivers_dir = os.path.join(OSLib.inst.sys_dir, 'module', module, 'drivers')
  486.         if not os.path.isdir(drivers_dir):
  487.             logging.warning('%s does not exist, cannot rebind %s driver' % (drivers_dir, module))
  488.             return None
  489.         succeeded = True
  490.         for driver in os.listdir(drivers_dir):
  491.             driver_path = os.path.join(drivers_dir, driver)
  492.             for device in os.listdir(driver_path):
  493.                 if device == 'module' or not os.path.isdir(os.path.join(driver_path, device)):
  494.                     continue
  495.                 
  496.                 
  497.                 try:
  498.                     logging.debug('unbind/rebind on driver %s: device %s', driver_path, device)
  499.                     f = open(os.path.join(driver_path, 'unbind'), 'w')
  500.                     f.write(device)
  501.                     f.close()
  502.                     f = open(os.path.join(driver_path, 'bind'), 'w')
  503.                     f.write(device)
  504.                     f.close()
  505.                 continue
  506.                 except IOError:
  507.                     logging.warning('unbind/rebind for device %s on driver %s failed', device, driver_path, exc_info = True)
  508.                     succeeded = False
  509.                     continue
  510.                 
  511.  
  512.             
  513.         
  514.         return succeeded
  515.  
  516.     rebind = classmethod(rebind)
  517.     
  518.     def read_loaded_modules(klass):
  519.         '''Get the list of loaded kernel modules.'''
  520.         klass._loaded_modules = []
  521.         proc_modules = open(OSLib.inst.proc_modules)
  522.         
  523.         try:
  524.             for line in proc_modules:
  525.                 
  526.                 try:
  527.                     line = line[:line.index(' ')]
  528.                 except ValueError:
  529.                     pass
  530.  
  531.                 klass._loaded_modules.append(line.strip())
  532.         finally:
  533.             proc_modules.close()
  534.  
  535.  
  536.     read_loaded_modules = classmethod(read_loaded_modules)
  537.     
  538.     def module_loaded(klass, module):
  539.         '''Return if a module is currently loaded.'''
  540.         if klass._loaded_modules == None:
  541.             klass.read_loaded_modules()
  542.         
  543.         return module in klass._loaded_modules
  544.  
  545.     module_loaded = classmethod(module_loaded)
  546.  
  547.  
  548. class FirmwareHandler(KernelModuleHandler):
  549.     """Handler for an already available kernel module needing firmware.
  550.  
  551.     Subclasses need to extend enable() and implement disable() to do something
  552.     with the downloaded file (unpack it, put into the right directory, etc.).
  553.     This class' enable() function will deal with downloading it and the UI
  554.     progress reporting of the download.
  555.     """
  556.     
  557.     def __init__(self, backend, kernel_module, testfile, name = None, description = None, rationale = None, url = None, sha1sum = None, free = False):
  558.         """Create handler for a piece of firmware for a kernel module.
  559.         
  560.         The required argument 'url' specifies where the firmware can be
  561.         downloaded from. The optional 'sha1sum' argument provides a checksum of
  562.         the downloaded file. The file will not be installed if it does not
  563.         match.
  564.  
  565.         enabled() will return True iff the path in testfile exists.
  566.  
  567.         By default this handler assumes that the firmware is not free (since
  568.         otherwise the distribution could ship it together with the driver). You
  569.         can set 'free' to True for free firmware or to None to use the kernel
  570.         module's freeness.
  571.     
  572.         If not given explicitly, the name is read from modinfo's 'description'
  573.         field.
  574.         """
  575.         self.url = url
  576.         self.sha1sum = sha1sum
  577.         self._free = free
  578.         self.testfile = testfile
  579.         KernelModuleHandler.__init__(self, backend, kernel_module, name, description, rationale)
  580.  
  581.     
  582.     def id(self):
  583.         '''Return an unique identifier of the handler.'''
  584.         i = 'firmware:' + self.module
  585.         if self.driver_vendor:
  586.             i += ':' + self.driver_vendor.replace(' ', '_')
  587.         
  588.         return i
  589.  
  590.     
  591.     def free(self):
  592.         '''Return if the handler represents a free software driver.'''
  593.         if self._free is None:
  594.             return KernelModuleHandler.free(self)
  595.         return self._free
  596.  
  597.     
  598.     def enabled(self):
  599.         """Return if the handler is enabled.
  600.         
  601.         'Enabled' means that the user agreed to use this driver if it is
  602.         applicable.
  603.         """
  604.         if os.path.exists(self.testfile):
  605.             pass
  606.         return KernelModuleHandler.enabled(self)
  607.  
  608.     
  609.     def used(self):
  610.         '''Return if the handler is currently in use.'''
  611.         if self.enabled():
  612.             pass
  613.         return KernelModuleHandler.used(self)
  614.  
  615.     
  616.     def enable(self):
  617.         '''Allow the OS to use it if the hardware is available.
  618.         
  619.         This downloads the url and puts it into self.firmware_file. Subclasses
  620.         need to provide an actual implementation what to do with the file.
  621.         '''
  622.         raise NotImplementedError, 'FirmwareHandler is currently not implemented'
  623.         KernelModuleHandler.enable(self)
  624.  
  625.     
  626.     def disable(self):
  627.         '''Prevent the OS from using it even if the hardware is available.
  628.         
  629.         Implementation in subclasses need to remove the firmware files and call
  630.         KernelModuleHandler.disable().
  631.         '''
  632.         raise NotImplementedError, 'subclasses need to implement this'
  633.  
  634.  
  635.  
  636. class PrinterDriverHandler(Handler):
  637.     '''Handler for a printer driver.'''
  638.     
  639.     def id(self):
  640.         '''Return an unique identifier of the handler.
  641.  
  642.         This is used for specifying a handler with --enable/--disable on the
  643.         command line, and is mentioned in the --list output.
  644.         '''
  645.         if self.package:
  646.             i = 'printer:' + self.package
  647.         else:
  648.             i = 'printer:%s' % self.name()
  649.         if self.version:
  650.             i += ':' + str(self.version)
  651.         elif self.driver_vendor:
  652.             i += ':' + self.driver_vendor.replace(' ', '_')
  653.         
  654.         return i
  655.  
  656.     
  657.     def used(self):
  658.         '''Return if the handler is currently in use.'''
  659.         return self.enabled()
  660.  
  661.  
  662.