Merged pull request #39 from Roejames12/1.1.

My *last* changes for 1.1 :)
1.1
Ariya Hidayat 2011-04-27 17:10:05 -07:00
commit 16a0cd36e3
6 changed files with 104 additions and 75 deletions

View File

@ -18,7 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
''' '''
from PyQt4.QtCore import QObject, QFile, QVariant, QString from PyQt4.QtCore import QObject, QFile
from PyQt4.QtWebKit import QWebPage from PyQt4.QtWebKit import QWebPage
class CSConverter(QObject): class CSConverter(QObject):
@ -29,7 +29,7 @@ class CSConverter(QObject):
converter = QFile(':/resources/coffee-script.js') converter = QFile(':/resources/coffee-script.js')
converter.open(QFile.ReadOnly) converter.open(QFile.ReadOnly)
script = QString.fromUtf8(converter.readAll()) script = str(converter.readAll())
converter.close() converter.close()
self.m_webPage.mainFrame().evaluateJavaScript(script) self.m_webPage.mainFrame().evaluateJavaScript(script)
self.m_webPage.mainFrame().addToJavaScriptWindowObject('converter', self) self.m_webPage.mainFrame().addToJavaScriptWindowObject('converter', self)
@ -37,6 +37,6 @@ class CSConverter(QObject):
def convert(self, script): def convert(self, script):
self.setProperty('source', script) self.setProperty('source', script)
result = self.m_webPage.mainFrame().evaluateJavaScript('this.CoffeeScript.compile(converter.source)') result = self.m_webPage.mainFrame().evaluateJavaScript('this.CoffeeScript.compile(converter.source)')
if result.type() == QVariant.String: if len(result):
return result.toString() return result
return QString() return ''

View File

@ -19,14 +19,14 @@
''' '''
from PyQt4.QtGui import QDesktopServices from PyQt4.QtGui import QDesktopServices
from PyQt4.QtCore import SIGNAL, QString, qDebug, qWarning from PyQt4.QtCore import qDebug, qWarning
from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkDiskCache, \ from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkDiskCache, \
QNetworkRequest QNetworkRequest
class NetworkAccessManager(QNetworkAccessManager): class NetworkAccessManager(QNetworkAccessManager):
def __init__(self, diskCacheEnabled, parent = None): def __init__(self, diskCacheEnabled, parent = None):
QNetworkAccessManager.__init__(self, parent) QNetworkAccessManager.__init__(self, parent)
self.connect(self, SIGNAL('finished(QNetworkReply *)'), self.handleFinished) self.finished.connect(self.handleFinished)
if diskCacheEnabled == 'yes': if diskCacheEnabled == 'yes':
m_networkDiskCache = QNetworkDiskCache() m_networkDiskCache = QNetworkDiskCache()
@ -49,16 +49,16 @@ class NetworkAccessManager(QNetworkAccessManager):
else: else:
qWarning('Unexpected HTTP Operation Type') qWarning('Unexpected HTTP Operation Type')
qDebug(QString('URL %s' % req.url().toString())) qDebug('URL %s' % req.url().toString())
return QNetworkAccessManager.createRequest(self, op, req, outgoingData) return QNetworkAccessManager.createRequest(self, op, req, outgoingData)
def handleFinished(self, reply): def handleFinished(self, reply):
qDebug('HTTP/1.1 Response') qDebug('HTTP/1.1 Response')
qDebug(QString('URL %s' % reply.url().toString())) qDebug('URL %s' % reply.url().toString())
code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute).toString() code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
if code: if code:
qDebug('Status code: %s' % code) qDebug('Status code: %d' % code)
headerPairs = reply.rawHeaderPairs() headerPairs = reply.rawHeaderPairs()
for pair in headerPairs: for pair in headerPairs:

View File

