home *** CD-ROM | disk | FTP | other *** search
- import errno
- import os
- import os.path
- import re
- import shutil
- import sys
- import site
- import zipfile
-
- __tag__ = '$Name: BOOT_0_2_11 $'[7:-2]
-
- VERSION = None
- if __tag__.startswith('BOOT_'):
- parts = __tag__.split('_')
- if len(parts) == 4:
- try:
- parts = map(int, parts[1:])
- except ValueError:
- pass
- else:
- VERSION = tuple(parts)
-
- # Initial startup file:
- #
- # Parse options
- # Import platform-dependent startup code
- # Find highest-version cc package zip file
- # Add to path
- # Put references to info that we determined on startup into magnet module
- # Jump into magnet main
- #
- # Catch any exceptions that occur before we can install the
- # more-capable handler or after shutdown and report them to the user
- # and try to report them to us
-
- MIN_VERSION = (0, 7, 0)
- DEFAULT_BUG_ADDRESS = 'jytebugs@janrain.com'
- DEFAULT_APP_NAME = 'Jyte'
- DEFAULT_MAIL_SERVER = 'smtp.janrain.com'
- DEFAULT_BUG_REPORT_TEXT = \
- """An error occurred that this application could not
- handle. Sending a bug report will make this less
- frequent in the future."""
- BAKED_SEARCH_FILENAME = 'startup.dat'
-
- name_pattern = re.compile('^magnet-(\d+)\.(\d+)\.(\d+).zip$')
- name_s = 'magnet-%d.%d.%d.zip'
-
- def getVersions(dirname):
- try:
- names = os.listdir(dirname)
- except OSError, e:
- if e.errno != errno.ENOENT:
- raise
- else:
- for name in names:
- match = name_pattern.match(name)
- if match is not None:
- version = tuple(map(int, match.groups()))
- if version >= MIN_VERSION:
- yield version
-
- def findZip(*locations):
- """Find zip files that should contain magnet releases.
-
- Prefer to get zip files from the directories given in the order
- that they are given. Prefer to get zip files with higher version
- numbers. If the file is not found in the first location passed in,
- then copy the file into that directory so it is there next time."""
-
- # Get the lib path and make sure that it exists
- lib_path = locations[0]
- if not os.path.exists(lib_path):
- os.makedirs(lib_path)
-
- # Sort by version number first, then by the order that locations
- # were passed to us, so that we use the highest-numbered version
- # from the first location in the locations list.
- versions = []
- for tie_breaker, location in enumerate(locations):
- for version in getVersions(location):
- versions.append((version, tie_breaker, location))
-
- versions.sort()
- versions.reverse()
-
- full_names = []
- for version, unused_tie_breaker, location in versions:
- basename = name_s % version
- source_name = os.path.join(location, basename)
-
- if not zipfile.is_zipfile(source_name):
- print >>sys.stderr, 'Skipping %s - not a valid zip file' % (
- source_name,)
-
- continue
-
- if location != lib_path:
- full_name = os.path.join(lib_path, basename)
-
- if not os.path.exists(full_name):
- print >>sys.stderr, 'Moving file to lib directory: %s' % (
- source_name)
-
- scratch_name = full_name + '-scratch'
-
- # Copy, then move since move is atomic.
- # This prevents getting a partial copy.
- shutil.copyfile(source_name, scratch_name)
- os.rename(scratch_name, full_name)
-
- else:
- full_name = source_name
-
- if full_name not in full_names:
- full_names.append(full_name)
-
- return full_names
-
- def getMagnet():
- """Attempt to get the magnet module"""
- try:
- from cc import magnet
- except ImportError:
- return None
- else:
- return magnet
-
- def getVersion():
- """Get a version string"""
- try:
- from cc import VERSION as magnet_version
- except ImportError:
- return '(unknown)'
- else:
- return magnet_version
-
- def sendErrorReport(text):
- """Attempt to send a bug report with contents text"""
- import smtplib
- from email.MIMEText import MIMEText
-
- boot_version = '(unknown)'
- if VERSION is not None:
- try:
- boot_version = '.'.join(map(str, VERSION))
- except ValueError:
- pass
-
- magnet = getMagnet()
- to_addr = getattr(magnet, 'BUG_ADDRESS', DEFAULT_BUG_ADDRESS)
- app_name = getattr(magnet, 'APP_NAME', DEFAULT_APP_NAME)
- mail_server = getattr(magnet, 'MAIL_SERVER', DEFAULT_MAIL_SERVER)
-
- addr_line = '%s Bugs <%s>' % (app_name, to_addr)
-
- msg = MIMEText(text)
- msg['Subject'] = '%s Crash' % (app_name,)
- msg['To'] = addr_line
- msg['From'] = addr_line
- msg['X-Magnet-Version'] = getVersion()
- msg['X-Magnet-Boot-Version'] = boot_version
-
- server = smtplib.SMTP(mail_server, smtplib.SMTP_PORT)
- server.sendmail(to_addr, [to_addr], msg.as_string())
- server.quit()
-
- def showError():
- """Show the user an error dialog
-
- that asks him if he wants to submit a bug report. Returns True if
- he does."""
-
- # It is necessary to have a QApplication instance to display a message box
- import qt
- if qt.QApplication.startingUp() or qt.QApplication.closingDown():
- unused_app = qt.QApplication([])
-
- magnet = getMagnet()
-
- app_name = getattr(magnet, 'APP_NAME', DEFAULT_APP_NAME)
- message_text = getattr(magnet, 'BUG_REPORT_TEXT', DEFAULT_BUG_REPORT_TEXT)
-
- choice = qt.QMessageBox.critical(
- None, # parent
- '%s Error' % (app_name,), # title
- message_text, # text
- "Send Report", # first button (choice 0) text
- "Don't Send Report") # second button (choice 1) text
-
- return (choice == 0)
-
- def setup():
- if os.name == 'nt':
- # set up win32xxx paths
- sys.path.append(site.here + r'\site-packages\win32')
- sys.path.append(site.here + r'\site-packages\win32\lib')
-
- def getPath():
- if os.name == 'nt':
- from win32com.shell import shell, shellcon
- app_data_path = shell.SHGetFolderPath(0, shellcon.CSIDL_APPDATA, 0, 0)
- return os.path.join(app_data_path.encode(), DEFAULT_APP_NAME)
- elif os.name == 'posix':
- home_dir = os.path.abspath(os.environ.get('HOME', os.getcwd()))
- return os.path.join(home_dir, ('.'+DEFAULT_APP_NAME).lower())
- else:
- raise RuntimeError, 'os not supported: %s' % (os.name,)
-
- def getSearchFile():
- d = os.path.split(__file__)[0]
- return os.path.join(d, BAKED_SEARCH_FILENAME)
-
- def getZipFiles(locations):
- return findZip(*locations)
-
- def bootstrap(options):
- setup()
- path = getPath()
- boot_path = os.path.abspath(os.path.dirname(__file__))
- locations = [os.path.join(path, 'lib'), boot_path]
- if options.path is not None and sys.platform != 'darwin':
- path = options.path
- locations.insert(0, os.path.join(path, 'lib'))
-
- print >>sys.stderr, 'Looking in', locations
-
- tried = []
- sys.path.insert(0, None)
- for zip_name in getZipFiles(locations):
- tried.append(zip_name)
- zip_file = zipfile.ZipFile(zip_name)
-
- sys.path[0] = zip_name
-
- try:
- import cc.magnet
- cc.magnet.BOOT_VERSION = VERSION
- cc.magnet.path = path
- cc.magnet.sendErrorReport = sendErrorReport
- cc.magnet.search_file = getSearchFile()
- import cc.magnet.main
- except ImportError:
- sys.excepthook(*sys.exc_info())
- print >>sys.stderr, 'File %s failed' % (zip_name,)
- continue
- else:
- break
- else:
- raise RuntimeError('Unable to find a good zip file after trying %r' % (
- tried,))
-
- print >>sys.stderr, 'Running from %s' % (zip_name,)
-
- def run(options):
- try:
- bootstrap(options)
- from cc.magnet import main
- main.start(log_level=options.log_level, console=options.console,
- data_path=options.data_path)
- except KeyboardInterrupt:
- pass
- except:
- try:
- import logging
- info = logging.Formatter().formatException(sys.exc_info())
- except:
- info = "Unhandled exception -- getting traceback failed"
-
- print >>sys.stderr, info
- try:
- send_report = showError()
- except:
- send_report = True
-
- if send_report:
- sendErrorReport(info)
-
- if __name__ == '__main__':
- import optparse
-
- parser = optparse.OptionParser()
-
- parser.add_option('-p', '--path', dest='path',
- help='Directory containing code files')
-
- parser.add_option('-d', '--data-path', dest='data_path',
- help='Directory containing data files')
-
- parser.add_option("-v", "--verbose", dest="console",
- action="store_true", default=False,
- help="Print log messages to the console")
-
- parser.add_option("-l", "--log-level",
- dest="log_level", default="info",
- choices=["debug",
- "info",
- "warning",
- "error",
- "critical"],
- help="Set logging level")
-
- (options, args) = parser.parse_args()
-
- if len(args):
- parser.error('This command takes no arguments')
-
- run(options)
-