From 65972716d47ba1ffde7304ea49bdb4e00a1a11ed Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 14 Jun 2008 12:21:47 -0700 Subject: [PATCH] Rationalize settings system. Unfortunately, this means you will lose most of your stored settings (Except the conversion defaults and the database location). Please spend a moment restoring them. --- src/calibre/__init__.py | 31 ++++--- src/calibre/gui2/__init__.py | 31 +++---- src/calibre/gui2/dialogs/config.py | 25 +++--- src/calibre/gui2/dialogs/fetch_metadata.py | 4 +- src/calibre/gui2/dialogs/lrf_single.py | 5 +- src/calibre/gui2/dialogs/lrf_single.ui | 28 ++---- src/calibre/gui2/dialogs/metadata_single.py | 2 +- src/calibre/gui2/dialogs/password.py | 8 +- src/calibre/gui2/jobs.py | 3 +- src/calibre/gui2/library.py | 6 +- src/calibre/gui2/lrf_renderer/main.py | 7 +- src/calibre/gui2/main.py | 18 ++-- src/calibre/library/cli.py | 2 +- upload.py | 54 ++++++++---- windows_installer.py | 94 +-------------------- 15 files changed, 114 insertions(+), 204 deletions(-) diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index 32a883b93f..6145c68f35 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -15,7 +15,7 @@ from optparse import OptionParser as _OptionParser from optparse import IndentedHelpFormatter from logging import Formatter -from PyQt4.QtCore import QSettings, QVariant, QUrl, QByteArray +from PyQt4.QtCore import QSettings, QVariant, QUrl, QByteArray, QString from PyQt4.QtGui import QDesktopServices from calibre.translations.msgfmt import make @@ -429,14 +429,10 @@ def singleinstance(name): class Settings(QSettings): - def __init__(self): + def __init__(self, name='calibre2'): QSettings.__init__(self, QSettings.IniFormat, QSettings.UserScope, - 'kovidgoyal.net', 'calibre') + 'kovidgoyal.net', name) - def migrate(self, settings): - for key in settings.allKeys(): - self.setValue(key, settings.value(key, QVariant())) - def get(self, key, default=None): key = str(key) if not self.contains(key): @@ -451,11 +447,24 @@ class Settings(QSettings): self.setValue(str(key), QVariant(QByteArray(val))) _settings = Settings() -if not _settings.get('migrated from QSettings'): - _settings.migrate(QSettings('KovidsBrain', 'libprs500')) - _settings.set('migrated from QSettings', True) - _settings.sync() +if not _settings.get('rationalized'): + __settings = Settings(name='calibre') + dbpath = os.path.join(os.path.expanduser('~'), 'library1.db').decode(sys.getfilesystemencoding()) + dbpath = unicode(__settings.value('database path', + QVariant(QString.fromUtf8(dbpath.encode('utf-8')))).toString()) + cmdline = __settings.value('LRF conversion defaults', QVariant(QByteArray(''))).toByteArray().data() + + _settings.set('database path', dbpath) + if cmdline: + cmdline = cPickle.loads(cmdline) + _settings.set('LRF conversion defaults', cmdline) + _settings.set('rationalized', True) + try: + os.unlink(unicode(__settings.fileName())) + except: + pass + _spat = re.compile(r'^the\s+|^a\s+|^an\s+', re.IGNORECASE) def english_sort(x, y): ''' diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 78015dcd91..91ae9f0d57 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -83,17 +83,12 @@ class TableView(QTableView): def read_settings(self): - self.cw = str(Settings().value(self.__class__.__name__ + ' column widths', QVariant('')).toString()) - try: - self.cw = tuple(int(i) for i in self.cw.split(',')) - except ValueError: - self.cw = None + self.cw = Settings().get(self.__class__.__name__ + ' column widths') def write_settings(self): settings = Settings() - settings.setValue(self.__class__.__name__ + ' column widths', - QVariant(','.join(str(self.columnWidth(i)) - for i in range(self.model().columnCount(None))))) + settings.set(self.__class__.__name__ + ' column widths', + tuple([int(self.columnWidth(i)) for i in range(self.model().columnCount(None))])) def restore_column_widths(self): if self.cw and len(self.cw): @@ -107,14 +102,10 @@ class TableView(QTableView): is hidden, if True it is shown. ''' if cols: - Settings().setValue(self.__class__.__name__ + ' visible columns', - QVariant(repr(cols))) + Settings().set(self.__class__.__name__ + ' visible columns', cols) else: - cols = qstring_to_unicode(Settings().value(self.__class__.__name__ + ' visible columns', - QVariant('')).toString()) - if cols: - cols = eval(cols) - else: + cols = Settings().get(self.__class__.__name__ + ' visible columns') + if not cols: cols = [True for i in range(self.model().columnCount(self))] for i in range(len(cols)): @@ -217,7 +208,7 @@ _sidebar_directories = [] def set_sidebar_directories(dirs): global _sidebar_directories if dirs is None: - dirs = Settings().value('frequently used directories', QVariant([])).toStringList() + dirs = Settings().get('frequently used directories', []) _sidebar_directories = [QUrl.fromLocalFile(i) for i in dirs] class FileDialog(QObject): @@ -251,7 +242,7 @@ class FileDialog(QObject): self.fd.setModal(modal) self.fd.setFilter(ftext) self.fd.setWindowTitle(title) - state = settings.value(name, QVariant()).toByteArray() + state = settings.get(self.dialog_name, QByteArray()) if not self.fd.restoreState(state): self.fd.setDirectory(os.path.expanduser('~')) osu = [i for i in self.fd.sidebarUrls()] @@ -259,7 +250,7 @@ class FileDialog(QObject): QObject.connect(self.fd, SIGNAL('accepted()'), self.save_dir) self.accepted = self.fd.exec_() == QFileDialog.Accepted else: - dir = settings.value(self.dialog_name, QVariant(os.path.expanduser('~'))).toString() + dir = settings.get(self.dialog_name, os.path.expanduser('~')) self.selected_files = [] if mode == QFileDialog.AnyFile: f = qstring_to_unicode( @@ -284,7 +275,7 @@ class FileDialog(QObject): self.selected_files.append(f) if self.selected_files: self.selected_files = [qstring_to_unicode(q) for q in self.selected_files] - settings.setValue(self.dialog_name, QVariant(os.path.dirname(self.selected_files[0]))) + settings.set(self.dialog_name, os.path.dirname(self.selected_files[0])) self.accepted = bool(self.selected_files) @@ -299,7 +290,7 @@ class FileDialog(QObject): def save_dir(self): if self.fd: settings = Settings() - settings.setValue(self.dialog_name, QVariant(self.fd.saveState())) + settings.set(self.dialog_name, self.fd.saveState()) def choose_dir(window, name, title): diff --git a/src/calibre/gui2/dialogs/config.py b/src/calibre/gui2/dialogs/config.py index f94706e7cc..8c1c7fe23d 100644 --- a/src/calibre/gui2/dialogs/config.py +++ b/src/calibre/gui2/dialogs/config.py @@ -3,7 +3,7 @@ __copyright__ = '2008, Kovid Goyal ' import os from PyQt4.QtGui import QDialog, QMessageBox, QListWidgetItem, QIcon -from PyQt4.QtCore import QVariant, SIGNAL, QStringList, QTimer, Qt, QSize +from PyQt4.QtCore import SIGNAL, QTimer, Qt, QSize from calibre import islinux, Settings from calibre.gui2.dialogs.config_ui import Ui_Dialog @@ -24,18 +24,15 @@ class ConfigDialog(QDialog, Ui_Dialog): self.db = db self.current_cols = columns settings = Settings() - path = qstring_to_unicode(\ - settings.value("database path", - QVariant(os.path.join(os.path.expanduser('~'),'library1.db'))).toString()) + path = settings.get('database path') self.location.setText(os.path.dirname(path)) self.connect(self.browse_button, SIGNAL('clicked(bool)'), self.browse) self.connect(self.compact_button, SIGNAL('clicked(bool)'), self.compact) - dirs = settings.value('frequently used directories', QVariant(QStringList())).toStringList() - rn = bool(settings.value('use roman numerals for series number', - QVariant(True)).toBool()) - self.timeout.setValue(settings.value('network timeout', QVariant(5)).toInt()[0]) + dirs = settings.get('frequently used directories', []) + rn = settings.get('use roman numerals for series number', True) + self.timeout.setValue(settings.get('network timeout', 5)) self.roman_numerals.setChecked(rn) self.directory_list.addItems(dirs) self.connect(self.add_button, SIGNAL('clicked(bool)'), self.add_dir) @@ -58,7 +55,7 @@ class ConfigDialog(QDialog, Ui_Dialog): self.filename_pattern = FilenamePattern(self) self.metadata_box.layout().insertWidget(0, self.filename_pattern) - icons = settings.value('toolbar icon size', QVariant(self.ICON_SIZES[0])).toSize() + icons = settings.get('toolbar icon size', self.ICON_SIZES[0]) self.toolbar_button_size.setCurrentIndex(0 if icons == self.ICON_SIZES[0] else 1 if icons == self.ICON_SIZES[1] else 2) self.show_toolbar_text.setChecked(settings.get('show text in toolbar', True)) @@ -84,14 +81,14 @@ class ConfigDialog(QDialog, Ui_Dialog): def accept(self): settings = Settings() - settings.setValue('use roman numerals for series number', QVariant(self.roman_numerals.isChecked())) - settings.setValue('network timeout', QVariant(self.timeout.value())) + settings.set('use roman numerals for series number', bool(self.roman_numerals.isChecked())) + settings.set('network timeout', int(self.timeout.value())) path = qstring_to_unicode(self.location.text()) self.final_columns = [self.columns.item(i).checkState() == Qt.Checked for i in range(self.columns.count())] - settings.setValue('toolbar icon size', QVariant(self.ICON_SIZES[self.toolbar_button_size.currentIndex()])) + settings.set('toolbar icon size', self.ICON_SIZES[self.toolbar_button_size.currentIndex()]) settings.set('show text in toolbar', bool(self.show_toolbar_text.isChecked())) pattern = self.filename_pattern.commit() - settings.setValue('filename pattern', QVariant(pattern)) + settings.set('filename pattern', pattern) if not path or not os.path.exists(path) or not os.path.isdir(path): d = error_dialog(self, _('Invalid database location'), _('Invalid database location ')+path+_('
Must be a directory.')) @@ -102,7 +99,7 @@ class ConfigDialog(QDialog, Ui_Dialog): else: self.database_location = os.path.abspath(path) self.directories = [qstring_to_unicode(self.directory_list.item(i).text()) for i in range(self.directory_list.count())] - settings.setValue('frequently used directories', QVariant(self.directories)) + settings.set('frequently used directories', self.directories) QDialog.accept(self) class Vacuum(QMessageBox): diff --git a/src/calibre/gui2/dialogs/fetch_metadata.py b/src/calibre/gui2/dialogs/fetch_metadata.py index 0967a91bb8..9a64c8dc42 100644 --- a/src/calibre/gui2/dialogs/fetch_metadata.py +++ b/src/calibre/gui2/dialogs/fetch_metadata.py @@ -76,7 +76,7 @@ class FetchMetadata(QDialog, Ui_FetchMetadata): self.timeout = timeout QObject.connect(self.fetch, SIGNAL('clicked()'), self.fetch_metadata) - self.key.setText(Settings().value('isbndb.com key', QVariant('')).toString()) + self.key.setText(Settings().get('isbndb.com key', '')) self.setWindowTitle(title if title else 'Unknown') self.tlabel.setText(self.tlabel.text().arg(title if title else 'Unknown')) @@ -106,7 +106,7 @@ class FetchMetadata(QDialog, Ui_FetchMetadata): _('You must specify a valid access key for isbndb.com')) return else: - Settings().setValue('isbndb.com key', QVariant(self.key.text())) + Settings().set('isbndb.com key', str(self.key.text())) args = ['isbndb'] if self.isbn: diff --git a/src/calibre/gui2/dialogs/lrf_single.py b/src/calibre/gui2/dialogs/lrf_single.py index 1929282770..e5df43a673 100644 --- a/src/calibre/gui2/dialogs/lrf_single.py +++ b/src/calibre/gui2/dialogs/lrf_single.py @@ -106,9 +106,8 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog): def load_saved_global_defaults(self): - cmdline = Settings().value('LRF conversion defaults', QVariant(QByteArray(''))).toByteArray().data() + cmdline = Settings().get('LRF conversion defaults') if cmdline: - cmdline = cPickle.loads(cmdline) self.set_options_from_cmdline(cmdline) def set_options_from_cmdline(self, cmdline): @@ -382,7 +381,7 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog): cmdline.extend([u'--cover', self.cover_file.name]) self.cmdline = [unicode(i) for i in cmdline] else: - Settings().setValue('LRF conversion defaults', QVariant(QByteArray(cPickle.dumps(cmdline)))) + Settings().set('LRF conversion defaults', cmdline) QDialog.accept(self) class LRFBulkDialog(LRFSingleDialog): diff --git a/src/calibre/gui2/dialogs/lrf_single.ui b/src/calibre/gui2/dialogs/lrf_single.ui index cf27b2fd7d..9fd3bee155 100644 --- a/src/calibre/gui2/dialogs/lrf_single.ui +++ b/src/calibre/gui2/dialogs/lrf_single.ui @@ -122,8 +122,8 @@ 0 0 - 622 - 454 + 642 + 458 @@ -435,8 +435,8 @@ 0 0 - 622 - 454 + 642 + 458 @@ -701,8 +701,8 @@ 0 0 - 622 - 454 + 642 + 458 @@ -825,8 +825,8 @@ 0 0 - 622 - 454 + 642 + 458 @@ -923,16 +923,6 @@ - - - - 0 - 0 - 100 - 30 - - - @@ -981,7 +971,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Candara'; font-size:11pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"></p></body></html> diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index 26e2058a96..af2c97a3be 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -144,7 +144,7 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog): self.edit_tags) QObject.connect(self.remove_series_button, SIGNAL('clicked()'), self.remove_unused_series) - self.timeout = float(Settings().value('network timeout', QVariant(5)).toInt()[0]) + self.timeout = float(Settings().get('network timeout', 5)) self.title.setText(db.title(row)) isbn = db.isbn(self.id, index_is_id=True) if not isbn: diff --git a/src/calibre/gui2/dialogs/password.py b/src/calibre/gui2/dialogs/password.py index 2710834a57..9248f313d4 100644 --- a/src/calibre/gui2/dialogs/password.py +++ b/src/calibre/gui2/dialogs/password.py @@ -16,8 +16,8 @@ class PasswordDialog(QDialog, Ui_Dialog): self.setupUi(self) settings = Settings() - un = settings.value(name+': un', QVariant('')).toString() - pw = settings.value(name+': pw', QVariant('')).toString() + un = settings.get(name+': un', u'') + pw = settings.get(name+': pw', u'') self.gui_username.setText(un) self.gui_password.setText(pw) self.sname = name @@ -38,6 +38,6 @@ class PasswordDialog(QDialog, Ui_Dialog): def accept(self): settings = Settings() - settings.setValue(self.sname+': un', QVariant(self.gui_username.text())) - settings.setValue(self.sname+': pw', QVariant(self.gui_password.text())) + settings.set(self.sname+': un', unicode(self.gui_username.text())) + settings.set(self.sname+': pw', unicode(self.gui_password.text())) QDialog.accept(self) diff --git a/src/calibre/gui2/jobs.py b/src/calibre/gui2/jobs.py index da9c9fa36a..d135b7d6cd 100644 --- a/src/calibre/gui2/jobs.py +++ b/src/calibre/gui2/jobs.py @@ -258,8 +258,7 @@ class JobManager(QAbstractTableModel): desc = kwargs.pop('job_description', '') if args and hasattr(args[0], 'append') and '--verbose' not in args[0]: args[0].append('--verbose') - priority = self.PRIORITY[str(Settings().value('conversion job priority', - QVariant('Normal')).toString())] + priority = self.PRIORITY[Settings().get('conversion job priority', 'Normal')] job = self.create_job(ConversionJob, desc, slot, priority, callable, *args, **kwargs) return job.id diff --git a/src/calibre/gui2/library.py b/src/calibre/gui2/library.py index 1130a141c5..afea0aa190 100644 --- a/src/calibre/gui2/library.py +++ b/src/calibre/gui2/library.py @@ -5,6 +5,7 @@ from datetime import timedelta, datetime from operator import attrgetter from collections import deque from math import cos, sin, pi +from itertools import repeat from PyQt4.QtGui import QTableView, QProgressDialog, QAbstractItemView, QColor, \ QItemDelegate, QPainterPath, QLinearGradient, QBrush, \ QPen, QStyle, QPainter, QLineEdit, QApplication, \ @@ -114,8 +115,7 @@ class BooksModel(QAbstractTableModel): self.load_queue = deque() def read_config(self): - self.use_roman_numbers = bool(Settings().value('use roman numerals for series number', - QVariant(True)).toBool()) + self.use_roman_numbers = Settings().get('use roman numerals for series number', True) def set_database(self, db): @@ -594,7 +594,7 @@ class DeviceBooksModel(BooksModel): base = self.map if refinement else self.sorted_map result = [] for i in base: - q = ['', self.db[i].title, self.db[i].authors, '', ', '.join(self.db[i].tags)] + ['' for j in range(10)] + q = ['', self.db[i].title, self.db[i].authors, '', ', '.join(self.db[i].tags)] + list(repeat('', 10)) if OR: add = False for token in tokens: diff --git a/src/calibre/gui2/lrf_renderer/main.py b/src/calibre/gui2/lrf_renderer/main.py index 2d927242cc..edab6b0c1b 100644 --- a/src/calibre/gui2/lrf_renderer/main.py +++ b/src/calibre/gui2/lrf_renderer/main.py @@ -103,13 +103,13 @@ class Main(MainWindow, Ui_MainWindow): def configure(self, triggered): - opts = cPickle.loads(str(Settings().value('ebook viewer options', QVariant(cPickle.dumps(self.opts))).toString())) + opts = Settings().get('LRF ebook viewer options', self.opts) d = Config(self, opts) d.exec_() if d.result() == QDialog.Accepted: opts.white_background = bool(d.white_background.isChecked()) opts.hyphenate = bool(d.hyphenate.isChecked()) - Settings().setValue('ebook viewer options', QVariant(cPickle.dumps(opts))) + Settings().set('LRF ebook viewer options', opts) def set_ebook(self, stream): self.progress_bar.setMinimum(0) @@ -279,8 +279,7 @@ def option_parser(): return parser def normalize_settings(parser, opts): - settings = Settings() - saved_opts = cPickle.loads(str(settings.value('ebook viewer options', QVariant(cPickle.dumps(opts))).toString())) + saved_opts = Settings().get('LRF ebook viewer options', opts) for opt in parser.option_list: if not opt.dest: continue diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 4720cd17c2..b3a00c4415 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -4,7 +4,7 @@ import os, sys, textwrap, collections, traceback, shutil, time from xml.parsers.expat import ExpatError from functools import partial from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \ - QVariant, QThread, QString, QSize, QUrl + QVariant, QThread, QSize, QUrl from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox, \ QToolButton, QDialog, QDesktopServices from PyQt4.QtSvg import QSvgRenderer @@ -18,7 +18,7 @@ from calibre.devices.interface import Device from calibre.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \ initialize_file_icon_provider, question_dialog,\ pixmap_to_data, choose_dir, ORG_NAME, \ - qstring_to_unicode, set_sidebar_directories, \ + set_sidebar_directories, \ SingleApplication, Application, available_height from calibre.gui2.cover_flow import CoverFlow, DatabaseImages from calibre.library.database import LibraryDatabase @@ -979,7 +979,7 @@ class Main(MainWindow, Ui_MainWindow): newloc = self.database_path self.database_path = newloc settings = Settings() - settings.setValue("database path", QVariant(self.database_path)) + settings.set('database path', self.database_path) except Exception, err: traceback.print_exc() d = error_dialog(self, _('Could not move database'), unicode(err)) @@ -1087,13 +1087,11 @@ class Main(MainWindow, Ui_MainWindow): def read_settings(self): settings = Settings() - settings.beginGroup("Main Window") + settings.beginGroup('Main Window') geometry = settings.value('main window geometry', QVariant()).toByteArray() self.restoreGeometry(geometry) settings.endGroup() - dbpath = os.path.join(os.path.expanduser('~'), 'library1.db').decode(sys.getfilesystemencoding()) - self.database_path = qstring_to_unicode(settings.value("database path", - QVariant(QString.fromUtf8(dbpath.encode('utf-8')))).toString()) + self.database_path = settings.get('database path') if not os.access(os.path.dirname(self.database_path), os.W_OK): error_dialog(self, _('Database does not exist'), _('The directory in which the database should be: %s no longer exists. Please choose a new database location.')%self.database_path).exec_() self.database_path = choose_dir(self, 'database path dialog', 'Choose new location for database') @@ -1102,10 +1100,10 @@ class Main(MainWindow, Ui_MainWindow): if not os.path.exists(self.database_path): os.makedirs(self.database_path) self.database_path = os.path.join(self.database_path, 'library1.db') - settings.setValue('database path', QVariant(QString.fromUtf8(self.database_path.encode('utf-8')))) + settings.set('database path', self.database_path) set_sidebar_directories(None) - set_filename_pat(qstring_to_unicode(settings.value('filename pattern', QVariant(get_filename_pat())).toString())) - self.tool_bar.setIconSize(settings.value('toolbar icon size', QVariant(QSize(48, 48))).toSize()) + set_filename_pat(settings.get('filename pattern', get_filename_pat())) + self.tool_bar.setIconSize(settings.get('toolbar icon size', QSize(48, 48))) self.tool_bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon if settings.get('show text in toolbar', True) else Qt.ToolButtonIconOnly) diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index b13a7a3680..b1824ac278 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -330,7 +330,7 @@ For help on an individual command: %%prog command --help return 1 command = eval('command_'+args[1]) - dbpath = unicode(Settings().value('database path', QVariant(os.path.expanduser('~/library1.db'))).toString()) + dbpath = Settings().get('database path') return command(args[2:], dbpath) diff --git a/upload.py b/upload.py index 2d70570542..e3241c1417 100644 --- a/upload.py +++ b/upload.py @@ -1,11 +1,14 @@ #!/usr/bin/python -import tempfile -import sys, os, shutil, time +import sys, os, shutil, time, tempfile, socket sys.path.append('src') import subprocess from subprocess import check_call as _check_call from functools import partial #from pyvix.vix import Host, VIX_SERVICEPROVIDER_VMWARE_WORKSTATION +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.connect(('google.com', 0)) +HOST=s.getsockname()[0] +PROJECT=os.path.basename(os.getcwd()) from calibre import __version__, __appname__ @@ -15,6 +18,15 @@ DOCS = PREFIX+"/htdocs/apidocs" USER_MANUAL = PREFIX+'/htdocs/user_manual' HTML2LRF = "src/calibre/ebooks/lrf/html/demo" TXT2LRF = "src/calibre/ebooks/lrf/txt/demo" +BUILD_SCRIPT ='''\ +#!/bin/bash +cd ~/build && \ +rsync -avz --exclude docs --exclude .bzr --exclude .build --exclude build --exclude dist --exclude "*.pyc" --exclude "*.pyo" rsync://%(host)s/work/%(project)s . && \ +cd %(project)s && \ +mkdir -p build dist && \ +rm -rf build/* dist/* && \ +python %%s +'''%dict(host=HOST, project=PROJECT) check_call = partial(_check_call, shell=True) #h = Host(hostType=VIX_SERVICEPROVIDER_VMWARE_WORKSTATION) @@ -29,15 +41,23 @@ def installer_name(ext): return 'dist/%s-%s.%s'%(__appname__, __version__, ext) return 'dist/%s-%s-i686.%s'%(__appname__, __version__, ext) +def start_vm(vm, ssh_host, build_script, sleep): + vmware = ('vmware', '-q', '-x', '-n', vm) + subprocess.Popen(vmware) + t = tempfile.NamedTemporaryFile(suffix='.sh') + t.write(build_script) + t.flush() + print 'Waiting for VM to startup' + time.sleep(sleep) + print 'Trying to SSH into VM' + subprocess.check_call(('scp', t.name, ssh_host+':build-'+PROJECT)) + def build_windows(): installer = installer_name('exe') vm = '/vmware/Windows XP/Windows XP Professional.vmx' - vmware = ('vmware', '-q', '-x', '-n', vm) - subprocess.Popen(vmware) - print 'Waiting for Windows to boot up...' - time.sleep(75) - print 'Trying to ssh into the Windows SSH server' - subprocess.check_call(('ssh', 'windows', '/usr/local/bin/build-calibre', os.path.basename(os.getcwd()))) + start_vm(vm, 'windows', BUILD_SCRIPT%'windows_installer.py', 75) + subprocess.check_call(('ssh', 'windows', '/bin/bash', '~/build-'+PROJECT)) + subprocess.check_call(('scp', 'windows:build/%s/dist/*.exe'%PROJECT, 'dist')) if not os.path.exists(installer): raise Exception('Failed to build installer '+installer) subprocess.Popen(('ssh', 'windows', 'shutdown', '-s', '-t', '0')) @@ -47,11 +67,9 @@ def build_osx(): installer = installer_name('dmg') vm = '/vmware/Mac OSX/Mac OSX.vmx' vmware = ('vmware', '-q', '-x', '-n', vm) - subprocess.Popen(vmware) - print 'Waiting for OS X to boot up...' - time.sleep(120) - print 'Trying to ssh into the OS X SSH server' - subprocess.check_call(('ssh', 'osx', '/Users/kovid/bin/build-calibre', os.path.basename(os.getcwd()))) + start_vm(vm, 'osx', BUILD_SCRIPT%'osx_installer.py', 120) + subprocess.check_call(('ssh', 'osx', '/bin/bash', '~/build-'+PROJECT)) + subprocess.check_call(('scp', 'windows:build/%s/dist/*.dmg'%PROJECT, 'dist')) if not os.path.exists(installer): raise Exception('Failed to build installer '+installer) subprocess.Popen(('ssh', 'osx', 'sudo', '/sbin/shutdown', '-h', 'now')) @@ -62,9 +80,9 @@ def _build_linux(): tbz2 = os.path.join(cwd, installer_name('tar.bz2')) SPEC="""\ import os -HOME = '%s' +HOME = '%(home)s' PYINSTALLER = os.path.expanduser('~/build/pyinstaller') -CALIBREPREFIX = HOME+'/work/calibre' +CALIBREPREFIX = HOME+'/work/%(project)s' CLIT = '/usr/bin/clit' PDFTOHTML = '/usr/bin/pdftohtml' LIBUNRAR = '/usr/lib/libunrar.so' @@ -180,12 +198,12 @@ for folder in EXTRAS: subprocess.check_call('cp -rf %%s .'%%folder, shell=True) print 'Building tarball...' -tf = tarfile.open('%s', 'w:bz2') +tf = tarfile.open('%(tarfile)s', 'w:bz2') for f in os.listdir('.'): tf.add(f) -"""%('/mnt/hgfs/giskard/', tbz2) +"""%dict(home='/mnt/hgfs/giskard/', tarfile=tbz2, project=PROJECT) os.chdir(os.path.expanduser('~/build/pyinstaller')) open('calibre/calibre.spec', 'wb').write(SPEC) try: @@ -200,7 +218,7 @@ def build_linux(): subprocess.Popen(vmware) print 'Waiting for linux to boot up...' time.sleep(75) - check_call('ssh linux make -C /mnt/hgfs/giskard/work/calibre all egg linux_binary') + check_call('ssh linux make -C /mnt/hgfs/giskard/work/%s all egg linux_binary'%PROJECT) check_call('ssh linux sudo poweroff') def build_installers(): diff --git a/windows_installer.py b/windows_installer.py index 6608effa16..da53aa7f7e 100644 --- a/windows_installer.py +++ b/windows_installer.py @@ -424,96 +424,6 @@ SectionEnd else: os.remove(path) -class WixInstaller(object): - ''' - Make a .msi installer. Can't get the driver installation to play well with - an existing installation of the connect USB driver. Pick this up again when - libusb1.dll is released based on winusb. - ''' - TEMPLATE=\ -r''' - - - - - - - - - Privileged - - 1 - http://calibre.kovidgoyal.net - appicon.ico - - - - - %(py2exefiles)s - - - - - - - - - - - - - - - - - - - - - - - - - ''' - CANDLE=r'C:\wix\candle.exe ' - LIGHT=r'C:\wix\light.exe -out %s -loc C:\wix\WixUI_en-us.wxl %s c:\wix\wixui.wixlib "C:\Program Files\Driver Installation Tools 2.01\DIFxApp\English-US\WiXLib\x86\DIFxApp.wixlib"' - - def __init__(self, py2exe_dir, dest_dir='dist'): - self.py2exe_dir = py2exe_dir - self.dest_dir = dest_dir - filelist = [] - print self.py2exe_dir - for root, dirs, files in os.walk(self.py2exe_dir): - for name in files: - path = os.path.abspath(os.path.join(root, name)) - filelist.append(path) - component = "\n" - counter = 0 - for path in filelist: - entry = ''%\ - (counter, counter, path, os.path.basename(path)) - component += entry + "\n" - counter += 1 - component += '' - self.installer = self.TEMPLATE%dict(appname=APPNAME, version=VERSION, - py2exefiles=component) - - def build(self): - f = open('installer.wxs', 'w') - f.write(self.installer) - f.close() - subprocess.check_call(self.CANDLE + ' ' + f.name, shell=True) - subprocess.check_call(self.LIGHT%(os.path.join(self.dest_dir, APPNAME + '-' + VERSION + '.msi'), - ' installer.wixobj'), shell=True) - - os.remove('installer.wxs') - os.remove('installer.wixobj') - class BuildEXE(build_exe): manifest_resource_id = 0 @@ -559,9 +469,9 @@ class BuildEXE(build_exe): subprocess.check_call(['mingw32-make', '-f', 'Makefile']) shutil.copyfile('pictureflow.pyd', os.path.join(dd, 'pictureflow.pyd')) os.chdir('..') - shutil.rmtree('.build') + shutil.rmtree('.build', True) os.chdir('..') - shutil.rmtree('.build') + shutil.rmtree('.build', True) finally: os.chdir(cwd)