@ -18,17 +18,18 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
''' '''
import os import sys, os
from utils import version_major, version_minor, version_patch
from csconverter import CSConverter from csconverter import CSConverter
from math import ceil, floor from math import ceil, floor
from time import sleep as usleep from time import sleep as usleep
from webpage import WebPage from webpage import WebPage
from networkaccessmanager import NetworkAccessManager from networkaccessmanager import NetworkAccessManager
from PyQt4.QtCore import pyqtProperty, pyqtSlot, Qt, QObject, QString, \ from PyQt4.QtCore import pyqtProperty, pyqtSlot, Qt, QObject, QRect, \
QRect, SIGNAL, SLOT, QTimer, QUrl, QFileInfo, \ SLOT, QTimer, QUrl, QFileInfo, QDir, QSize, \
QDir, QSize, QSizeF, QTime, QEventLoop, qDebug QSizeF, QTime, QEventLoop, qDebug
from PyQt4.QtGui import QPalette, QDesktopServices, qApp, QPrinter, \ from PyQt4.QtGui import QPalette, QDesktopServices, qApp, QPrinter, \
QImage, QPainter, QRegion, QApplication, qRgba QImage, QPainter, QRegion, QApplication, qRgba
from PyQt4.QtWebKit import QWebSettings, QWebPage from PyQt4.QtWebKit import QWebSettings, QWebPage
@ -43,14 +44,19 @@ class Phantom(QObject):
QObject.__init__(self, parent) QObject.__init__(self, parent)
# variable declarations # variable declarations
self.m_loadStatus = self.m_state = QString() self.m_loadStatus = self.m_state = ''
self.m_var = self.m_paperSize = self.m_loadScript_cache = {} self.m_var = self.m_paperSize = self.m_loadScript_cache = {}
self.m_verbose = args.verbose self.m_verbose = args.verbose
self.m_page = WebPage(self) self.m_page = WebPage(self)
self.m_clipRect = QRect() self.m_clipRect = QRect()
# setup the values from args # setup the values from args
self.m_script = QString.fromUtf8(args.script.read()) self.m_script = args.script.read()
self.m_scriptFile = args.script.name self.m_scriptFile = args.script.name
self.m_scriptDir = os.path.dirname(args.script.name)
if sys.platform.startswith('win'):
self.m_scriptDir += '\\'
else:
self.m_scriptDir += '/'
self.m_args = args.script_args self.m_args = args.script_args
self.m_upload_file = args.upload_file self.m_upload_file = args.upload_file
autoLoadImages = False if args.load_images == 'no' else True autoLoadImages = False if args.load_images == 'no' else True
@ -82,24 +88,19 @@ class Phantom(QObject):
self.m_page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) self.m_page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
self.m_page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self.m_page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
# if our script was called in a different directory, change to it
# to make any dealings with files be relative to the scripts directory
if os.path.dirname(self.m_scriptFile):
os.chdir(os.path.dirname(self.m_scriptFile))
if self.m_verbose: if self.m_verbose:
m_netAccessMan = NetworkAccessManager(args.disk_cache, self) m_netAccessMan = NetworkAccessManager(args.disk_cache, self)
self.m_page.setNetworkAccessManager(m_netAccessMan) self.m_page.setNetworkAccessManager(m_netAccessMan)
# inject our properties and slots into javascript # inject our properties and slots into javascript
self.connect(self.m_page.mainFrame(), SIGNAL('javaScriptWindowObjectCleared()'), self.inject) self.m_page.mainFrame().javaScriptWindowObjectCleared.connect(self.inject)
self.connect(self.m_page, SIGNAL('loadFinished(bool)'), self.finish) self.m_page.loadFinished.connect(self.finish)
def execute(self): def execute(self):
if self.m_script.startsWith('#!'): if self.m_script.startswith('#!'):
self.m_script.prepend('//') self.m_script = '//' + self.m_script
if self.m_scriptFile.endswith('.coffee'): if self.m_scriptFile.lower().endswith('.coffee'):
coffee = CSConverter(self) coffee = CSConverter(self)
self.m_script = coffee.convert(self.m_script) self.m_script = coffee.convert(self.m_script)
@ -195,15 +196,19 @@ class Phantom(QObject):
@clipRect.setter @clipRect.setter
def clipRect(self, size): def clipRect(self, size):
w = int(size[QString('width')]) names = ('width', 'height', 'top', 'left')
h = int(size[QString('height')]) for item in names:
top = int(size[QString('top')]) try:
left = int(size[QString('left')]) globals()[item] = int(size[item])
if globals()[item] < 0:
if item not in ('top', 'left'):
globals()[item] = 0
except KeyError:
globals()[item] = getattr(self.m_clipRect, item)()
if w >= 0 and h >= 0: self.m_clipRect = QRect(left, top, width, height)
self.m_clipRect = QRect(left, top, w, h)
@pyqtProperty('QString') @pyqtProperty(str)
def content(self): def content(self):
return self.m_page.mainFrame().toHtml() return self.m_page.mainFrame().toHtml()
@ -215,7 +220,7 @@ class Phantom(QObject):
@pyqtSlot(int) @pyqtSlot(int)
def exit(self, code = 0): def exit(self, code = 0):
self.m_returnValue = code self.m_returnValue = code
self.disconnect(self.m_page, SIGNAL('loadFinished(bool)'), self.finish) self.m_page.loadFinished.disconnect(self.finish)
QTimer.singleShot(0, qApp, SLOT('quit()')) QTimer.singleShot(0, qApp, SLOT('quit()'))
@pyqtProperty(str) @pyqtProperty(str)
@ -228,19 +233,19 @@ class Phantom(QObject):
self.m_page.mainFrame().evaluateJavaScript(self.m_loadScript_cache[script]) self.m_page.mainFrame().evaluateJavaScript(self.m_loadScript_cache[script])
return True return True
scriptFile = QString(script) scriptFile = script
try: try:
script = open(script) script = open(self.m_scriptDir + script)
script = QString.fromUtf8(script.read()) script = script.read()
except IOError: except IOError:
return False return False
if script.startsWith('#!'): if script.startswith('#!'):
script.prepend('//') script = '//' + script
if scriptFile.endsWith('.coffee'): if scriptFile.lower().endswith('.coffee'):
coffee = CSConverter(self) coffee = CSConverter(self)
script = QString.fromUtf8(coffee.convert(script)) script = coffee.convert(script)
self.m_loadScript_cache[scriptFile] = script self.m_loadScript_cache[scriptFile] = script
self.m_page.mainFrame().evaluateJavaScript(script) self.m_page.mainFrame().evaluateJavaScript(script)
@ -259,12 +264,7 @@ class Phantom(QObject):
@paperSize.setter @paperSize.setter
def paperSize(self, size): def paperSize(self, size):
# convert QString to str self.m_paperSize = size
size_buffer = {}
for key, value in size.items():
size_buffer[str(key)] = str(value)
self.m_paperSize = size_buffer
@pyqtSlot(str, result=bool) @pyqtSlot(str, result=bool)
def render(self, fileName): def render(self, fileName):
@ -272,7 +272,7 @@ class Phantom(QObject):
path = QDir() path = QDir()
path.mkpath(fileInfo.absolutePath()) path.mkpath(fileInfo.absolutePath())
if fileName.endsWith('.pdf', Qt.CaseInsensitive): if fileName.lower().endswith('.pdf'):
return self.renderPdf(fileName) return self.renderPdf(fileName)
viewportSize = QSize(self.m_page.viewportSize()) viewportSize = QSize(self.m_page.viewportSize())
@ -361,7 +361,7 @@ class Phantom(QObject):
@pyqtProperty('QVariantMap') @pyqtProperty('QVariantMap')
def viewportSize(self): def viewportSize(self):
size = QSize(self.m_page.viewportSize()) size = self.m_page.viewportSize()
result = { result = {
'width': size.width(), 'width': size.width(),
'height': size.height() 'height': size.height()
@ -370,7 +370,13 @@ class Phantom(QObject):
@viewportSize.setter @viewportSize.setter
def viewportSize(self, size): def viewportSize(self, size):
w = int(size[QString('width')]) names = ('width', 'height')
h = int(size[QString('height')]) for item in names:
if w > 0 and h > 0: try:
self.m_page.setViewportSize(QSize(w, h)) globals()[item] = int(size[item])
if globals()[item] < 0:
globals()[item] = 0
except KeyError:
globals()[item] = getattr(self.m_page.viewportSize(), item)()
self.m_page.setViewportSize(QSize(width, height))

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python
''' '''
This file is part of the PyPhantomJS project. This file is part of the PyPhantomJS project.
@ -19,35 +19,40 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
''' '''
# automatically convert Qt types by using api 2
import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
import os, sys, resources import os, sys, resources
from phantom import Phantom from phantom import Phantom
from utils import argParser, MessageHandler, version from utils import argParser, MessageHandler, version
from PyQt4.QtCore import QString, qInstallMsgHandler, qFatal from PyQt4.QtCore import qInstallMsgHandler
from PyQt4.QtGui import QIcon, QApplication from PyQt4.QtGui import QIcon, QApplication
# make keyboard interrupt quit program # make keyboard interrupt quit program
import signal import signal
signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGINT, signal.SIG_DFL)
if __name__ == '__main__': def parseArgs(args):
# Handle all command-line options # Handle all command-line options
p = argParser() p = argParser()
arg_data = p.parse_known_args(sys.argv[1:]) arg_data = p.parse_known_args(args)
args = arg_data[0] args = arg_data[0]
args.script_args = arg_data[1] args.script_args = arg_data[1]
# register an alternative Message Handler
messageHandler = MessageHandler(args.verbose)
qInstallMsgHandler(messageHandler.process)
if args.upload_file: if args.upload_file:
# process the tags
item_buffer = {} item_buffer = {}
for i in range(len(args.upload_file)): for i in range(len(args.upload_file)):
item = args.upload_file[i].split('=') item = args.upload_file[i].split('=')
if len(item) < 2 or not len(item[1]): if len(item) < 2 or not len(item[1]):
if len(item_buffer) == 0: # if buffer is empty, or tag has no
# value 'tag=', print help and exit
if not len(item_buffer) or \
item[1:] and not item[1:][0]:
p.print_help() p.print_help()
sys.exit(1) sys.exit(1)
@ -75,12 +80,18 @@ if __name__ == '__main__':
else: else:
args.script = args.upload_file[i] args.script = args.upload_file[i]
args.script_args = args.upload_file[i+1:] args.script_args = args.upload_file[i+1:]
break break
item_buffer[QString(item[0])] = QString(item[1])
# duplicate tag checking
if item[0] in item_buffer:
sys.exit('Multiple tags named \'%s\' were found' % item[0])
item_buffer[item[0]] = item[1]
# make sure files exist
for tag in item_buffer: for tag in item_buffer:
if not os.path.exists(item_buffer[tag]): if not os.path.exists(item_buffer[tag]):
qFatal('No such file or directory: \'%s\'' % item_buffer[tag]) sys.exit('No such file or directory: \'%s\'' % item_buffer[tag])
args.upload_file = item_buffer args.upload_file = item_buffer
if args.proxy: if args.proxy:
@ -97,7 +108,16 @@ if __name__ == '__main__':
try: try:
args.script = open(args.script) args.script = open(args.script)
except IOError as (errno, stderr): except IOError as (errno, stderr):
qFatal(str(stderr) + ': \'%s\'' % args.script) sys.exit('%s: \'%s\'' % (stderr, args.script))
return args
def main():
args = parseArgs(sys.argv[1:])
# register an alternative Message Handler
messageHandler = MessageHandler(args.verbose)
qInstallMsgHandler(messageHandler.process)
app = QApplication(sys.argv) app = QApplication(sys.argv)
@ -111,3 +131,6 @@ if __name__ == '__main__':
phantom.execute() phantom.execute()
app.exec_() app.exec_()
sys.exit(phantom.returnValue()) sys.exit(phantom.returnValue())
if __name__ == '__main__':
main()

View File

@ -62,7 +62,7 @@ def argParser():
) )
parser.add_argument('--load-plugins', default='no', parser.add_argument('--load-plugins', default='no',
choices=['yes', 'no'], choices=['yes', 'no'],
help='Load all plugins (i.e. Flash, Silverlight, ...)\n(default: %(default)s)' help='Load all plugins (i.e. Flash, Silverlight, ...) (default: %(default)s)'
) )
parser.add_argument('--proxy', metavar='address:port', parser.add_argument('--proxy', metavar='address:port',
help='Set the network proxy' help='Set the network proxy'

View File

@ -18,7 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
''' '''
from PyQt4.QtCore import SIGNAL, QString, QUrl, QEventLoop, qDebug from PyQt4.QtCore import QUrl, QEventLoop, qDebug
from PyQt4.QtGui import QApplication from PyQt4.QtGui import QApplication
from PyQt4.QtWebKit import QWebPage from PyQt4.QtWebKit import QWebPage
@ -27,12 +27,12 @@ class WebPage(QWebPage):
QWebPage.__init__(self, parent) QWebPage.__init__(self, parent)
self.parent = parent self.parent = parent
self.m_nextFileTag = QString() self.m_nextFileTag = ''
self.m_userAgent = QWebPage.userAgentForUrl(self, QUrl()) self.m_userAgent = QWebPage.userAgentForUrl(self, QUrl())
if self.parent.m_verbose: if self.parent.m_verbose:
self.connect(self.currentFrame(), SIGNAL('urlChanged(const QUrl&)'), self.handleFrameUrlChanged) self.currentFrame().urlChanged.connect(self.handleFrameUrlChanged)
self.connect(self, SIGNAL('linkClicked(const QUrl&)'), self.handleLinkClicked) self.linkClicked.connect(self.handleLinkClicked)
def handleFrameUrlChanged(self, url): def handleFrameUrlChanged(self, url):
qDebug('URL Changed: %s' % url.toString()) qDebug('URL Changed: %s' % url.toString())
@ -45,9 +45,9 @@ class WebPage(QWebPage):
def javaScriptConsoleMessage(self, message, lineNumber, sourceID): def javaScriptConsoleMessage(self, message, lineNumber, sourceID):
if sourceID: if sourceID:
print sourceID + ':%s' % lineNumber + ' %s' % message.toUtf8() print '%s:%s %s' % (sourceID, lineNumber, message)
else: else:
print message.toUtf8() print message
def shouldInterruptJavaScript(self): def shouldInterruptJavaScript(self):
QApplication.processEvents(QEventLoop.AllEvents, 42) QApplication.processEvents(QEventLoop.AllEvents, 42)
@ -59,4 +59,4 @@ class WebPage(QWebPage):
def chooseFile(self, webframe, suggestedFile): def chooseFile(self, webframe, suggestedFile):
if self.m_nextFileTag in self.parent.m_upload_file: if self.m_nextFileTag in self.parent.m_upload_file:
return self.parent.m_upload_file[self.m_nextFileTag] return self.parent.m_upload_file[self.m_nextFileTag]
return QString() return ''