new version
This commit is contained in:
parent
f2963a938d
commit
28036e6205
|
@ -26,28 +26,33 @@ import re
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from datetime import datetime
|
|
||||||
from chaosc.argparser_groups import *
|
from chaosc.argparser_groups import ArgParser
|
||||||
from chaosc.lib import logger, resolve_host
|
from chaosc.lib import logger, resolve_host
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
|
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
|
||||||
from PyQt4.QtNetwork import QTcpServer, QTcpSocket, QUdpSocket, QHostAddress
|
from PyQt4.QtGui import QPixmap, QPainter
|
||||||
|
from PyQt4.QtNetwork import QHostAddress
|
||||||
|
|
||||||
from dump_grabber.dump_grabber_ui import Ui_MainWindow
|
from dump_grabber.dump_grabber_ui import Ui_MainWindow
|
||||||
from psylib.mjpeg_streaming_server import *
|
from psylib.mjpeg_streaming_server import (MjpegStreamingServer,
|
||||||
|
MjpegStreamingConsumerInterface)
|
||||||
from psylib.psyqt_base import PsyQtChaoscClientBase
|
from psylib.psyqt_base import PsyQtChaoscClientBase
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from chaosc.c_osc_lib import OSCMessage, decode_osc
|
from chaosc.c_osc_lib import OSCMessage, decode_osc
|
||||||
except ImportError as e:
|
except ImportError:
|
||||||
from chaosc.osc_lib import OSCMessage, decode_osc
|
from chaosc.osc_lib import OSCMessage, decode_osc
|
||||||
|
|
||||||
app = QtGui.QApplication([])
|
QTAPP = QtGui.QApplication([])
|
||||||
|
|
||||||
class ExclusiveTextStorage(object):
|
class ExclusiveTextStorage(object):
|
||||||
|
"""Stores the text representation of per actor osc messages"""
|
||||||
|
|
||||||
def __init__(self, columns, default_font, column_width, line_height, scene):
|
def __init__(self, columns, default_font, column_width, line_height, scene):
|
||||||
self.column_count = columns
|
self.column_count = columns
|
||||||
self.colors = (QtCore.Qt.red, QtCore.Qt.green, QtGui.QColor(46, 100, 254))
|
self.colors = (
|
||||||
|
QtCore.Qt.red, QtCore.Qt.green, QtGui.QColor(46, 100, 254))
|
||||||
self.lines = deque()
|
self.lines = deque()
|
||||||
self.default_font = default_font
|
self.default_font = default_font
|
||||||
self.column_width = column_width
|
self.column_width = column_width
|
||||||
|
@ -58,50 +63,49 @@ class ExclusiveTextStorage(object):
|
||||||
|
|
||||||
def init_columns(self):
|
def init_columns(self):
|
||||||
color = self.colors[0]
|
color = self.colors[0]
|
||||||
for y in range(self.num_lines):
|
for line_index in range(self.num_lines):
|
||||||
text_item = self.graphics_scene.addSimpleText("", self.default_font)
|
text_item = self.graphics_scene.addSimpleText("", self.default_font)
|
||||||
text_item.setBrush(color)
|
text_item.setBrush(color)
|
||||||
text_item.setPos(0, y * self.line_height)
|
text_item.setPos(0, line_index * self.line_height)
|
||||||
self.lines.append(text_item)
|
self.lines.append(text_item)
|
||||||
|
|
||||||
def __add_text(self, column, text):
|
def __add_text(self, column, text):
|
||||||
text_item = self.graphics_scene.addSimpleText(text, self.default_font)
|
text_item = self.graphics_scene.addSimpleText(text, self.default_font)
|
||||||
text_item.setX(column * self.column_width)
|
text_item.setX(column * self.column_width)
|
||||||
color = self.colors[column]
|
text_item.setBrush(self.colors[column])
|
||||||
text_item.setBrush(color)
|
|
||||||
|
|
||||||
old_item = self.lines.popleft()
|
old_item = self.lines.popleft()
|
||||||
self.graphics_scene.removeItem(old_item)
|
self.graphics_scene.removeItem(old_item)
|
||||||
self.lines.append(text_item)
|
self.lines.append(text_item)
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
while 1:
|
for column, text in self.data:
|
||||||
try:
|
|
||||||
column, text = self.data.popleft()
|
|
||||||
self.__add_text(column, text)
|
self.__add_text(column, text)
|
||||||
except IndexError, msg:
|
self.data.clear()
|
||||||
break
|
|
||||||
|
|
||||||
|
for text_index, text_item in enumerate(self.lines):
|
||||||
for iy, text_item in enumerate(self.lines):
|
text_item.setY(text_index * self.line_height)
|
||||||
text_item.setY(iy * self.line_height)
|
|
||||||
|
|
||||||
def add_text(self, column, text):
|
def add_text(self, column, text):
|
||||||
self.data.append((column, text))
|
self.data.append((column, text))
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QtGui.QMainWindow, Ui_MainWindow, MjpegStreamingConsumerInterface, PsyQtChaoscClientBase):
|
class MainWindow(QtGui.QMainWindow, Ui_MainWindow,
|
||||||
|
MjpegStreamingConsumerInterface, PsyQtChaoscClientBase):
|
||||||
|
|
||||||
|
"""This app receives per actor osc messages and provides an mjpeg stream
|
||||||
|
with colored text representation arranged in columns"""
|
||||||
|
|
||||||
def __init__(self, args, parent=None):
|
def __init__(self, args, parent=None):
|
||||||
self.args = args
|
self.args = args
|
||||||
#PsyQtChaoscClientBase.__init__(self)
|
|
||||||
super(MainWindow, self).__init__()
|
super(MainWindow, self).__init__()
|
||||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
|
|
||||||
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self)
|
self.http_server = MjpegStreamingServer(
|
||||||
|
(args.http_host, args.http_port), self)
|
||||||
self.http_server.listen(port=args.http_port)
|
self.http_server.listen(port=args.http_port)
|
||||||
self.graphics_view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
self.graphics_view.setHorizontalScrollBarPolicy(
|
||||||
self.graphics_view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
self.graphics_view.setVerticalScrollBarPolicy(
|
||||||
|
QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
self.graphics_view.setRenderHint(QtGui.QPainter.Antialiasing, True)
|
self.graphics_view.setRenderHint(QtGui.QPainter.Antialiasing, True)
|
||||||
self.graphics_view.setFrameStyle(QtGui.QFrame.NoFrame)
|
self.graphics_view.setFrameStyle(QtGui.QFrame.NoFrame)
|
||||||
self.graphics_scene = QtGui.QGraphicsScene(self)
|
self.graphics_scene = QtGui.QGraphicsScene(self)
|
||||||
|
@ -109,16 +113,17 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, MjpegStreamingConsumerInterfa
|
||||||
self.graphics_view.setScene(self.graphics_scene)
|
self.graphics_view.setScene(self.graphics_scene)
|
||||||
self.default_font = QtGui.QFont("Monospace", 14)
|
self.default_font = QtGui.QFont("Monospace", 14)
|
||||||
self.default_font.setStyleHint(QtGui.QFont.Monospace)
|
self.default_font.setStyleHint(QtGui.QFont.Monospace)
|
||||||
#self.default_font.setBold(True)
|
self.default_font.setBold(True)
|
||||||
self.graphics_scene.setFont(self.default_font)
|
self.graphics_scene.setFont(self.default_font)
|
||||||
self.font_metrics = QtGui.QFontMetrics(self.default_font)
|
self.font_metrics = QtGui.QFontMetrics(self.default_font)
|
||||||
self.line_height = self.font_metrics.height()
|
self.line_height = self.font_metrics.height()
|
||||||
columns = 3
|
columns = 3
|
||||||
self.column_width = 775 / columns
|
self.column_width = 775 / columns
|
||||||
|
self.text_storage = ExclusiveTextStorage(columns, self.default_font,
|
||||||
self.text_storage = ExclusiveTextStorage(columns, self.default_font, self.column_width, self.line_height, self.graphics_scene)
|
self.column_width,
|
||||||
|
self.line_height,
|
||||||
|
self.graphics_scene)
|
||||||
self.text_storage.init_columns()
|
self.text_storage.init_columns()
|
||||||
|
|
||||||
self.regex = re.compile("^/(uwe|merle|bjoern)/(.*?)$")
|
self.regex = re.compile("^/(uwe|merle|bjoern)/(.*?)$")
|
||||||
|
|
||||||
def pubdir(self):
|
def pubdir(self):
|
||||||
|
@ -129,7 +134,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, MjpegStreamingConsumerInterfa
|
||||||
msg.appendTypedArg("localhost", "s")
|
msg.appendTypedArg("localhost", "s")
|
||||||
msg.appendTypedArg(self.args.client_port, "i")
|
msg.appendTypedArg(self.args.client_port, "i")
|
||||||
msg.appendTypedArg(self.args.authenticate, "s")
|
msg.appendTypedArg(self.args.authenticate, "s")
|
||||||
self.osc_sock.writeDatagram(QByteArray(msg.encode_osc()), QHostAddress("127.0.0.1"), 7110)
|
self.osc_sock.writeDatagram(
|
||||||
|
QByteArray(msg.encode_osc()), QHostAddress("127.0.0.1"), 7110)
|
||||||
|
|
||||||
def handle_osc_error(self, error):
|
def handle_osc_error(self, error):
|
||||||
logger.info("osc socket error %d", error)
|
logger.info("osc socket error %d", error)
|
||||||
|
@ -139,28 +145,29 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, MjpegStreamingConsumerInterfa
|
||||||
|
|
||||||
def render_image(self):
|
def render_image(self):
|
||||||
self.text_storage.finish()
|
self.text_storage.finish()
|
||||||
image = QtGui.QImage(768, 576, QtGui.QImage.Format_ARGB32_Premultiplied)
|
image = QPixmap(768, 576)
|
||||||
image.fill(QtCore.Qt.black)
|
image.fill(QtCore.Qt.black)
|
||||||
painter = QtGui.QPainter(image)
|
painter = QPainter(image)
|
||||||
painter.setRenderHints(QtGui.QPainter.RenderHint(
|
painter.setRenderHints(QPainter.RenderHint(
|
||||||
QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing),
|
QPainter.Antialiasing | QPainter.TextAntialiasing), True)
|
||||||
True)
|
|
||||||
painter.setFont(self.default_font)
|
painter.setFont(self.default_font)
|
||||||
self.graphics_view.render(painter, target=QtCore.QRectF(0, 0, 768, 576),
|
self.graphics_view.render(
|
||||||
|
painter, target=QtCore.QRectF(0, 0, 768, 576),
|
||||||
source=QtCore.QRect(0, 0, 768, 576))
|
source=QtCore.QRect(0, 0, 768, 576))
|
||||||
painter.end()
|
painter.end()
|
||||||
buf = QBuffer()
|
buf = QBuffer()
|
||||||
buf.open(QIODevice.WriteOnly)
|
buf.open(QIODevice.WriteOnly)
|
||||||
image.save(buf, "JPG", 85)
|
image.save(buf, "JPG", 100)
|
||||||
image_data = buf.data()
|
image_data = buf.data()
|
||||||
return image_data
|
return image_data
|
||||||
|
|
||||||
def got_message(self):
|
def got_message(self):
|
||||||
while self.osc_sock.hasPendingDatagrams():
|
while self.osc_sock.hasPendingDatagrams():
|
||||||
data, address, port = self.osc_sock.readDatagram(self.osc_sock.pendingDatagramSize())
|
data, address, port = self.osc_sock.readDatagram(
|
||||||
|
self.osc_sock.pendingDatagramSize())
|
||||||
try:
|
try:
|
||||||
osc_address, typetags, args = decode_osc(data, 0, len(data))
|
osc_address, typetags, args = decode_osc(data, 0, len(data))
|
||||||
except Exception:
|
except ValueError:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
actor, text = self.regex.match(osc_address).groups()
|
actor, text = self.regex.match(osc_address).groups()
|
||||||
|
@ -170,11 +177,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, MjpegStreamingConsumerInterfa
|
||||||
if text == "temperatur":
|
if text == "temperatur":
|
||||||
text += "e"
|
text += "e"
|
||||||
if actor == "merle":
|
if actor == "merle":
|
||||||
self.add_text(0, "%s = %s" % (text, ", ".join([str(i) for i in args])))
|
self.add_text(0, "%s = %s" % (
|
||||||
|
text, ", ".join([str(i) for i in args])))
|
||||||
elif actor == "uwe":
|
elif actor == "uwe":
|
||||||
self.add_text(1, "%s = %s" % (text, ", ".join([str(i) for i in args])))
|
self.add_text(1, "%s = %s" % (
|
||||||
|
text, ", ".join([str(i) for i in args])))
|
||||||
elif actor == "bjoern":
|
elif actor == "bjoern":
|
||||||
self.add_text(2, "%s = %s" % (text, ", ".join([str(i) for i in args])))
|
self.add_text(2, "%s = %s" % (
|
||||||
|
text, ", ".join([str(i) for i in args])))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,14 +200,16 @@ def main():
|
||||||
arg_parser.add_subscriber_group()
|
arg_parser.add_subscriber_group()
|
||||||
args = arg_parser.finalize()
|
args = arg_parser.finalize()
|
||||||
|
|
||||||
http_host, http_port = resolve_host(args.http_host, args.http_port, args.address_family)
|
args.http_host, args.http_port = resolve_host(
|
||||||
args.chaosc_host, args.chaosc_port = resolve_host(args.chaosc_host, args.chaosc_port, args.address_family)
|
args.http_host, args.http_port, args.address_family)
|
||||||
|
args.chaosc_host, args.chaosc_port = resolve_host(
|
||||||
|
args.chaosc_host, args.chaosc_port, args.address_family)
|
||||||
|
|
||||||
window = MainWindow(args)
|
window = MainWindow(args)
|
||||||
sys.excepthook = window.sigint_handler
|
sys.excepthook = window.sigint_handler
|
||||||
signal.signal(signal.SIGTERM, window.sigterm_handler)
|
signal.signal(signal.SIGTERM, window.sigterm_handler)
|
||||||
app.exec_()
|
QTAPP.exec_()
|
||||||
|
|
||||||
|
|
||||||
if ( __name__ == '__main__' ):
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from distribute_setup import use_setuptools
|
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
@ -12,13 +9,15 @@ if sys.version_info >= (3,):
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='dump_grabber',
|
name='dump_grabber',
|
||||||
version="0.1",
|
version="0.2",
|
||||||
packages=find_packages(exclude=["scripts",]),
|
packages=find_packages(exclude=["scripts",]),
|
||||||
|
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
|
|
||||||
exclude_package_data = {'': ['.gitignore']},
|
exclude_package_data = {'': ['.gitignore']},
|
||||||
|
|
||||||
|
install_requires = ["psylib"],
|
||||||
|
|
||||||
# installing unzipped
|
# installing unzipped
|
||||||
zip_safe = False,
|
zip_safe = False,
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,556 @@
|
||||||
|
#!python
|
||||||
|
"""Bootstrap distribute installation
|
||||||
|
|
||||||
|
If you want to use setuptools in your package's setup.py, just include this
|
||||||
|
file in the same directory with it, and add this to the top of your setup.py::
|
||||||
|
|
||||||
|
from distribute_setup import use_setuptools
|
||||||
|
use_setuptools()
|
||||||
|
|
||||||
|
If you want to require a specific version of setuptools, set a download
|
||||||
|
mirror, or use an alternate download directory, you can do so by supplying
|
||||||
|
the appropriate options to ``use_setuptools()``.
|
||||||
|
|
||||||
|
This file can also be run as a script to install or upgrade setuptools.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import fnmatch
|
||||||
|
import tempfile
|
||||||
|
import tarfile
|
||||||
|
import optparse
|
||||||
|
|
||||||
|
from distutils import log
|
||||||
|
|
||||||
|
try:
|
||||||
|
from site import USER_SITE
|
||||||
|
except ImportError:
|
||||||
|
USER_SITE = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
return subprocess.call(args) == 0
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# will be used for python 2.3
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
# quoting arguments if windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
def quote(arg):
|
||||||
|
if ' ' in arg:
|
||||||
|
return '"%s"' % arg
|
||||||
|
return arg
|
||||||
|
args = [quote(arg) for arg in args]
|
||||||
|
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||||
|
|
||||||
|
DEFAULT_VERSION = "0.6.49"
|
||||||
|
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||||
|
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||||
|
|
||||||
|
SETUPTOOLS_PKG_INFO = """\
|
||||||
|
Metadata-Version: 1.0
|
||||||
|
Name: setuptools
|
||||||
|
Version: %s
|
||||||
|
Summary: xxxx
|
||||||
|
Home-page: xxx
|
||||||
|
Author: xxx
|
||||||
|
Author-email: xxx
|
||||||
|
License: xxx
|
||||||
|
Description: xxx
|
||||||
|
""" % SETUPTOOLS_FAKED_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def _install(tarball, install_args=()):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# installing
|
||||||
|
log.warn('Installing Distribute')
|
||||||
|
if not _python_cmd('setup.py', 'install', *install_args):
|
||||||
|
log.warn('Something went wrong during the installation.')
|
||||||
|
log.warn('See the error message above.')
|
||||||
|
# exitcode will be 2
|
||||||
|
return 2
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_egg(egg, tarball, to_dir):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# building an egg
|
||||||
|
log.warn('Building a Distribute egg in %s', to_dir)
|
||||||
|
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
# returning the result
|
||||||
|
log.warn(egg)
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
raise IOError('Could not build the egg.')
|
||||||
|
|
||||||
|
|
||||||
|
def _do_download(version, download_base, to_dir, download_delay):
|
||||||
|
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||||
|
% (version, sys.version_info[0], sys.version_info[1]))
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
tarball = download_setuptools(version, download_base,
|
||||||
|
to_dir, download_delay)
|
||||||
|
_build_egg(egg, tarball, to_dir)
|
||||||
|
sys.path.insert(0, egg)
|
||||||
|
import setuptools
|
||||||
|
setuptools.bootstrap_install_from = egg
|
||||||
|
|
||||||
|
|
||||||
|
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
was_imported = 'pkg_resources' in sys.modules or \
|
||||||
|
'setuptools' in sys.modules
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
# Setuptools 0.7b and later is a suitable (and preferable)
|
||||||
|
# substitute for any Distribute version.
|
||||||
|
try:
|
||||||
|
pkg_resources.require("setuptools>=0.7b")
|
||||||
|
return
|
||||||
|
except (pkg_resources.DistributionNotFound,
|
||||||
|
pkg_resources.VersionConflict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not hasattr(pkg_resources, '_distribute'):
|
||||||
|
if not no_fake:
|
||||||
|
_fake_setuptools()
|
||||||
|
raise ImportError
|
||||||
|
except ImportError:
|
||||||
|
return _do_download(version, download_base, to_dir, download_delay)
|
||||||
|
try:
|
||||||
|
pkg_resources.require("distribute>=" + version)
|
||||||
|
return
|
||||||
|
except pkg_resources.VersionConflict:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if was_imported:
|
||||||
|
sys.stderr.write(
|
||||||
|
"The required version of distribute (>=%s) is not available,\n"
|
||||||
|
"and can't be installed while this script is running. Please\n"
|
||||||
|
"install a more recent version first, using\n"
|
||||||
|
"'easy_install -U distribute'."
|
||||||
|
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
except pkg_resources.DistributionNotFound:
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
finally:
|
||||||
|
if not no_fake:
|
||||||
|
_create_fake_setuptools_pkg_info(to_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, delay=15):
|
||||||
|
"""Download distribute from a specified location and return its filename
|
||||||
|
|
||||||
|
`version` should be a valid distribute version number that is available
|
||||||
|
as an egg for download under the `download_base` URL (which should end
|
||||||
|
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||||
|
`delay` is the number of seconds to pause before an actual download
|
||||||
|
attempt.
|
||||||
|
"""
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
try:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
except ImportError:
|
||||||
|
from urllib2 import urlopen
|
||||||
|
tgz_name = "distribute-%s.tar.gz" % version
|
||||||
|
url = download_base + tgz_name
|
||||||
|
saveto = os.path.join(to_dir, tgz_name)
|
||||||
|
src = dst = None
|
||||||
|
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||||
|
try:
|
||||||
|
log.warn("Downloading %s", url)
|
||||||
|
src = urlopen(url)
|
||||||
|
# Read/write all in one block, so we don't create a corrupt file
|
||||||
|
# if the download is interrupted.
|
||||||
|
data = src.read()
|
||||||
|
dst = open(saveto, "wb")
|
||||||
|
dst.write(data)
|
||||||
|
finally:
|
||||||
|
if src:
|
||||||
|
src.close()
|
||||||
|
if dst:
|
||||||
|
dst.close()
|
||||||
|
return os.path.realpath(saveto)
|
||||||
|
|
||||||
|
|
||||||
|
def _no_sandbox(function):
|
||||||
|
def __no_sandbox(*args, **kw):
|
||||||
|
try:
|
||||||
|
from setuptools.sandbox import DirectorySandbox
|
||||||
|
if not hasattr(DirectorySandbox, '_old'):
|
||||||
|
def violation(*args):
|
||||||
|
pass
|
||||||
|
DirectorySandbox._old = DirectorySandbox._violation
|
||||||
|
DirectorySandbox._violation = violation
|
||||||
|
patched = True
|
||||||
|
else:
|
||||||
|
patched = False
|
||||||
|
except ImportError:
|
||||||
|
patched = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
return function(*args, **kw)
|
||||||
|
finally:
|
||||||
|
if patched:
|
||||||
|
DirectorySandbox._violation = DirectorySandbox._old
|
||||||
|
del DirectorySandbox._old
|
||||||
|
|
||||||
|
return __no_sandbox
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_file(path, content):
|
||||||
|
"""Will backup the file then patch it"""
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
if existing_content == content:
|
||||||
|
# already patched
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return False
|
||||||
|
log.warn('Patching...')
|
||||||
|
_rename_path(path)
|
||||||
|
f = open(path, 'w')
|
||||||
|
try:
|
||||||
|
f.write(content)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_file = _no_sandbox(_patch_file)
|
||||||
|
|
||||||
|
|
||||||
|
def _same_content(path, content):
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
return existing_content == content
|
||||||
|
|
||||||
|
|
||||||
|
def _rename_path(path):
|
||||||
|
new_name = path + '.OLD.%s' % time.time()
|
||||||
|
log.warn('Renaming %s to %s', path, new_name)
|
||||||
|
os.rename(path, new_name)
|
||||||
|
return new_name
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_flat_installation(placeholder):
|
||||||
|
if not os.path.isdir(placeholder):
|
||||||
|
log.warn('Unkown installation at %s', placeholder)
|
||||||
|
return False
|
||||||
|
found = False
|
||||||
|
for file in os.listdir(placeholder):
|
||||||
|
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
log.warn('Could not locate setuptools*.egg-info')
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Moving elements out of the way...')
|
||||||
|
pkg_info = os.path.join(placeholder, file)
|
||||||
|
if os.path.isdir(pkg_info):
|
||||||
|
patched = _patch_egg_dir(pkg_info)
|
||||||
|
else:
|
||||||
|
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||||
|
|
||||||
|
if not patched:
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
# now let's move the files out of the way
|
||||||
|
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||||
|
element = os.path.join(placeholder, element)
|
||||||
|
if os.path.exists(element):
|
||||||
|
_rename_path(element)
|
||||||
|
else:
|
||||||
|
log.warn('Could not find the %s element of the '
|
||||||
|
'Setuptools distribution', element)
|
||||||
|
return True
|
||||||
|
|
||||||
|
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||||
|
|
||||||
|
|
||||||
|
def _after_install(dist):
|
||||||
|
log.warn('After install bootstrap.')
|
||||||
|
placeholder = dist.get_command_obj('install').install_purelib
|
||||||
|
_create_fake_setuptools_pkg_info(placeholder)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_fake_setuptools_pkg_info(placeholder):
|
||||||
|
if not placeholder or not os.path.exists(placeholder):
|
||||||
|
log.warn('Could not find the install location')
|
||||||
|
return
|
||||||
|
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||||
|
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||||
|
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||||
|
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
log.warn('%s already exists', pkg_info)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Creating %s', pkg_info)
|
||||||
|
try:
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
except EnvironmentError:
|
||||||
|
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||||
|
log.warn('Creating %s', pth_file)
|
||||||
|
f = open(pth_file, 'w')
|
||||||
|
try:
|
||||||
|
f.write(os.path.join(os.curdir, setuptools_file))
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||||
|
_create_fake_setuptools_pkg_info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_egg_dir(path):
|
||||||
|
# let's check if it's already patched
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
_rename_path(path)
|
||||||
|
os.mkdir(path)
|
||||||
|
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def _before_install():
|
||||||
|
log.warn('Before install bootstrap.')
|
||||||
|
_fake_setuptools()
|
||||||
|
|
||||||
|
|
||||||
|
def _under_prefix(location):
|
||||||
|
if 'install' not in sys.argv:
|
||||||
|
return True
|
||||||
|
args = sys.argv[sys.argv.index('install') + 1:]
|
||||||
|
for index, arg in enumerate(args):
|
||||||
|
for option in ('--root', '--prefix'):
|
||||||
|
if arg.startswith('%s=' % option):
|
||||||
|
top_dir = arg.split('root=')[-1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
elif arg == option:
|
||||||
|
if len(args) > index:
|
||||||
|
top_dir = args[index + 1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
if arg == '--user' and USER_SITE is not None:
|
||||||
|
return location.startswith(USER_SITE)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _fake_setuptools():
|
||||||
|
log.warn('Scanning installed packages')
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
except ImportError:
|
||||||
|
# we're cool
|
||||||
|
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||||
|
return
|
||||||
|
ws = pkg_resources.working_set
|
||||||
|
try:
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||||
|
)
|
||||||
|
except TypeError:
|
||||||
|
# old distribute API
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools')
|
||||||
|
)
|
||||||
|
|
||||||
|
if setuptools_dist is None:
|
||||||
|
log.warn('No setuptools distribution found')
|
||||||
|
return
|
||||||
|
# detecting if it was already faked
|
||||||
|
setuptools_location = setuptools_dist.location
|
||||||
|
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||||
|
|
||||||
|
# if --root or --preix was provided, and if
|
||||||
|
# setuptools is not located in them, we don't patch it
|
||||||
|
if not _under_prefix(setuptools_location):
|
||||||
|
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||||
|
' in another location')
|
||||||
|
return
|
||||||
|
|
||||||
|
# let's see if its an egg
|
||||||
|
if not setuptools_location.endswith('.egg'):
|
||||||
|
log.warn('Non-egg installation')
|
||||||
|
res = _remove_flat_installation(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log.warn('Egg installation')
|
||||||
|
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if (os.path.exists(pkg_info) and
|
||||||
|
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return
|
||||||
|
log.warn('Patching...')
|
||||||
|
# let's create a fake egg replacing setuptools one
|
||||||
|
res = _patch_egg_dir(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
log.warn('Patching complete.')
|
||||||
|
_relaunch()
|
||||||
|
|
||||||
|
|
||||||
|
def _relaunch():
|
||||||
|
log.warn('Relaunching...')
|
||||||
|
# we have to relaunch the process
|
||||||
|
# pip marker to avoid a relaunch bug
|
||||||
|
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||||
|
_cmd2 = ['-c', 'install', '--record']
|
||||||
|
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||||
|
sys.argv[0] = 'setup.py'
|
||||||
|
args = [sys.executable] + sys.argv
|
||||||
|
sys.exit(subprocess.call(args))
|
||||||
|
|
||||||
|
|
||||||
|
def _extractall(self, path=".", members=None):
|
||||||
|
"""Extract all members from the archive to the current working
|
||||||
|
directory and set owner, modification time and permissions on
|
||||||
|
directories afterwards. `path' specifies a different directory
|
||||||
|
to extract to. `members' is optional and must be a subset of the
|
||||||
|
list returned by getmembers().
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
import operator
|
||||||
|
from tarfile import ExtractError
|
||||||
|
directories = []
|
||||||
|
|
||||||
|
if members is None:
|
||||||
|
members = self
|
||||||
|
|
||||||
|
for tarinfo in members:
|
||||||
|
if tarinfo.isdir():
|
||||||
|
# Extract directories with a safe mode.
|
||||||
|
directories.append(tarinfo)
|
||||||
|
tarinfo = copy.copy(tarinfo)
|
||||||
|
tarinfo.mode = 448 # decimal for oct 0700
|
||||||
|
self.extract(tarinfo, path)
|
||||||
|
|
||||||
|
# Reverse sort directories.
|
||||||
|
if sys.version_info < (2, 4):
|
||||||
|
def sorter(dir1, dir2):
|
||||||
|
return cmp(dir1.name, dir2.name)
|
||||||
|
directories.sort(sorter)
|
||||||
|
directories.reverse()
|
||||||
|
else:
|
||||||
|
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||||
|
|
||||||
|
# Set correct owner, mtime and filemode on directories.
|
||||||
|
for tarinfo in directories:
|
||||||
|
dirpath = os.path.join(path, tarinfo.name)
|
||||||
|
try:
|
||||||
|
self.chown(tarinfo, dirpath)
|
||||||
|
self.utime(tarinfo, dirpath)
|
||||||
|
self.chmod(tarinfo, dirpath)
|
||||||
|
except ExtractError:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if self.errorlevel > 1:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self._dbg(1, "tarfile: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_install_args(options):
|
||||||
|
"""
|
||||||
|
Build the arguments to 'python setup.py install' on the distribute package
|
||||||
|
"""
|
||||||
|
install_args = []
|
||||||
|
if options.user_install:
|
||||||
|
if sys.version_info < (2, 6):
|
||||||
|
log.warn("--user requires Python 2.6 or later")
|
||||||
|
raise SystemExit(1)
|
||||||
|
install_args.append('--user')
|
||||||
|
return install_args
|
||||||
|
|
||||||
|
def _parse_args():
|
||||||
|
"""
|
||||||
|
Parse the command line for options
|
||||||
|
"""
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'--user', dest='user_install', action='store_true', default=False,
|
||||||
|
help='install in user site package (requires Python 2.6 or later)')
|
||||||
|
parser.add_option(
|
||||||
|
'--download-base', dest='download_base', metavar="URL",
|
||||||
|
default=DEFAULT_URL,
|
||||||
|
help='alternative URL from where to download the distribute package')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
# positional arguments are ignored
|
||||||
|
return options
|
||||||
|
|
||||||
|
def main(version=DEFAULT_VERSION):
|
||||||
|
"""Install or upgrade setuptools and EasyInstall"""
|
||||||
|
options = _parse_args()
|
||||||
|
tarball = download_setuptools(download_base=options.download_base)
|
||||||
|
return _install(tarball, _build_install_args(options))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
|
@ -1,30 +1,25 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# This file is part of sensors2osc package
|
# This file is part of psychose/ekgplotter package
|
||||||
#
|
#
|
||||||
# sensors2osc is free software: you can redistribute it and/or modify
|
# psychose/ekgplotter is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# sensors2osc is distributed in the hope that it will be useful,
|
# psychose/ekgplotter is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with sensors2osc. If not, see <http://www.gnu.org/licenses/>.
|
# along with psychose/ekgplotter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
|
||||||
# found the mjpeg part here, thanks for the nice code :)
|
|
||||||
# http://hardsoftlucid.wordpress.com/2013/04/11/mjpeg-server-for-webcam-in-python-with-opencv/
|
|
||||||
# the osc integration stuff is implemented by me
|
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014 Stefan Kögl
|
# Copyright (C) 2014 Stefan Kögl
|
||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import atexit
|
|
||||||
import random
|
import random
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
|
@ -33,13 +28,15 @@ import sys
|
||||||
import exceptions
|
import exceptions
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
|
from PyQt4.QtGui import QImage, QPixmap, QMainWindow
|
||||||
from PyQt4.QtNetwork import QUdpSocket, QHostAddress
|
from PyQt4.QtCore import QBuffer, QIODevice
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
from pyqtgraph.widgets.PlotWidget import PlotWidget
|
from pyqtgraph.widgets.PlotWidget import PlotWidget
|
||||||
|
from pyqtgraph.graphicsItems.PlotCurveItem import PlotCurveItem
|
||||||
|
from pyqtgraph.graphicsItems.ScatterPlotItem import ScatterPlotItem
|
||||||
|
|
||||||
from chaosc.argparser_groups import ArgParser
|
from chaosc.argparser_groups import ArgParser
|
||||||
from chaosc.lib import logger, resolve_host
|
from chaosc.lib import logger, resolve_host
|
||||||
|
@ -47,9 +44,9 @@ from psylib.mjpeg_streaming_server import *
|
||||||
from psylib.psyqt_base import PsyQtChaoscClientBase
|
from psylib.psyqt_base import PsyQtChaoscClientBase
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from chaosc.c_osc_lib import OSCMessage, decode_osc
|
from chaosc.c_osc_lib import decode_osc
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
from chaosc.osc_lib import OSCMessage, decode_osc
|
from chaosc.osc_lib import decode_osc
|
||||||
|
|
||||||
qtapp = QtGui.QApplication([])
|
qtapp = QtGui.QApplication([])
|
||||||
|
|
||||||
|
@ -67,8 +64,8 @@ class Generator(object):
|
||||||
self.count = 0
|
self.count = 0
|
||||||
self.pulse = random.randint(85, 105)
|
self.pulse = random.randint(85, 105)
|
||||||
self.delta = delta
|
self.delta = delta
|
||||||
self.multiplier = 4
|
self.finished = False
|
||||||
self.steps, _ = get_steps(self.pulse, delta / self.multiplier)
|
self.steps, _ = get_steps(self.pulse, delta / 4)
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
while 1:
|
while 1:
|
||||||
|
@ -89,6 +86,7 @@ class Generator(object):
|
||||||
elif self.count < self.steps:
|
elif self.count < self.steps:
|
||||||
value = random.randint(15, 30)
|
value = random.randint(15, 30)
|
||||||
else:
|
else:
|
||||||
|
self.finished = True
|
||||||
self.count = 0
|
self.count = 0
|
||||||
value = 30
|
value = 30
|
||||||
|
|
||||||
|
@ -97,8 +95,7 @@ class Generator(object):
|
||||||
|
|
||||||
def set_pulse(self, pulse):
|
def set_pulse(self, pulse):
|
||||||
self.pulse = pulse
|
self.pulse = pulse
|
||||||
self.steps, _ = get_steps(pulse, self.delta / self.multiplier)
|
self.steps, _ = get_steps(pulse, self.delta)
|
||||||
|
|
||||||
|
|
||||||
def retrigger(self):
|
def retrigger(self):
|
||||||
self.count = self.steps / 2
|
self.count = self.steps / 2
|
||||||
|
@ -112,37 +109,33 @@ class Actor(object):
|
||||||
self.ix = ix
|
self.ix = ix
|
||||||
self.max_actors = max_actors
|
self.max_actors = max_actors
|
||||||
self.actor_height = actor_height
|
self.actor_height = actor_height
|
||||||
self.updated = 0
|
|
||||||
|
|
||||||
self.offset = ix * actor_height
|
self.offset = ix * actor_height
|
||||||
self.data = np.array([self.offset] * num_data)
|
self.data = np.array([self.offset + 30] * num_data)
|
||||||
self.head = 0
|
self.head = 0
|
||||||
self.pre_head = 0
|
self.pre_head = 0
|
||||||
self.plotItem = pg.PlotCurveItem(pen=pg.mkPen(color, width=3), width=4, name=name)
|
self.plotItem = PlotCurveItem(pen=pg.mkPen(color, width=3), width=4, name=name)
|
||||||
#self.plotItem.setShadowPen(pg.mkPen("w", width=5))
|
self.plotPoint = ScatterPlotItem(pen=pg.mkPen("w", width=5), brush=pg.mkBrush(color), size=5)
|
||||||
self.plotPoint = pg.ScatterPlotItem(pen=pg.mkPen("w", width=5), brush=pg.mkBrush(color), size=5)
|
|
||||||
self.osci = None
|
self.osci = None
|
||||||
self.osci_obj = None
|
self.osci_obj = None
|
||||||
|
self.render()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "<Actor name:%r, position=%r>" % (self.name, self.head)
|
return "<Actor name:%r, position=%r>" % (self.name, self.head)
|
||||||
|
|
||||||
__repr__ = __str__
|
def __repr__(self):
|
||||||
|
return "Actor(%r, %r, %r, %r, %r, %r)" % (self.name, self.num_data,
|
||||||
|
self.color, self.ix, self.max_actors, self.actor_height)
|
||||||
|
|
||||||
def add_value(self, value):
|
def add_value(self, value):
|
||||||
dp = self.head
|
self.pre_head = self.head
|
||||||
self.data[dp] = value / self.max_actors + self.offset
|
self.data[self.pre_head] = value / self.max_actors + self.offset
|
||||||
self.pre_head = dp
|
self.head = (self.pre_head + 1) % self.num_data
|
||||||
self.head = (dp + 1) % self.num_data
|
|
||||||
self.updated += 1
|
|
||||||
|
|
||||||
def fill_missing(self, count):
|
def fill_missing(self, count):
|
||||||
dp = self.head
|
dp = self.head
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
self.data[dp] = self.offset
|
self.data[dp] = self.offset
|
||||||
dp = (dp + 1) % self.num_data
|
dp = (dp + 1) % self.num_data
|
||||||
self.updated += 1
|
|
||||||
|
|
||||||
self.pre_head = (dp - 1) % self.num_data
|
self.pre_head = (dp - 1) % self.num_data
|
||||||
self.head = dp
|
self.head = dp
|
||||||
|
@ -151,41 +144,47 @@ class Actor(object):
|
||||||
self.plotItem.setData(y=self.data, clear=True)
|
self.plotItem.setData(y=self.data, clear=True)
|
||||||
self.plotPoint.setData(x=[self.pre_head], y=[self.data[self.pre_head]])
|
self.plotPoint.setData(x=[self.pre_head], y=[self.data[self.pre_head]])
|
||||||
|
|
||||||
|
class PlotWindow(PlotWidget):
|
||||||
|
def __init__(self, title=None, **kargs):
|
||||||
|
self.win = QtGui.QMainWindow()
|
||||||
|
self.win.resize(768, 576)
|
||||||
|
PlotWidget.__init__(self, **kargs)
|
||||||
|
self.win.setCentralWidget(self)
|
||||||
|
for m in ['resize']:
|
||||||
|
setattr(self, m, getattr(self.win, m))
|
||||||
|
if title is not None:
|
||||||
|
self.win.setWindowTitle(title)
|
||||||
|
self.win.show()
|
||||||
|
|
||||||
class EkgPlotWidget(PlotWidget, PsyQtChaoscClientBase, MjpegStreamingConsumerInterface):
|
|
||||||
|
class EkgPlotWidget(QMainWindow, PsyQtChaoscClientBase, MjpegStreamingConsumerInterface):
|
||||||
def __init__(self, args, parent=None):
|
def __init__(self, args, parent=None):
|
||||||
self.args = args
|
self.args = args
|
||||||
super(EkgPlotWidget, self).__init__()
|
super(EkgPlotWidget, self).__init__()
|
||||||
PsyQtChaoscClientBase.__init__(self)
|
PsyQtChaoscClientBase.__init__(self)
|
||||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
|
self.plot_widget = PlotWidget(title="Psychose - EkgPlotter")
|
||||||
|
|
||||||
self.fps = 12.5
|
|
||||||
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self, self.fps)
|
|
||||||
self.http_server.listen(port=args.http_port)
|
|
||||||
|
|
||||||
self.num_data = 100
|
|
||||||
|
|
||||||
self.hide()
|
|
||||||
self.showGrid(False, False)
|
|
||||||
self.setYRange(0, 255)
|
|
||||||
self.setXRange(0, self.num_data)
|
|
||||||
self.resize(768, 576)
|
|
||||||
colors = ["r", "g", "b"]
|
colors = ["r", "g", "b"]
|
||||||
|
|
||||||
ba = self.getAxis("bottom")
|
|
||||||
bl = self.getAxis("left")
|
|
||||||
ba.setTicks([])
|
|
||||||
bl.setTicks([])
|
|
||||||
ba.hide()
|
|
||||||
bl.hide()
|
|
||||||
self.active_actors = list()
|
self.active_actors = list()
|
||||||
|
|
||||||
self.actors = dict()
|
self.actors = dict()
|
||||||
|
|
||||||
self.max_value = 255
|
self.max_value = 255
|
||||||
actor_names = ["merle", "uwe", "bjoern"]
|
actor_names = ["merle", "uwe", "bjoern"]
|
||||||
self.max_actors = len(actor_names)
|
self.max_actors = len(actor_names)
|
||||||
self.actor_height = self.max_value / self.max_actors
|
self.actor_height = self.max_value / self.max_actors
|
||||||
|
self.fps = 12.5
|
||||||
|
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self, self.fps)
|
||||||
|
self.http_server.listen(port=args.http_port)
|
||||||
|
self.num_data = 100
|
||||||
|
self.plot_widget.showGrid(False, False)
|
||||||
|
self.plot_widget.setYRange(0, 255)
|
||||||
|
self.plot_widget.setXRange(0, self.num_data)
|
||||||
|
self.plot_widget.resize(768, 576)
|
||||||
|
|
||||||
|
bottom_axis = self.plot_widget.getAxis("bottom")
|
||||||
|
left_axis = self.plot_widget.getAxis("left")
|
||||||
|
bottom_axis.setTicks([])
|
||||||
|
left_axis.setTicks([])
|
||||||
|
bottom_axis.hide()
|
||||||
|
left_axis.hide()
|
||||||
|
|
||||||
for ix, (actor_name, color) in enumerate(zip(actor_names, colors)):
|
for ix, (actor_name, color) in enumerate(zip(actor_names, colors)):
|
||||||
self.add_actor(actor_name, self.num_data, color, ix, self.max_actors, self.actor_height)
|
self.add_actor(actor_name, self.num_data, color, ix, self.max_actors, self.actor_height)
|
||||||
|
@ -193,21 +192,16 @@ class EkgPlotWidget(PlotWidget, PsyQtChaoscClientBase, MjpegStreamingConsumerInt
|
||||||
self.set_positions()
|
self.set_positions()
|
||||||
self.heartbeat_regex = re.compile("^/(.*?)/heartbeat$")
|
self.heartbeat_regex = re.compile("^/(.*?)/heartbeat$")
|
||||||
|
|
||||||
self.pull_timer = QtCore.QTimer()
|
|
||||||
self.pull_timer.timeout.connect(self.slot_pull_ekg)
|
|
||||||
self.pull_timer.start(40)
|
|
||||||
|
|
||||||
def pubdir(self):
|
def pubdir(self):
|
||||||
return os.path.dirname(os.path.abspath(__file__))
|
return os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
def add_actor(self, actor_name, num_data, color, ix, max_actors, actor_height):
|
def add_actor(self, actor_name, num_data, color, ix, max_actors, actor_height):
|
||||||
actor_obj = Actor(actor_name, num_data, color, ix, max_actors, actor_height)
|
actor_obj = Actor(actor_name, num_data, color, ix, max_actors, actor_height)
|
||||||
self.actors[actor_name] = actor_obj
|
self.actors[actor_name] = actor_obj
|
||||||
self.addItem(actor_obj.plotItem)
|
self.plot_widget.addItem(actor_obj.plotItem)
|
||||||
self.addItem(actor_obj.plotPoint)
|
self.plot_widget.addItem(actor_obj.plotPoint)
|
||||||
self.active_actors.append(actor_obj)
|
self.active_actors.append(actor_obj)
|
||||||
actor_obj.osci_obj = Generator(delta=self.http_server.timer_delta)
|
actor_obj.osci_obj = Generator(pulse=random.randint(88, 104), delta=self.http_server.timer_delta)
|
||||||
actor_obj.osci = actor_obj.osci_obj()
|
actor_obj.osci = actor_obj.osci_obj()
|
||||||
|
|
||||||
def set_positions(self):
|
def set_positions(self):
|
||||||
|
@ -219,7 +213,6 @@ class EkgPlotWidget(PlotWidget, PsyQtChaoscClientBase, MjpegStreamingConsumerInt
|
||||||
return self.max_actors
|
return self.max_actors
|
||||||
|
|
||||||
def update(self, osc_address, args):
|
def update(self, osc_address, args):
|
||||||
|
|
||||||
res = self.heartbeat_regex.match(osc_address)
|
res = self.heartbeat_regex.match(osc_address)
|
||||||
if res:
|
if res:
|
||||||
actor_name = res.group(1)
|
actor_name = res.group(1)
|
||||||
|
@ -229,16 +222,25 @@ class EkgPlotWidget(PlotWidget, PsyQtChaoscClientBase, MjpegStreamingConsumerInt
|
||||||
actor_obj.osci_obj.retrigger()
|
actor_obj.osci_obj.retrigger()
|
||||||
actor_obj.osci_obj.set_pulse(args[1])
|
actor_obj.osci_obj.set_pulse(args[1])
|
||||||
|
|
||||||
|
|
||||||
def render_image(self):
|
def render_image(self):
|
||||||
for actor_obj in self.active_actors:
|
for actor_obj in self.active_actors:
|
||||||
|
actor_obj.add_value(actor_obj.osci.next())
|
||||||
|
actor_obj.add_value(actor_obj.osci.next())
|
||||||
|
actor_obj.add_value(actor_obj.osci.next())
|
||||||
|
actor_obj.add_value(actor_obj.osci.next())
|
||||||
actor_obj.render()
|
actor_obj.render()
|
||||||
exporter = pg.exporters.ImageExporter.ImageExporter(self.plotItem)
|
image = QPixmap(768, 576)
|
||||||
exporter.parameters()['width'] = 768
|
image.fill(QtCore.Qt.white)
|
||||||
img = exporter.export(toBytes=True)
|
painter = QtGui.QPainter(image)
|
||||||
|
painter.setRenderHints(QtGui.QPainter.RenderHint(
|
||||||
|
QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing),
|
||||||
|
True)
|
||||||
|
scene = self.plot_widget.plotItem.scene()
|
||||||
|
scene.render(painter, QtCore.QRectF(0, 0, 768, 576), QtCore.QRectF(0, 0, 768, 576))
|
||||||
|
painter.end()
|
||||||
buf = QBuffer()
|
buf = QBuffer()
|
||||||
buf.open(QIODevice.WriteOnly)
|
buf.open(QIODevice.WriteOnly)
|
||||||
img.save(buf, "JPG", 75)
|
image.save(buf, "JPG", 80)
|
||||||
JpegData = buf.data()
|
JpegData = buf.data()
|
||||||
return JpegData
|
return JpegData
|
||||||
|
|
||||||
|
@ -247,16 +249,11 @@ class EkgPlotWidget(PlotWidget, PsyQtChaoscClientBase, MjpegStreamingConsumerInt
|
||||||
data, address, port = self.osc_sock.readDatagram(self.osc_sock.pendingDatagramSize())
|
data, address, port = self.osc_sock.readDatagram(self.osc_sock.pendingDatagramSize())
|
||||||
try:
|
try:
|
||||||
osc_address, typetags, args = decode_osc(data, 0, len(data))
|
osc_address, typetags, args = decode_osc(data, 0, len(data))
|
||||||
except Exception, e:
|
except ValueError, error:
|
||||||
logger.exception(e)
|
logger.exception(error)
|
||||||
else:
|
else:
|
||||||
self.update(osc_address, args)
|
self.update(osc_address, args)
|
||||||
|
|
||||||
def slot_pull_ekg(self):
|
|
||||||
for actor_obj in self.active_actors:
|
|
||||||
actor_obj.add_value(actor_obj.osci.next())
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
arg_parser = ArgParser("ekgplotter")
|
arg_parser = ArgParser("ekgplotter")
|
||||||
|
@ -274,8 +271,10 @@ def main():
|
||||||
args.chaosc_host, args.chaosc_port = resolve_host(args.chaosc_host, args.chaosc_port, args.address_family)
|
args.chaosc_host, args.chaosc_port = resolve_host(args.chaosc_host, args.chaosc_port, args.address_family)
|
||||||
|
|
||||||
window = EkgPlotWidget(args)
|
window = EkgPlotWidget(args)
|
||||||
sys.excepthook = window.sigint_handler
|
logger.info("foooooooo")
|
||||||
signal.signal(signal.SIGTERM, window.sigterm_handler)
|
window.hide()
|
||||||
|
#sys.excepthook = window.sigint_handler
|
||||||
|
#signal.signal(signal.SIGTERM, window.sigterm_handler)
|
||||||
qtapp.exec_()
|
qtapp.exec_()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from distribute_setup import use_setuptools
|
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
@ -12,7 +9,7 @@ if sys.version_info >= (3,):
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='ekgplotter',
|
name='ekgplotter',
|
||||||
version="0.1",
|
version="0.2",
|
||||||
packages=find_packages(exclude=["scripts",]),
|
packages=find_packages(exclude=["scripts",]),
|
||||||
|
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
|
@ -22,7 +19,7 @@ setup(
|
||||||
|
|
||||||
exclude_package_data = {'': ['.gitignore']},
|
exclude_package_data = {'': ['.gitignore']},
|
||||||
|
|
||||||
install_requires=["pyqtgraph"],
|
install_requires=["psylib", "pyqtgraph"],
|
||||||
|
|
||||||
# installing unzipped
|
# installing unzipped
|
||||||
zip_safe = False,
|
zip_safe = False,
|
||||||
|
|
|
@ -0,0 +1,556 @@
|
||||||
|
#!python
|
||||||
|
"""Bootstrap distribute installation
|
||||||
|
|
||||||
|
If you want to use setuptools in your package's setup.py, just include this
|
||||||
|
file in the same directory with it, and add this to the top of your setup.py::
|
||||||
|
|
||||||
|
from distribute_setup import use_setuptools
|
||||||
|
use_setuptools()
|
||||||
|
|
||||||
|
If you want to require a specific version of setuptools, set a download
|
||||||
|
mirror, or use an alternate download directory, you can do so by supplying
|
||||||
|
the appropriate options to ``use_setuptools()``.
|
||||||
|
|
||||||
|
This file can also be run as a script to install or upgrade setuptools.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import fnmatch
|
||||||
|
import tempfile
|
||||||
|
import tarfile
|
||||||
|
import optparse
|
||||||
|
|
||||||
|
from distutils import log
|
||||||
|
|
||||||
|
try:
|
||||||
|
from site import USER_SITE
|
||||||
|
except ImportError:
|
||||||
|
USER_SITE = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
return subprocess.call(args) == 0
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# will be used for python 2.3
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
# quoting arguments if windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
def quote(arg):
|
||||||
|
if ' ' in arg:
|
||||||
|
return '"%s"' % arg
|
||||||
|
return arg
|
||||||
|
args = [quote(arg) for arg in args]
|
||||||
|
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||||
|
|
||||||
|
DEFAULT_VERSION = "0.6.49"
|
||||||
|
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||||
|
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||||
|
|
||||||
|
SETUPTOOLS_PKG_INFO = """\
|
||||||
|
Metadata-Version: 1.0
|
||||||
|
Name: setuptools
|
||||||
|
Version: %s
|
||||||
|
Summary: xxxx
|
||||||
|
Home-page: xxx
|
||||||
|
Author: xxx
|
||||||
|
Author-email: xxx
|
||||||
|
License: xxx
|
||||||
|
Description: xxx
|
||||||
|
""" % SETUPTOOLS_FAKED_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def _install(tarball, install_args=()):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# installing
|
||||||
|
log.warn('Installing Distribute')
|
||||||
|
if not _python_cmd('setup.py', 'install', *install_args):
|
||||||
|
log.warn('Something went wrong during the installation.')
|
||||||
|
log.warn('See the error message above.')
|
||||||
|
# exitcode will be 2
|
||||||
|
return 2
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_egg(egg, tarball, to_dir):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# building an egg
|
||||||
|
log.warn('Building a Distribute egg in %s', to_dir)
|
||||||
|
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
# returning the result
|
||||||
|
log.warn(egg)
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
raise IOError('Could not build the egg.')
|
||||||
|
|
||||||
|
|
||||||
|
def _do_download(version, download_base, to_dir, download_delay):
|
||||||
|
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||||
|
% (version, sys.version_info[0], sys.version_info[1]))
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
tarball = download_setuptools(version, download_base,
|
||||||
|
to_dir, download_delay)
|
||||||
|
_build_egg(egg, tarball, to_dir)
|
||||||
|
sys.path.insert(0, egg)
|
||||||
|
import setuptools
|
||||||
|
setuptools.bootstrap_install_from = egg
|
||||||
|
|
||||||
|
|
||||||
|
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
was_imported = 'pkg_resources' in sys.modules or \
|
||||||
|
'setuptools' in sys.modules
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
# Setuptools 0.7b and later is a suitable (and preferable)
|
||||||
|
# substitute for any Distribute version.
|
||||||
|
try:
|
||||||
|
pkg_resources.require("setuptools>=0.7b")
|
||||||
|
return
|
||||||
|
except (pkg_resources.DistributionNotFound,
|
||||||
|
pkg_resources.VersionConflict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not hasattr(pkg_resources, '_distribute'):
|
||||||
|
if not no_fake:
|
||||||
|
_fake_setuptools()
|
||||||
|
raise ImportError
|
||||||
|
except ImportError:
|
||||||
|
return _do_download(version, download_base, to_dir, download_delay)
|
||||||
|
try:
|
||||||
|
pkg_resources.require("distribute>=" + version)
|
||||||
|
return
|
||||||
|
except pkg_resources.VersionConflict:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if was_imported:
|
||||||
|
sys.stderr.write(
|
||||||
|
"The required version of distribute (>=%s) is not available,\n"
|
||||||
|
"and can't be installed while this script is running. Please\n"
|
||||||
|
"install a more recent version first, using\n"
|
||||||
|
"'easy_install -U distribute'."
|
||||||
|
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
except pkg_resources.DistributionNotFound:
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
finally:
|
||||||
|
if not no_fake:
|
||||||
|
_create_fake_setuptools_pkg_info(to_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, delay=15):
|
||||||
|
"""Download distribute from a specified location and return its filename
|
||||||
|
|
||||||
|
`version` should be a valid distribute version number that is available
|
||||||
|
as an egg for download under the `download_base` URL (which should end
|
||||||
|
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||||
|
`delay` is the number of seconds to pause before an actual download
|
||||||
|
attempt.
|
||||||
|
"""
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
try:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
except ImportError:
|
||||||
|
from urllib2 import urlopen
|
||||||
|
tgz_name = "distribute-%s.tar.gz" % version
|
||||||
|
url = download_base + tgz_name
|
||||||
|
saveto = os.path.join(to_dir, tgz_name)
|
||||||
|
src = dst = None
|
||||||
|
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||||
|
try:
|
||||||
|
log.warn("Downloading %s", url)
|
||||||
|
src = urlopen(url)
|
||||||
|
# Read/write all in one block, so we don't create a corrupt file
|
||||||
|
# if the download is interrupted.
|
||||||
|
data = src.read()
|
||||||
|
dst = open(saveto, "wb")
|
||||||
|
dst.write(data)
|
||||||
|
finally:
|
||||||
|
if src:
|
||||||
|
src.close()
|
||||||
|
if dst:
|
||||||
|
dst.close()
|
||||||
|
return os.path.realpath(saveto)
|
||||||
|
|
||||||
|
|
||||||
|
def _no_sandbox(function):
|
||||||
|
def __no_sandbox(*args, **kw):
|
||||||
|
try:
|
||||||
|
from setuptools.sandbox import DirectorySandbox
|
||||||
|
if not hasattr(DirectorySandbox, '_old'):
|
||||||
|
def violation(*args):
|
||||||
|
pass
|
||||||
|
DirectorySandbox._old = DirectorySandbox._violation
|
||||||
|
DirectorySandbox._violation = violation
|
||||||
|
patched = True
|
||||||
|
else:
|
||||||
|
patched = False
|
||||||
|
except ImportError:
|
||||||
|
patched = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
return function(*args, **kw)
|
||||||
|
finally:
|
||||||
|
if patched:
|
||||||
|
DirectorySandbox._violation = DirectorySandbox._old
|
||||||
|
del DirectorySandbox._old
|
||||||
|
|
||||||
|
return __no_sandbox
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_file(path, content):
|
||||||
|
"""Will backup the file then patch it"""
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
if existing_content == content:
|
||||||
|
# already patched
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return False
|
||||||
|
log.warn('Patching...')
|
||||||
|
_rename_path(path)
|
||||||
|
f = open(path, 'w')
|
||||||
|
try:
|
||||||
|
f.write(content)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_file = _no_sandbox(_patch_file)
|
||||||
|
|
||||||
|
|
||||||
|
def _same_content(path, content):
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
return existing_content == content
|
||||||
|
|
||||||
|
|
||||||
|
def _rename_path(path):
|
||||||
|
new_name = path + '.OLD.%s' % time.time()
|
||||||
|
log.warn('Renaming %s to %s', path, new_name)
|
||||||
|
os.rename(path, new_name)
|
||||||
|
return new_name
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_flat_installation(placeholder):
|
||||||
|
if not os.path.isdir(placeholder):
|
||||||
|
log.warn('Unkown installation at %s', placeholder)
|
||||||
|
return False
|
||||||
|
found = False
|
||||||
|
for file in os.listdir(placeholder):
|
||||||
|
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
log.warn('Could not locate setuptools*.egg-info')
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Moving elements out of the way...')
|
||||||
|
pkg_info = os.path.join(placeholder, file)
|
||||||
|
if os.path.isdir(pkg_info):
|
||||||
|
patched = _patch_egg_dir(pkg_info)
|
||||||
|
else:
|
||||||
|
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||||
|
|
||||||
|
if not patched:
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
# now let's move the files out of the way
|
||||||
|
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||||
|
element = os.path.join(placeholder, element)
|
||||||
|
if os.path.exists(element):
|
||||||
|
_rename_path(element)
|
||||||
|
else:
|
||||||
|
log.warn('Could not find the %s element of the '
|
||||||
|
'Setuptools distribution', element)
|
||||||
|
return True
|
||||||
|
|
||||||
|
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||||
|
|
||||||
|
|
||||||
|
def _after_install(dist):
|
||||||
|
log.warn('After install bootstrap.')
|
||||||
|
placeholder = dist.get_command_obj('install').install_purelib
|
||||||
|
_create_fake_setuptools_pkg_info(placeholder)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_fake_setuptools_pkg_info(placeholder):
|
||||||
|
if not placeholder or not os.path.exists(placeholder):
|
||||||
|
log.warn('Could not find the install location')
|
||||||
|
return
|
||||||
|
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||||
|
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||||
|
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||||
|
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
log.warn('%s already exists', pkg_info)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Creating %s', pkg_info)
|
||||||
|
try:
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
except EnvironmentError:
|
||||||
|
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||||
|
log.warn('Creating %s', pth_file)
|
||||||
|
f = open(pth_file, 'w')
|
||||||
|
try:
|
||||||
|
f.write(os.path.join(os.curdir, setuptools_file))
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||||
|
_create_fake_setuptools_pkg_info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_egg_dir(path):
|
||||||
|
# let's check if it's already patched
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
_rename_path(path)
|
||||||
|
os.mkdir(path)
|
||||||
|
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def _before_install():
|
||||||
|
log.warn('Before install bootstrap.')
|
||||||
|
_fake_setuptools()
|
||||||
|
|
||||||
|
|
||||||
|
def _under_prefix(location):
|
||||||
|
if 'install' not in sys.argv:
|
||||||
|
return True
|
||||||
|
args = sys.argv[sys.argv.index('install') + 1:]
|
||||||
|
for index, arg in enumerate(args):
|
||||||
|
for option in ('--root', '--prefix'):
|
||||||
|
if arg.startswith('%s=' % option):
|
||||||
|
top_dir = arg.split('root=')[-1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
elif arg == option:
|
||||||
|
if len(args) > index:
|
||||||
|
top_dir = args[index + 1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
if arg == '--user' and USER_SITE is not None:
|
||||||
|
return location.startswith(USER_SITE)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _fake_setuptools():
|
||||||
|
log.warn('Scanning installed packages')
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
except ImportError:
|
||||||
|
# we're cool
|
||||||
|
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||||
|
return
|
||||||
|
ws = pkg_resources.working_set
|
||||||
|
try:
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||||
|
)
|
||||||
|
except TypeError:
|
||||||
|
# old distribute API
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools')
|
||||||
|
)
|
||||||
|
|
||||||
|
if setuptools_dist is None:
|
||||||
|
log.warn('No setuptools distribution found')
|
||||||
|
return
|
||||||
|
# detecting if it was already faked
|
||||||
|
setuptools_location = setuptools_dist.location
|
||||||
|
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||||
|
|
||||||
|
# if --root or --preix was provided, and if
|
||||||
|
# setuptools is not located in them, we don't patch it
|
||||||
|
if not _under_prefix(setuptools_location):
|
||||||
|
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||||
|
' in another location')
|
||||||
|
return
|
||||||
|
|
||||||
|
# let's see if its an egg
|
||||||
|
if not setuptools_location.endswith('.egg'):
|
||||||
|
log.warn('Non-egg installation')
|
||||||
|
res = _remove_flat_installation(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log.warn('Egg installation')
|
||||||
|
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if (os.path.exists(pkg_info) and
|
||||||
|
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return
|
||||||
|
log.warn('Patching...')
|
||||||
|
# let's create a fake egg replacing setuptools one
|
||||||
|
res = _patch_egg_dir(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
log.warn('Patching complete.')
|
||||||
|
_relaunch()
|
||||||
|
|
||||||
|
|
||||||
|
def _relaunch():
|
||||||
|
log.warn('Relaunching...')
|
||||||
|
# we have to relaunch the process
|
||||||
|
# pip marker to avoid a relaunch bug
|
||||||
|
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||||
|
_cmd2 = ['-c', 'install', '--record']
|
||||||
|
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||||
|
sys.argv[0] = 'setup.py'
|
||||||
|
args = [sys.executable] + sys.argv
|
||||||
|
sys.exit(subprocess.call(args))
|
||||||
|
|
||||||
|
|
||||||
|
def _extractall(self, path=".", members=None):
|
||||||
|
"""Extract all members from the archive to the current working
|
||||||
|
directory and set owner, modification time and permissions on
|
||||||
|
directories afterwards. `path' specifies a different directory
|
||||||
|
to extract to. `members' is optional and must be a subset of the
|
||||||
|
list returned by getmembers().
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
import operator
|
||||||
|
from tarfile import ExtractError
|
||||||
|
directories = []
|
||||||
|
|
||||||
|
if members is None:
|
||||||
|
members = self
|
||||||
|
|
||||||
|
for tarinfo in members:
|
||||||
|
if tarinfo.isdir():
|
||||||
|
# Extract directories with a safe mode.
|
||||||
|
directories.append(tarinfo)
|
||||||
|
tarinfo = copy.copy(tarinfo)
|
||||||
|
tarinfo.mode = 448 # decimal for oct 0700
|
||||||
|
self.extract(tarinfo, path)
|
||||||
|
|
||||||
|
# Reverse sort directories.
|
||||||
|
if sys.version_info < (2, 4):
|
||||||
|
def sorter(dir1, dir2):
|
||||||
|
return cmp(dir1.name, dir2.name)
|
||||||
|
directories.sort(sorter)
|
||||||
|
directories.reverse()
|
||||||
|
else:
|
||||||
|
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||||
|
|
||||||
|
# Set correct owner, mtime and filemode on directories.
|
||||||
|
for tarinfo in directories:
|
||||||
|
dirpath = os.path.join(path, tarinfo.name)
|
||||||
|
try:
|
||||||
|
self.chown(tarinfo, dirpath)
|
||||||
|
self.utime(tarinfo, dirpath)
|
||||||
|
self.chmod(tarinfo, dirpath)
|
||||||
|
except ExtractError:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if self.errorlevel > 1:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self._dbg(1, "tarfile: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_install_args(options):
|
||||||
|
"""
|
||||||
|
Build the arguments to 'python setup.py install' on the distribute package
|
||||||
|
"""
|
||||||
|
install_args = []
|
||||||
|
if options.user_install:
|
||||||
|
if sys.version_info < (2, 6):
|
||||||
|
log.warn("--user requires Python 2.6 or later")
|
||||||
|
raise SystemExit(1)
|
||||||
|
install_args.append('--user')
|
||||||
|
return install_args
|
||||||
|
|
||||||
|
def _parse_args():
|
||||||
|
"""
|
||||||
|
Parse the command line for options
|
||||||
|
"""
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'--user', dest='user_install', action='store_true', default=False,
|
||||||
|
help='install in user site package (requires Python 2.6 or later)')
|
||||||
|
parser.add_option(
|
||||||
|
'--download-base', dest='download_base', metavar="URL",
|
||||||
|
default=DEFAULT_URL,
|
||||||
|
help='alternative URL from where to download the distribute package')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
# positional arguments are ignored
|
||||||
|
return options
|
||||||
|
|
||||||
|
def main(version=DEFAULT_VERSION):
|
||||||
|
"""Install or upgrade setuptools and EasyInstall"""
|
||||||
|
options = _parse_args()
|
||||||
|
tarball = download_setuptools(download_base=options.download_base)
|
||||||
|
return _install(tarball, _build_install_args(options))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
|
@ -49,6 +49,11 @@ class MjpegStreamingConsumerInterface(object):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
class MjpegStreamingServer(QTcpServer):
|
class MjpegStreamingServer(QTcpServer):
|
||||||
|
"""A simple async http class which provides a mjpeg stream and if found,
|
||||||
|
an index.html file containing the mjpeg stream.
|
||||||
|
|
||||||
|
Parent should implement the interface 'MjpegStreamingConsumerInterface'
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, server_address, parent=None, fps=12.5):
|
def __init__(self, server_address, parent=None, fps=12.5):
|
||||||
super(MjpegStreamingServer, self).__init__(parent)
|
super(MjpegStreamingServer, self).__init__(parent)
|
||||||
|
@ -73,7 +78,8 @@ class MjpegStreamingServer(QTcpServer):
|
||||||
sock = self.sender()
|
sock = self.sender()
|
||||||
sock_id = id(sock)
|
sock_id = id(sock)
|
||||||
logger.info("handle_request: sock_id=%r", sock_id)
|
logger.info("handle_request: sock_id=%r", sock_id)
|
||||||
if sock.state() in (QTcpSocket.UnconnectedState, QTcpSocket.ClosingState):
|
if sock.state() in (
|
||||||
|
QTcpSocket.UnconnectedState, QTcpSocket.ClosingState):
|
||||||
logger.info("connection closed")
|
logger.info("connection closed")
|
||||||
self.sockets.remove(sock)
|
self.sockets.remove(sock)
|
||||||
sock.deleteLater()
|
sock.deleteLater()
|
||||||
|
@ -85,7 +91,9 @@ class MjpegStreamingServer(QTcpServer):
|
||||||
logger.info("first line: %r", line)
|
logger.info("first line: %r", line)
|
||||||
try:
|
try:
|
||||||
resource, ext, http_version = self.get_regex.match(line).groups()
|
resource, ext, http_version = self.get_regex.match(line).groups()
|
||||||
logger.info("resource=%r, ext=%r, http_version=%r", resource, ext, http_version)
|
logger.info(
|
||||||
|
"resource=%r, ext=%r, http_version=%r",
|
||||||
|
resource, ext, http_version)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
try:
|
try:
|
||||||
host, port = self.host_regex.match(line).groups()
|
host, port = self.host_regex.match(line).groups()
|
||||||
|
@ -101,24 +109,30 @@ class MjpegStreamingServer(QTcpServer):
|
||||||
if ext == "ico":
|
if ext == "ico":
|
||||||
directory = self.widget.pubdir()
|
directory = self.widget.pubdir()
|
||||||
try:
|
try:
|
||||||
data = open(os.path.join(directory, "favicon.ico"), "rb").read()
|
data = open(
|
||||||
|
os.path.join(directory, "favicon.ico"), "rb").read()
|
||||||
except IOError:
|
except IOError:
|
||||||
logger.error("request not found/handled - sending 404 not found")
|
logger.error(
|
||||||
|
"request not found/handled - sending 404 not found")
|
||||||
sock.write("HTTP/1.1 404 Not Found\r\n")
|
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type: image/x-ico\r\n\r\n%s' % data))
|
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type:' \
|
||||||
|
'image/x-ico\r\n\r\n%s' % data))
|
||||||
elif ext == "html":
|
elif ext == "html":
|
||||||
directory = self.widget.pubdir()
|
directory = self.widget.pubdir()
|
||||||
try:
|
try:
|
||||||
data = open(os.path.join(directory, "index.html"), "rb").read() % sock_id
|
data = open(os.path.join(
|
||||||
|
directory, "index.html"), "rb").read() % sock_id
|
||||||
self.html_map[sock_id] = None
|
self.html_map[sock_id] = None
|
||||||
except IOError:
|
except IOError:
|
||||||
logger.error("request not found/handled - sending 404 not found")
|
logger.error(
|
||||||
|
"request not found/handled - sending 404 not found")
|
||||||
sock.write("HTTP/1.1 404 Not Found\r\n")
|
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type: text/html;encoding: utf-8\r\n\r\n%s' % data))
|
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type:"\
|
||||||
|
"text/html;encoding: utf-8\r\n\r\n%s' % data))
|
||||||
elif ext == "mjpeg":
|
elif ext == "mjpeg":
|
||||||
try:
|
try:
|
||||||
_, html_sock_id = resource.split("_", 1)
|
_, html_sock_id = resource.split("_", 1)
|
||||||
|
@ -131,9 +145,12 @@ class MjpegStreamingServer(QTcpServer):
|
||||||
if html_sock_id is not None:
|
if html_sock_id is not None:
|
||||||
self.html_map[html_sock_id] = sock
|
self.html_map[html_sock_id] = sock
|
||||||
self.stream_clients.append(sock)
|
self.stream_clients.append(sock)
|
||||||
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type: multipart/x-mixed-replace; boundary=--2342\r\n\r\n'))
|
sock.write(QByteArray('HTTP/1.1 200 Ok\r\n" \
|
||||||
|
"Content-Type: multipart/x-mixed-replace;" \
|
||||||
|
"boundary=--2342\r\n\r\n'))
|
||||||
else:
|
else:
|
||||||
logger.error("request not found/handled - sending 404 not found")
|
logger.error(
|
||||||
|
"request not found/handled - sending 404 not found")
|
||||||
sock.write("HTTP/1.1 404 Not Found\r\n")
|
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||||
|
|
||||||
def slot_remove_connection(self):
|
def slot_remove_connection(self):
|
||||||
|
@ -155,43 +172,45 @@ class MjpegStreamingServer(QTcpServer):
|
||||||
except ValueError, msg:
|
except ValueError, msg:
|
||||||
logger.info("connection %r was not stored?", sock_id)
|
logger.info("connection %r was not stored?", sock_id)
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.stream_clients.remove(sock)
|
self.stream_clients.remove(sock)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.info("connection %r was not streaming", sock_id)
|
logger.info("connection %r was not streaming", sock_id)
|
||||||
|
|
||||||
|
# cleaning up streaming connections if that sock is serving index.html
|
||||||
try:
|
try:
|
||||||
stream_client = self.html_map.pop(sock_id)
|
stream_client = self.html_map.pop(sock_id)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logger.info("socket %r has no child socket", sock_id)
|
logger.info("connection %r has no child connections", sock_id)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
stream_client.close()
|
stream_client.close()
|
||||||
|
stream_client.deleteLater()
|
||||||
except AttributeError, msg:
|
except AttributeError, msg:
|
||||||
logger.info("no stream client")
|
logger.info("no stream client")
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self.stream_clients.remove(stream_client)
|
self.stream_clients.remove(stream_client)
|
||||||
logger.info("child connection %r removed from streaming", id(stream_client))
|
logger.info("child connection %r removed from streaming",
|
||||||
|
id(stream_client))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.sockets.remove(stream_client)
|
self.sockets.remove(stream_client)
|
||||||
logger.info("child connection %r removed from storage", id(stream_client))
|
logger.info("child connection %r removed from storage",
|
||||||
|
id(stream_client))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def send_image(self):
|
def send_image(self):
|
||||||
if not self.stream_clients:
|
if not self.stream_clients:
|
||||||
return
|
return
|
||||||
|
|
||||||
img_data = self.widget.render_image()
|
img_data = self.widget.render_image()
|
||||||
len_data = len(img_data)
|
len_data = len(img_data)
|
||||||
array = QByteArray("--2342\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len_data, img_data))
|
array = QByteArray("--2342\r\nContent-Type: image/jpeg\r\n" \
|
||||||
|
"Content-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len_data, img_data))
|
||||||
for sock in self.stream_clients:
|
for sock in self.stream_clients:
|
||||||
sock.write(array)
|
sock.write(array)
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from distribute_setup import use_setuptools
|
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
@ -12,7 +9,7 @@ if sys.version_info >= (3,):
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='psylib',
|
name='psylib',
|
||||||
version="0.1",
|
version="0.2",
|
||||||
packages=find_packages(exclude=["scripts",]),
|
packages=find_packages(exclude=["scripts",]),
|
||||||
|
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
|
|
|
@ -0,0 +1,556 @@
|
||||||
|
#!python
|
||||||
|
"""Bootstrap distribute installation
|
||||||
|
|
||||||
|
If you want to use setuptools in your package's setup.py, just include this
|
||||||
|
file in the same directory with it, and add this to the top of your setup.py::
|
||||||
|
|
||||||
|
from distribute_setup import use_setuptools
|
||||||
|
use_setuptools()
|
||||||
|
|
||||||
|
If you want to require a specific version of setuptools, set a download
|
||||||
|
mirror, or use an alternate download directory, you can do so by supplying
|
||||||
|
the appropriate options to ``use_setuptools()``.
|
||||||
|
|
||||||
|
This file can also be run as a script to install or upgrade setuptools.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import fnmatch
|
||||||
|
import tempfile
|
||||||
|
import tarfile
|
||||||
|
import optparse
|
||||||
|
|
||||||
|
from distutils import log
|
||||||
|
|
||||||
|
try:
|
||||||
|
from site import USER_SITE
|
||||||
|
except ImportError:
|
||||||
|
USER_SITE = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
return subprocess.call(args) == 0
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# will be used for python 2.3
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
# quoting arguments if windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
def quote(arg):
|
||||||
|
if ' ' in arg:
|
||||||
|
return '"%s"' % arg
|
||||||
|
return arg
|
||||||
|
args = [quote(arg) for arg in args]
|
||||||
|
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||||
|
|
||||||
|
DEFAULT_VERSION = "0.6.49"
|
||||||
|
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||||
|
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||||
|
|
||||||
|
SETUPTOOLS_PKG_INFO = """\
|
||||||
|
Metadata-Version: 1.0
|
||||||
|
Name: setuptools
|
||||||
|
Version: %s
|
||||||
|
Summary: xxxx
|
||||||
|
Home-page: xxx
|
||||||
|
Author: xxx
|
||||||
|
Author-email: xxx
|
||||||
|
License: xxx
|
||||||
|
Description: xxx
|
||||||
|
""" % SETUPTOOLS_FAKED_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def _install(tarball, install_args=()):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# installing
|
||||||
|
log.warn('Installing Distribute')
|
||||||
|
if not _python_cmd('setup.py', 'install', *install_args):
|
||||||
|
log.warn('Something went wrong during the installation.')
|
||||||
|
log.warn('See the error message above.')
|
||||||
|
# exitcode will be 2
|
||||||
|
return 2
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_egg(egg, tarball, to_dir):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# building an egg
|
||||||
|
log.warn('Building a Distribute egg in %s', to_dir)
|
||||||
|
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
# returning the result
|
||||||
|
log.warn(egg)
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
raise IOError('Could not build the egg.')
|
||||||
|
|
||||||
|
|
||||||
|
def _do_download(version, download_base, to_dir, download_delay):
|
||||||
|
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||||
|
% (version, sys.version_info[0], sys.version_info[1]))
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
tarball = download_setuptools(version, download_base,
|
||||||
|
to_dir, download_delay)
|
||||||
|
_build_egg(egg, tarball, to_dir)
|
||||||
|
sys.path.insert(0, egg)
|
||||||
|
import setuptools
|
||||||
|
setuptools.bootstrap_install_from = egg
|
||||||
|
|
||||||
|
|
||||||
|
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
was_imported = 'pkg_resources' in sys.modules or \
|
||||||
|
'setuptools' in sys.modules
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
# Setuptools 0.7b and later is a suitable (and preferable)
|
||||||
|
# substitute for any Distribute version.
|
||||||
|
try:
|
||||||
|
pkg_resources.require("setuptools>=0.7b")
|
||||||
|
return
|
||||||
|
except (pkg_resources.DistributionNotFound,
|
||||||
|
pkg_resources.VersionConflict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not hasattr(pkg_resources, '_distribute'):
|
||||||
|
if not no_fake:
|
||||||
|
_fake_setuptools()
|
||||||
|
raise ImportError
|
||||||
|
except ImportError:
|
||||||
|
return _do_download(version, download_base, to_dir, download_delay)
|
||||||
|
try:
|
||||||
|
pkg_resources.require("distribute>=" + version)
|
||||||
|
return
|
||||||
|
except pkg_resources.VersionConflict:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if was_imported:
|
||||||
|
sys.stderr.write(
|
||||||
|
"The required version of distribute (>=%s) is not available,\n"
|
||||||
|
"and can't be installed while this script is running. Please\n"
|
||||||
|
"install a more recent version first, using\n"
|
||||||
|
"'easy_install -U distribute'."
|
||||||
|
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
except pkg_resources.DistributionNotFound:
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
finally:
|
||||||
|
if not no_fake:
|
||||||
|
_create_fake_setuptools_pkg_info(to_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, delay=15):
|
||||||
|
"""Download distribute from a specified location and return its filename
|
||||||
|
|
||||||
|
`version` should be a valid distribute version number that is available
|
||||||
|
as an egg for download under the `download_base` URL (which should end
|
||||||
|
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||||
|
`delay` is the number of seconds to pause before an actual download
|
||||||
|
attempt.
|
||||||
|
"""
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
try:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
except ImportError:
|
||||||
|
from urllib2 import urlopen
|
||||||
|
tgz_name = "distribute-%s.tar.gz" % version
|
||||||
|
url = download_base + tgz_name
|
||||||
|
saveto = os.path.join(to_dir, tgz_name)
|
||||||
|
src = dst = None
|
||||||
|
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||||
|
try:
|
||||||
|
log.warn("Downloading %s", url)
|
||||||
|
src = urlopen(url)
|
||||||
|
# Read/write all in one block, so we don't create a corrupt file
|
||||||
|
# if the download is interrupted.
|
||||||
|
data = src.read()
|
||||||
|
dst = open(saveto, "wb")
|
||||||
|
dst.write(data)
|
||||||
|
finally:
|
||||||
|
if src:
|
||||||
|
src.close()
|
||||||
|
if dst:
|
||||||
|
dst.close()
|
||||||
|
return os.path.realpath(saveto)
|
||||||
|
|
||||||
|
|
||||||
|
def _no_sandbox(function):
|
||||||
|
def __no_sandbox(*args, **kw):
|
||||||
|
try:
|
||||||
|
from setuptools.sandbox import DirectorySandbox
|
||||||
|
if not hasattr(DirectorySandbox, '_old'):
|
||||||
|
def violation(*args):
|
||||||
|
pass
|
||||||
|
DirectorySandbox._old = DirectorySandbox._violation
|
||||||
|
DirectorySandbox._violation = violation
|
||||||
|
patched = True
|
||||||
|
else:
|
||||||
|
patched = False
|
||||||
|
except ImportError:
|
||||||
|
patched = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
return function(*args, **kw)
|
||||||
|
finally:
|
||||||
|
if patched:
|
||||||
|
DirectorySandbox._violation = DirectorySandbox._old
|
||||||
|
del DirectorySandbox._old
|
||||||
|
|
||||||
|
return __no_sandbox
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_file(path, content):
|
||||||
|
"""Will backup the file then patch it"""
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
if existing_content == content:
|
||||||
|
# already patched
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return False
|
||||||
|
log.warn('Patching...')
|
||||||
|
_rename_path(path)
|
||||||
|
f = open(path, 'w')
|
||||||
|
try:
|
||||||
|
f.write(content)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_file = _no_sandbox(_patch_file)
|
||||||
|
|
||||||
|
|
||||||
|
def _same_content(path, content):
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
return existing_content == content
|
||||||
|
|
||||||
|
|
||||||
|
def _rename_path(path):
|
||||||
|
new_name = path + '.OLD.%s' % time.time()
|
||||||
|
log.warn('Renaming %s to %s', path, new_name)
|
||||||
|
os.rename(path, new_name)
|
||||||
|
return new_name
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_flat_installation(placeholder):
|
||||||
|
if not os.path.isdir(placeholder):
|
||||||
|
log.warn('Unkown installation at %s', placeholder)
|
||||||
|
return False
|
||||||
|
found = False
|
||||||
|
for file in os.listdir(placeholder):
|
||||||
|
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
log.warn('Could not locate setuptools*.egg-info')
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Moving elements out of the way...')
|
||||||
|
pkg_info = os.path.join(placeholder, file)
|
||||||
|
if os.path.isdir(pkg_info):
|
||||||
|
patched = _patch_egg_dir(pkg_info)
|
||||||
|
else:
|
||||||
|
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||||
|
|
||||||
|
if not patched:
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
# now let's move the files out of the way
|
||||||
|
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||||
|
element = os.path.join(placeholder, element)
|
||||||
|
if os.path.exists(element):
|
||||||
|
_rename_path(element)
|
||||||
|
else:
|
||||||
|
log.warn('Could not find the %s element of the '
|
||||||
|
'Setuptools distribution', element)
|
||||||
|
return True
|
||||||
|
|
||||||
|
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||||
|
|
||||||
|
|
||||||
|
def _after_install(dist):
|
||||||
|
log.warn('After install bootstrap.')
|
||||||
|
placeholder = dist.get_command_obj('install').install_purelib
|
||||||
|
_create_fake_setuptools_pkg_info(placeholder)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_fake_setuptools_pkg_info(placeholder):
|
||||||
|
if not placeholder or not os.path.exists(placeholder):
|
||||||
|
log.warn('Could not find the install location')
|
||||||
|
return
|
||||||
|
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||||
|
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||||
|
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||||
|
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
log.warn('%s already exists', pkg_info)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Creating %s', pkg_info)
|
||||||
|
try:
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
except EnvironmentError:
|
||||||
|
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||||
|
log.warn('Creating %s', pth_file)
|
||||||
|
f = open(pth_file, 'w')
|
||||||
|
try:
|
||||||
|
f.write(os.path.join(os.curdir, setuptools_file))
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||||
|
_create_fake_setuptools_pkg_info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_egg_dir(path):
|
||||||
|
# let's check if it's already patched
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
_rename_path(path)
|
||||||
|
os.mkdir(path)
|
||||||
|
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def _before_install():
|
||||||
|
log.warn('Before install bootstrap.')
|
||||||
|
_fake_setuptools()
|
||||||
|
|
||||||
|
|
||||||
|
def _under_prefix(location):
|
||||||
|
if 'install' not in sys.argv:
|
||||||
|
return True
|
||||||
|
args = sys.argv[sys.argv.index('install') + 1:]
|
||||||
|
for index, arg in enumerate(args):
|
||||||
|
for option in ('--root', '--prefix'):
|
||||||
|
if arg.startswith('%s=' % option):
|
||||||
|
top_dir = arg.split('root=')[-1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
elif arg == option:
|
||||||
|
if len(args) > index:
|
||||||
|
top_dir = args[index + 1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
if arg == '--user' and USER_SITE is not None:
|
||||||
|
return location.startswith(USER_SITE)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _fake_setuptools():
|
||||||
|
log.warn('Scanning installed packages')
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
except ImportError:
|
||||||
|
# we're cool
|
||||||
|
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||||
|
return
|
||||||
|
ws = pkg_resources.working_set
|
||||||
|
try:
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||||
|
)
|
||||||
|
except TypeError:
|
||||||
|
# old distribute API
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools')
|
||||||
|
)
|
||||||
|
|
||||||
|
if setuptools_dist is None:
|
||||||
|
log.warn('No setuptools distribution found')
|
||||||
|
return
|
||||||
|
# detecting if it was already faked
|
||||||
|
setuptools_location = setuptools_dist.location
|
||||||
|
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||||
|
|
||||||
|
# if --root or --preix was provided, and if
|
||||||
|
# setuptools is not located in them, we don't patch it
|
||||||
|
if not _under_prefix(setuptools_location):
|
||||||
|
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||||
|
' in another location')
|
||||||
|
return
|
||||||
|
|
||||||
|
# let's see if its an egg
|
||||||
|
if not setuptools_location.endswith('.egg'):
|
||||||
|
log.warn('Non-egg installation')
|
||||||
|
res = _remove_flat_installation(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log.warn('Egg installation')
|
||||||
|
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if (os.path.exists(pkg_info) and
|
||||||
|
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return
|
||||||
|
log.warn('Patching...')
|
||||||
|
# let's create a fake egg replacing setuptools one
|
||||||
|
res = _patch_egg_dir(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
log.warn('Patching complete.')
|
||||||
|
_relaunch()
|
||||||
|
|
||||||
|
|
||||||
|
def _relaunch():
|
||||||
|
log.warn('Relaunching...')
|
||||||
|
# we have to relaunch the process
|
||||||
|
# pip marker to avoid a relaunch bug
|
||||||
|
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||||
|
_cmd2 = ['-c', 'install', '--record']
|
||||||
|
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||||
|
sys.argv[0] = 'setup.py'
|
||||||
|
args = [sys.executable] + sys.argv
|
||||||
|
sys.exit(subprocess.call(args))
|
||||||
|
|
||||||
|
|
||||||
|
def _extractall(self, path=".", members=None):
|
||||||
|
"""Extract all members from the archive to the current working
|
||||||
|
directory and set owner, modification time and permissions on
|
||||||
|
directories afterwards. `path' specifies a different directory
|
||||||
|
to extract to. `members' is optional and must be a subset of the
|
||||||
|
list returned by getmembers().
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
import operator
|
||||||
|
from tarfile import ExtractError
|
||||||
|
directories = []
|
||||||
|
|
||||||
|
if members is None:
|
||||||
|
members = self
|
||||||
|
|
||||||
|
for tarinfo in members:
|
||||||
|
if tarinfo.isdir():
|
||||||
|
# Extract directories with a safe mode.
|
||||||
|
directories.append(tarinfo)
|
||||||
|
tarinfo = copy.copy(tarinfo)
|
||||||
|
tarinfo.mode = 448 # decimal for oct 0700
|
||||||
|
self.extract(tarinfo, path)
|
||||||
|
|
||||||
|
# Reverse sort directories.
|
||||||
|
if sys.version_info < (2, 4):
|
||||||
|
def sorter(dir1, dir2):
|
||||||
|
return cmp(dir1.name, dir2.name)
|
||||||
|
directories.sort(sorter)
|
||||||
|
directories.reverse()
|
||||||
|
else:
|
||||||
|
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||||
|
|
||||||
|
# Set correct owner, mtime and filemode on directories.
|
||||||
|
for tarinfo in directories:
|
||||||
|
dirpath = os.path.join(path, tarinfo.name)
|
||||||
|
try:
|
||||||
|
self.chown(tarinfo, dirpath)
|
||||||
|
self.utime(tarinfo, dirpath)
|
||||||
|
self.chmod(tarinfo, dirpath)
|
||||||
|
except ExtractError:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if self.errorlevel > 1:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self._dbg(1, "tarfile: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_install_args(options):
|
||||||
|
"""
|
||||||
|
Build the arguments to 'python setup.py install' on the distribute package
|
||||||
|
"""
|
||||||
|
install_args = []
|
||||||
|
if options.user_install:
|
||||||
|
if sys.version_info < (2, 6):
|
||||||
|
log.warn("--user requires Python 2.6 or later")
|
||||||
|
raise SystemExit(1)
|
||||||
|
install_args.append('--user')
|
||||||
|
return install_args
|
||||||
|
|
||||||
|
def _parse_args():
|
||||||
|
"""
|
||||||
|
Parse the command line for options
|
||||||
|
"""
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'--user', dest='user_install', action='store_true', default=False,
|
||||||
|
help='install in user site package (requires Python 2.6 or later)')
|
||||||
|
parser.add_option(
|
||||||
|
'--download-base', dest='download_base', metavar="URL",
|
||||||
|
default=DEFAULT_URL,
|
||||||
|
help='alternative URL from where to download the distribute package')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
# positional arguments are ignored
|
||||||
|
return options
|
||||||
|
|
||||||
|
def main(version=DEFAULT_VERSION):
|
||||||
|
"""Install or upgrade setuptools and EasyInstall"""
|
||||||
|
options = _parse_args()
|
||||||
|
tarball = download_setuptools(download_base=options.download_base)
|
||||||
|
return _install(tarball, _build_install_args(options))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
|
@ -0,0 +1,556 @@
|
||||||
|
#!python
|
||||||
|
"""Bootstrap distribute installation
|
||||||
|
|
||||||
|
If you want to use setuptools in your package's setup.py, just include this
|
||||||
|
file in the same directory with it, and add this to the top of your setup.py::
|
||||||
|
|
||||||
|
from distribute_setup import use_setuptools
|
||||||
|
use_setuptools()
|
||||||
|
|
||||||
|
If you want to require a specific version of setuptools, set a download
|
||||||
|
mirror, or use an alternate download directory, you can do so by supplying
|
||||||
|
the appropriate options to ``use_setuptools()``.
|
||||||
|
|
||||||
|
This file can also be run as a script to install or upgrade setuptools.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import fnmatch
|
||||||
|
import tempfile
|
||||||
|
import tarfile
|
||||||
|
import optparse
|
||||||
|
|
||||||
|
from distutils import log
|
||||||
|
|
||||||
|
try:
|
||||||
|
from site import USER_SITE
|
||||||
|
except ImportError:
|
||||||
|
USER_SITE = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
return subprocess.call(args) == 0
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# will be used for python 2.3
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
# quoting arguments if windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
def quote(arg):
|
||||||
|
if ' ' in arg:
|
||||||
|
return '"%s"' % arg
|
||||||
|
return arg
|
||||||
|
args = [quote(arg) for arg in args]
|
||||||
|
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||||
|
|
||||||
|
DEFAULT_VERSION = "0.6.49"
|
||||||
|
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||||
|
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||||
|
|
||||||
|
SETUPTOOLS_PKG_INFO = """\
|
||||||
|
Metadata-Version: 1.0
|
||||||
|
Name: setuptools
|
||||||
|
Version: %s
|
||||||
|
Summary: xxxx
|
||||||
|
Home-page: xxx
|
||||||
|
Author: xxx
|
||||||
|
Author-email: xxx
|
||||||
|
License: xxx
|
||||||
|
Description: xxx
|
||||||
|
""" % SETUPTOOLS_FAKED_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def _install(tarball, install_args=()):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# installing
|
||||||
|
log.warn('Installing Distribute')
|
||||||
|
if not _python_cmd('setup.py', 'install', *install_args):
|
||||||
|
log.warn('Something went wrong during the installation.')
|
||||||
|
log.warn('See the error message above.')
|
||||||
|
# exitcode will be 2
|
||||||
|
return 2
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_egg(egg, tarball, to_dir):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# building an egg
|
||||||
|
log.warn('Building a Distribute egg in %s', to_dir)
|
||||||
|
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
# returning the result
|
||||||
|
log.warn(egg)
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
raise IOError('Could not build the egg.')
|
||||||
|
|
||||||
|
|
||||||
|
def _do_download(version, download_base, to_dir, download_delay):
|
||||||
|
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||||
|
% (version, sys.version_info[0], sys.version_info[1]))
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
tarball = download_setuptools(version, download_base,
|
||||||
|
to_dir, download_delay)
|
||||||
|
_build_egg(egg, tarball, to_dir)
|
||||||
|
sys.path.insert(0, egg)
|
||||||
|
import setuptools
|
||||||
|
setuptools.bootstrap_install_from = egg
|
||||||
|
|
||||||
|
|
||||||
|
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
was_imported = 'pkg_resources' in sys.modules or \
|
||||||
|
'setuptools' in sys.modules
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
# Setuptools 0.7b and later is a suitable (and preferable)
|
||||||
|
# substitute for any Distribute version.
|
||||||
|
try:
|
||||||
|
pkg_resources.require("setuptools>=0.7b")
|
||||||
|
return
|
||||||
|
except (pkg_resources.DistributionNotFound,
|
||||||
|
pkg_resources.VersionConflict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not hasattr(pkg_resources, '_distribute'):
|
||||||
|
if not no_fake:
|
||||||
|
_fake_setuptools()
|
||||||
|
raise ImportError
|
||||||
|
except ImportError:
|
||||||
|
return _do_download(version, download_base, to_dir, download_delay)
|
||||||
|
try:
|
||||||
|
pkg_resources.require("distribute>=" + version)
|
||||||
|
return
|
||||||
|
except pkg_resources.VersionConflict:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if was_imported:
|
||||||
|
sys.stderr.write(
|
||||||
|
"The required version of distribute (>=%s) is not available,\n"
|
||||||
|
"and can't be installed while this script is running. Please\n"
|
||||||
|
"install a more recent version first, using\n"
|
||||||
|
"'easy_install -U distribute'."
|
||||||
|
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
except pkg_resources.DistributionNotFound:
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
finally:
|
||||||
|
if not no_fake:
|
||||||
|
_create_fake_setuptools_pkg_info(to_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, delay=15):
|
||||||
|
"""Download distribute from a specified location and return its filename
|
||||||
|
|
||||||
|
`version` should be a valid distribute version number that is available
|
||||||
|
as an egg for download under the `download_base` URL (which should end
|
||||||
|
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||||
|
`delay` is the number of seconds to pause before an actual download
|
||||||
|
attempt.
|
||||||
|
"""
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
try:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
except ImportError:
|
||||||
|
from urllib2 import urlopen
|
||||||
|
tgz_name = "distribute-%s.tar.gz" % version
|
||||||
|
url = download_base + tgz_name
|
||||||
|
saveto = os.path.join(to_dir, tgz_name)
|
||||||
|
src = dst = None
|
||||||
|
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||||
|
try:
|
||||||
|
log.warn("Downloading %s", url)
|
||||||
|
src = urlopen(url)
|
||||||
|
# Read/write all in one block, so we don't create a corrupt file
|
||||||
|
# if the download is interrupted.
|
||||||
|
data = src.read()
|
||||||
|
dst = open(saveto, "wb")
|
||||||
|
dst.write(data)
|
||||||
|
finally:
|
||||||
|
if src:
|
||||||
|
src.close()
|
||||||
|
if dst:
|
||||||
|
dst.close()
|
||||||
|
return os.path.realpath(saveto)
|
||||||
|
|
||||||
|
|
||||||
|
def _no_sandbox(function):
|
||||||
|
def __no_sandbox(*args, **kw):
|
||||||
|
try:
|
||||||
|
from setuptools.sandbox import DirectorySandbox
|
||||||
|
if not hasattr(DirectorySandbox, '_old'):
|
||||||
|
def violation(*args):
|
||||||
|
pass
|
||||||
|
DirectorySandbox._old = DirectorySandbox._violation
|
||||||
|
DirectorySandbox._violation = violation
|
||||||
|
patched = True
|
||||||
|
else:
|
||||||
|
patched = False
|
||||||
|
except ImportError:
|
||||||
|
patched = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
return function(*args, **kw)
|
||||||
|
finally:
|
||||||
|
if patched:
|
||||||
|
DirectorySandbox._violation = DirectorySandbox._old
|
||||||
|
del DirectorySandbox._old
|
||||||
|
|
||||||
|
return __no_sandbox
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_file(path, content):
|
||||||
|
"""Will backup the file then patch it"""
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
if existing_content == content:
|
||||||
|
# already patched
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return False
|
||||||
|
log.warn('Patching...')
|
||||||
|
_rename_path(path)
|
||||||
|
f = open(path, 'w')
|
||||||
|
try:
|
||||||
|
f.write(content)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_file = _no_sandbox(_patch_file)
|
||||||
|
|
||||||
|
|
||||||
|
def _same_content(path, content):
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
return existing_content == content
|
||||||
|
|
||||||
|
|
||||||
|
def _rename_path(path):
|
||||||
|
new_name = path + '.OLD.%s' % time.time()
|
||||||
|
log.warn('Renaming %s to %s', path, new_name)
|
||||||
|
os.rename(path, new_name)
|
||||||
|
return new_name
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_flat_installation(placeholder):
|
||||||
|
if not os.path.isdir(placeholder):
|
||||||
|
log.warn('Unkown installation at %s', placeholder)
|
||||||
|
return False
|
||||||
|
found = False
|
||||||
|
for file in os.listdir(placeholder):
|
||||||
|
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
log.warn('Could not locate setuptools*.egg-info')
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Moving elements out of the way...')
|
||||||
|
pkg_info = os.path.join(placeholder, file)
|
||||||
|
if os.path.isdir(pkg_info):
|
||||||
|
patched = _patch_egg_dir(pkg_info)
|
||||||
|
else:
|
||||||
|
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||||
|
|
||||||
|
if not patched:
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
# now let's move the files out of the way
|
||||||
|
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||||
|
element = os.path.join(placeholder, element)
|
||||||
|
if os.path.exists(element):
|
||||||
|
_rename_path(element)
|
||||||
|
else:
|
||||||
|
log.warn('Could not find the %s element of the '
|
||||||
|
'Setuptools distribution', element)
|
||||||
|
return True
|
||||||
|
|
||||||
|
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||||
|
|
||||||
|
|
||||||
|
def _after_install(dist):
|
||||||
|
log.warn('After install bootstrap.')
|
||||||
|
placeholder = dist.get_command_obj('install').install_purelib
|
||||||
|
_create_fake_setuptools_pkg_info(placeholder)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_fake_setuptools_pkg_info(placeholder):
|
||||||
|
if not placeholder or not os.path.exists(placeholder):
|
||||||
|
log.warn('Could not find the install location')
|
||||||
|
return
|
||||||
|
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||||
|
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||||
|
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||||
|
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
log.warn('%s already exists', pkg_info)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Creating %s', pkg_info)
|
||||||
|
try:
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
except EnvironmentError:
|
||||||
|
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||||
|
log.warn('Creating %s', pth_file)
|
||||||
|
f = open(pth_file, 'w')
|
||||||
|
try:
|
||||||
|
f.write(os.path.join(os.curdir, setuptools_file))
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||||
|
_create_fake_setuptools_pkg_info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_egg_dir(path):
|
||||||
|
# let's check if it's already patched
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
_rename_path(path)
|
||||||
|
os.mkdir(path)
|
||||||
|
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def _before_install():
|
||||||
|
log.warn('Before install bootstrap.')
|
||||||
|
_fake_setuptools()
|
||||||
|
|
||||||
|
|
||||||
|
def _under_prefix(location):
|
||||||
|
if 'install' not in sys.argv:
|
||||||
|
return True
|
||||||
|
args = sys.argv[sys.argv.index('install') + 1:]
|
||||||
|
for index, arg in enumerate(args):
|
||||||
|
for option in ('--root', '--prefix'):
|
||||||
|
if arg.startswith('%s=' % option):
|
||||||
|
top_dir = arg.split('root=')[-1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
elif arg == option:
|
||||||
|
if len(args) > index:
|
||||||
|
top_dir = args[index + 1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
if arg == '--user' and USER_SITE is not None:
|
||||||
|
return location.startswith(USER_SITE)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _fake_setuptools():
|
||||||
|
log.warn('Scanning installed packages')
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
except ImportError:
|
||||||
|
# we're cool
|
||||||
|
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||||
|
return
|
||||||
|
ws = pkg_resources.working_set
|
||||||
|
try:
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||||
|
)
|
||||||
|
except TypeError:
|
||||||
|
# old distribute API
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools')
|
||||||
|
)
|
||||||
|
|
||||||
|
if setuptools_dist is None:
|
||||||
|
log.warn('No setuptools distribution found')
|
||||||
|
return
|
||||||
|
# detecting if it was already faked
|
||||||
|
setuptools_location = setuptools_dist.location
|
||||||
|
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||||
|
|
||||||
|
# if --root or --preix was provided, and if
|
||||||
|
# setuptools is not located in them, we don't patch it
|
||||||
|
if not _under_prefix(setuptools_location):
|
||||||
|
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||||
|
' in another location')
|
||||||
|
return
|
||||||
|
|
||||||
|
# let's see if its an egg
|
||||||
|
if not setuptools_location.endswith('.egg'):
|
||||||
|
log.warn('Non-egg installation')
|
||||||
|
res = _remove_flat_installation(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log.warn('Egg installation')
|
||||||
|
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if (os.path.exists(pkg_info) and
|
||||||
|
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return
|
||||||
|
log.warn('Patching...')
|
||||||
|
# let's create a fake egg replacing setuptools one
|
||||||
|
res = _patch_egg_dir(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
log.warn('Patching complete.')
|
||||||
|
_relaunch()
|
||||||
|
|
||||||
|
|
||||||
|
def _relaunch():
|
||||||
|
log.warn('Relaunching...')
|
||||||
|
# we have to relaunch the process
|
||||||
|
# pip marker to avoid a relaunch bug
|
||||||
|
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||||
|
_cmd2 = ['-c', 'install', '--record']
|
||||||
|
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||||
|
sys.argv[0] = 'setup.py'
|
||||||
|
args = [sys.executable] + sys.argv
|
||||||
|
sys.exit(subprocess.call(args))
|
||||||
|
|
||||||
|
|
||||||
|
def _extractall(self, path=".", members=None):
|
||||||
|
"""Extract all members from the archive to the current working
|
||||||
|
directory and set owner, modification time and permissions on
|
||||||
|
directories afterwards. `path' specifies a different directory
|
||||||
|
to extract to. `members' is optional and must be a subset of the
|
||||||
|
list returned by getmembers().
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
import operator
|
||||||
|
from tarfile import ExtractError
|
||||||
|
directories = []
|
||||||
|
|
||||||
|
if members is None:
|
||||||
|
members = self
|
||||||
|
|
||||||
|
for tarinfo in members:
|
||||||
|
if tarinfo.isdir():
|
||||||
|
# Extract directories with a safe mode.
|
||||||
|
directories.append(tarinfo)
|
||||||
|
tarinfo = copy.copy(tarinfo)
|
||||||
|
tarinfo.mode = 448 # decimal for oct 0700
|
||||||
|
self.extract(tarinfo, path)
|
||||||
|
|
||||||
|
# Reverse sort directories.
|
||||||
|
if sys.version_info < (2, 4):
|
||||||
|
def sorter(dir1, dir2):
|
||||||
|
return cmp(dir1.name, dir2.name)
|
||||||
|
directories.sort(sorter)
|
||||||
|
directories.reverse()
|
||||||
|
else:
|
||||||
|
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||||
|
|
||||||
|
# Set correct owner, mtime and filemode on directories.
|
||||||
|
for tarinfo in directories:
|
||||||
|
dirpath = os.path.join(path, tarinfo.name)
|
||||||
|
try:
|
||||||
|
self.chown(tarinfo, dirpath)
|
||||||
|
self.utime(tarinfo, dirpath)
|
||||||
|
self.chmod(tarinfo, dirpath)
|
||||||
|
except ExtractError:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if self.errorlevel > 1:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self._dbg(1, "tarfile: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_install_args(options):
|
||||||
|
"""
|
||||||
|
Build the arguments to 'python setup.py install' on the distribute package
|
||||||
|
"""
|
||||||
|
install_args = []
|
||||||
|
if options.user_install:
|
||||||
|
if sys.version_info < (2, 6):
|
||||||
|
log.warn("--user requires Python 2.6 or later")
|
||||||
|
raise SystemExit(1)
|
||||||
|
install_args.append('--user')
|
||||||
|
return install_args
|
||||||
|
|
||||||
|
def _parse_args():
|
||||||
|
"""
|
||||||
|
Parse the command line for options
|
||||||
|
"""
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'--user', dest='user_install', action='store_true', default=False,
|
||||||
|
help='install in user site package (requires Python 2.6 or later)')
|
||||||
|
parser.add_option(
|
||||||
|
'--download-base', dest='download_base', metavar="URL",
|
||||||
|
default=DEFAULT_URL,
|
||||||
|
help='alternative URL from where to download the distribute package')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
# positional arguments are ignored
|
||||||
|
return options
|
||||||
|
|
||||||
|
def main(version=DEFAULT_VERSION):
|
||||||
|
"""Install or upgrade setuptools and EasyInstall"""
|
||||||
|
options = _parse_args()
|
||||||
|
tarball = download_setuptools(download_base=options.download_base)
|
||||||
|
return _install(tarball, _build_install_args(options))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
|
@ -1,9 +1,6 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from distribute_setup import use_setuptools
|
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
@ -12,11 +9,13 @@ if sys.version_info >= (3,):
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='texter',
|
name='texter',
|
||||||
version="0.1",
|
version="0.2",
|
||||||
packages=find_packages(exclude=["scripts",]),
|
packages=find_packages(exclude=["scripts",]),
|
||||||
|
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
|
|
||||||
|
install_requires = ["psylib"],
|
||||||
|
|
||||||
package_data = {
|
package_data = {
|
||||||
"texter" : ["*.ui", "*.qrc", "*.png", "*.ico", "*.html"]},
|
"texter" : ["*.ui", "*.qrc", "*.png", "*.ico", "*.html"]},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue