IGN:Easier development environment using the binary build on windows

This commit is contained in:
Kovid Goyal 2009-09-26 11:28:28 -06:00
parent 0c678d9f05
commit c9aeb3fd09
9 changed files with 318 additions and 321 deletions

View File

@ -6,7 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os, cStringIO, re import os
from setup import Command, __appname__ from setup import Command, __appname__
@ -17,6 +17,8 @@ class GUI(Command):
@classmethod @classmethod
def find_forms(cls): def find_forms(cls):
from calibre.gui2 import find_forms
return find_forms(cls.SRC)
forms = [] forms = []
for root, _, files in os.walk(cls.PATH): for root, _, files in os.walk(cls.PATH):
for name in files: for name in files:
@ -27,7 +29,8 @@ class GUI(Command):
@classmethod @classmethod
def form_to_compiled_form(cls, form): def form_to_compiled_form(cls, form):
return form.rpartition('.')[0]+'_ui.py' from calibre.gui2 import form_to_compiled_form
return form_to_compiled_form(form)
def run(self, opts): def run(self, opts):
self.build_forms() self.build_forms()
@ -53,38 +56,8 @@ class GUI(Command):
def build_forms(self): def build_forms(self):
from PyQt4.uic import compileUi from calibre.gui2 import build_forms
forms = self.find_forms() build_forms(self.SRC, info=self.info)
pat = re.compile(r'''(['"]):/images/([^'"]+)\1''')
def sub(match):
ans = 'I(%s%s%s)'%(match.group(1), match.group(2), match.group(1))
return ans
for form in forms:
compiled_form = self.form_to_compiled_form(form)
if not os.path.exists(compiled_form) or os.stat(form).st_mtime > os.stat(compiled_form).st_mtime:
self.info('\tCompiling form', form)
buf = cStringIO.StringIO()
compileUi(form, buf)
dat = buf.getvalue()
dat = dat.replace('__appname__', __appname__)
dat = dat.replace('import images_rc', '')
dat = dat.replace('from library import', 'from calibre.gui2.library import')
dat = dat.replace('from widgets import', 'from calibre.gui2.widgets import')
dat = dat.replace('from convert.xpath_wizard import',
'from calibre.gui2.convert.xpath_wizard import')
dat = re.compile(r'QtGui.QApplication.translate\(.+?,\s+"(.+?)(?<!\\)",.+?\)', re.DOTALL).sub(r'_("\1")', dat)
dat = dat.replace('_("MMM yyyy")', '"MMM yyyy"')
dat = pat.sub(sub, dat)
if form.endswith('viewer%smain.ui'%os.sep):
self.info('\t\tPromoting WebView')
dat = dat.replace('self.view = QtWebKit.QWebView(', 'self.view = DocumentView(')
dat += '\n\nfrom calibre.gui2.viewer.documentview import DocumentView'
dat += '\nQtWebKit'
open(compiled_form, 'wb').write(dat)
def clean(self): def clean(self):
forms = self.find_forms() forms = self.find_forms()

View File

@ -121,6 +121,9 @@ base = os.path.dirname(sys.executable.decode(fenc))
sys.resources_location = os.path.join(base, 'resources') sys.resources_location = os.path.join(base, 'resources')
sys.extensions_location = os.path.join(base, 'plugins') sys.extensions_location = os.path.join(base, 'plugins')
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
if dv and os.path.exists(dv):
sys.path.insert(0, os.path.abspath(dv))
del sys del sys
''' '''
@ -278,7 +281,9 @@ def main(args=sys.argv):
'packages' : ['PIL', 'lxml', 'cherrypy', 'packages' : ['PIL', 'lxml', 'cherrypy',
'dateutil', 'dns'], 'dateutil', 'dns'],
'excludes' : ["Tkconstants", "Tkinter", "tcl", 'excludes' : ["Tkconstants", "Tkinter", "tcl",
"_imagingtk", "ImageTk", "FixTk" "_imagingtk", "ImageTk",
"FixTk",
'PyQt4.uic.port_v3.proxy_base'
], ],
'dll_excludes' : ['mswsock.dll', 'tcl85.dll', 'dll_excludes' : ['mswsock.dll', 'tcl85.dll',
'tk85.dll'], 'tk85.dll'],

View File

@ -6,10 +6,9 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
Embedded console for debugging. Embedded console for debugging.
''' '''
import sys, os, re, shutil import sys, os
from calibre.utils.config import OptionParser from calibre.utils.config import OptionParser
from calibre.constants import iswindows, isosx from calibre.constants import iswindows, isosx
from calibre.libunzip import update
from calibre import prints from calibre import prints
def option_parser(): def option_parser():
@ -18,11 +17,6 @@ def option_parser():
Run an embedded python interpreter. Run an embedded python interpreter.
''') ''')
parser.add_option('-u', '--update-module', default=False,
action='store_true',
help='Update the specified module in the frozen library. '+
'Module specifications are of the form full.name.of.module path_to_module.py',
)
parser.add_option('-c', '--command', help='Run python code.', default=None) parser.add_option('-c', '--command', help='Run python code.', default=None)
parser.add_option('-e', '--exec-file', default=None, help='Run the python code in file.') parser.add_option('-e', '--exec-file', default=None, help='Run the python code in file.')
parser.add_option('-d', '--debug-device-driver', default=False, action='store_true', parser.add_option('-d', '--debug-device-driver', default=False, action='store_true',
@ -41,39 +35,17 @@ Run an embedded python interpreter.
parser.add_option('--pdfreflow', default=None, parser.add_option('--pdfreflow', default=None,
help='Path to PDF file to try and reflow. Output will be placed in ' help='Path to PDF file to try and reflow. Output will be placed in '
'current directory. ') 'current directory. ')
parser.add_option('-f', '--develop-from', default=None,
help=('Develop calibre from the specified path. '
'The path should point to the src sub-directory in the '
'calibre source tree.'))
return parser return parser
def update_zipfile(zipfile, mod, path): def develop_from(path):
if 'win32' in sys.platform: from calibre.gui2 import build_forms
print 'WARNING: On Windows Vista using this option may cause windows to put library.zip into the Virtual Store (typically located in c:\Users\username\AppData\Local\VirtualStore). If it does this you must delete it from there after you\'re done debugging).' print 'Compiling .ui forms...'
pat = re.compile(mod.replace('.', '/')+r'\.py[co]*') build_forms(path)
name = mod.replace('.', '/') + os.path.splitext(path)[-1]
update(zipfile, [pat], [path], [name])
def update_site_packages(sp, mod, path):
dest = os.path.join(sp, *mod.split('.'))+'.py'
shutil.copy2(path, dest)
def update_module(mod, path):
if not hasattr(sys, 'frozen'):
raise RuntimeError('Modules can only be updated in frozen installs.')
zp = None
if iswindows:
zp = os.path.join(os.path.dirname(sys.executable), 'library.zip')
elif getattr(sys, 'new_app_bundle', False):
update_site_packages(sys.site_packages, mod, path)
elif isosx:
zp = os.path.join(os.path.dirname(getattr(sys, 'frameworks_dir')),
'Resources', 'lib',
'python'+'.'.join(map(str, sys.version_info[:2])),
'site-packages.zip')
else:
zp = os.path.join(getattr(sys, 'frozen_path'), 'loader.zip')
if zp is not None:
update_zipfile(zp, mod, path)
else:
raise ValueError('Updating modules is not supported on this platform.')
def migrate(old, new): def migrate(old, new):
from calibre.utils.config import prefs from calibre.utils.config import prefs
@ -189,9 +161,6 @@ def main(args=sys.argv):
if opts.gui: if opts.gui:
from calibre.gui2.main import main from calibre.gui2.main import main
main(['calibre']) main(['calibre'])
elif opts.update_module:
mod, path = args[1:3]
update_module(mod, os.path.expanduser(path))
elif opts.command: elif opts.command:
sys.argv = args[:1] sys.argv = args[:1]
exec opts.command exec opts.command
@ -218,6 +187,8 @@ def main(args=sys.argv):
from calibre.utils.logging import default_log from calibre.utils.logging import default_log
opts2, args = px().parse_args(['xxxx', '-vvvv', opts.pdfreflow]) opts2, args = px().parse_args(['xxxx', '-vvvv', opts.pdfreflow])
run(opts2, opts.pdfreflow, default_log) run(opts2, opts.pdfreflow, default_log)
elif opts.develop_from is not None:
develop_from(opts.develop_from)
else: else:
from IPython.Shell import IPShellEmbed from IPython.Shell import IPShellEmbed
ipshell = IPShellEmbed() ipshell = IPShellEmbed()

View File

@ -525,3 +525,53 @@ def is_ok_to_use_qt():
gui_thread = QThread.currentThread() gui_thread = QThread.currentThread()
return gui_thread is QThread.currentThread() return gui_thread is QThread.currentThread()
def find_forms(srcdir):
base = os.path.join(srcdir, 'calibre', 'gui2')
forms = []
for root, _, files in os.walk(base):
for name in files:
if name.endswith('.ui'):
forms.append(os.path.abspath(os.path.join(root, name)))
return forms
def form_to_compiled_form(form):
return form.rpartition('.')[0]+'_ui.py'
def build_forms(srcdir, info=None):
import re, cStringIO
from PyQt4.uic import compileUi
forms = find_forms(srcdir)
if info is None:
from calibre import prints
info = prints
pat = re.compile(r'''(['"]):/images/([^'"]+)\1''')
def sub(match):
ans = 'I(%s%s%s)'%(match.group(1), match.group(2), match.group(1))
return ans
for form in forms:
compiled_form = form_to_compiled_form(form)
if not os.path.exists(compiled_form) or os.stat(form).st_mtime > os.stat(compiled_form).st_mtime:
info('\tCompiling form', form)
buf = cStringIO.StringIO()
compileUi(form, buf)
dat = buf.getvalue()
dat = dat.replace('__appname__', 'calibre')
dat = dat.replace('import images_rc', '')
dat = dat.replace('from library import', 'from calibre.gui2.library import')
dat = dat.replace('from widgets import', 'from calibre.gui2.widgets import')
dat = dat.replace('from convert.xpath_wizard import',
'from calibre.gui2.convert.xpath_wizard import')
dat = re.compile(r'QtGui.QApplication.translate\(.+?,\s+"(.+?)(?<!\\)",.+?\)', re.DOTALL).sub(r'_("\1")', dat)
dat = dat.replace('_("MMM yyyy")', '"MMM yyyy"')
dat = pat.sub(sub, dat)
if form.endswith('viewer%smain.ui'%os.sep):
info('\t\tPromoting WebView')
dat = dat.replace('self.view = QtWebKit.QWebView(', 'self.view = DocumentView(')
dat += '\n\nfrom calibre.gui2.viewer.documentview import DocumentView'
dat += '\nQtWebKit'
open(compiled_form, 'wb').write(dat)

View File

@ -6,10 +6,9 @@ __copyright__ = '2008-2009, Darko Miletic <darko.miletic at gmail.com>'
mondediplo.com mondediplo.com
''' '''
import re, urllib import urllib
from calibre import strftime from calibre import strftime
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import Tag
class LeMondeDiplomatiqueEn(BasicNewsRecipe): class LeMondeDiplomatiqueEn(BasicNewsRecipe):
title = 'Le Monde diplomatique - English edition' title = 'Le Monde diplomatique - English edition'

View File

@ -291,7 +291,7 @@ class NYTimes(BasicNewsRecipe):
return soup return soup
else: else:
print "no allowed content found, removing article" print "no allowed content found, removing article"
raise StringError raise Exception()
def postprocess_html(self,soup, True): def postprocess_html(self,soup, True):

View File

@ -7,7 +7,6 @@ www.smashingmagazine.com
''' '''
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import Tag
class SmashingMagazine(BasicNewsRecipe): class SmashingMagazine(BasicNewsRecipe):
title = 'Smashing Magazine' title = 'Smashing Magazine'