Better support for frozen environments:

- integrated Cristian Gavin's replacement for os.listdir
  - added replacement for os.isdir
Fixed ViewBox generating error messages at shutdown
This commit is contained in:
Luke Campagnola 2012-10-11 01:26:44 -04:00
commit ad7645c9c5
7 changed files with 147 additions and 58 deletions

View File

@ -104,36 +104,61 @@ def renamePyc(startDir):
import os import os
path = os.path.split(__file__)[0] path = os.path.split(__file__)[0]
renamePyc(path) if not hasattr(sys, 'frozen'): ## If we are frozen, there's a good chance we don't have the original .py files anymore.
renamePyc(path)
## Import almost everything to make it available from a single namespace ## Import almost everything to make it available from a single namespace
## don't import the more complex systems--canvas, parametertree, flowchart, dockarea ## don't import the more complex systems--canvas, parametertree, flowchart, dockarea
## these must be imported separately. ## these must be imported separately.
import frozenSupport
def importAll(path, excludes=()): def importModules(path, globals, locals, excludes=()):
d = os.path.join(os.path.split(__file__)[0], path) """Import all modules residing within *path*, return a dict of name: module pairs.
files = []
for f in os.listdir(d): Note that *path* MUST be relative to the module doing the import.
if os.path.isdir(os.path.join(d, f)) and f != '__pycache__': """
files.append(f) d = os.path.join(os.path.split(globals['__file__'])[0], path)
files = set()
for f in frozenSupport.listdir(d):
if frozenSupport.isdir(os.path.join(d, f)) and f != '__pycache__':
files.add(f)
elif f[-3:] == '.py' and f != '__init__.py': elif f[-3:] == '.py' and f != '__init__.py':
files.append(f[:-3]) files.add(f[:-3])
elif f[-4:] == '.pyc' and f != '__init__.pyc':
files.add(f[:-4])
mods = {}
path = path.replace(os.sep, '.')
for modName in files: for modName in files:
if modName in excludes: if modName in excludes:
continue continue
mod = __import__(path+"."+modName, globals(), locals(), fromlist=['*']) try:
if len(path) > 0:
modName = path + '.' + modName
mod = __import__(modName, globals, locals, fromlist=['*'])
mods[modName] = mod
except:
import traceback
traceback.print_stack()
sys.excepthook(*sys.exc_info())
print("[Error importing module: %s]" % modName)
return mods
def importAll(path, globals, locals, excludes=()):
"""Given a list of modules, import all names from each module into the global namespace."""
mods = importModules(path, globals, locals, excludes)
for mod in mods.values():
if hasattr(mod, '__all__'): if hasattr(mod, '__all__'):
names = mod.__all__ names = mod.__all__
else: else:
names = [n for n in dir(mod) if n[0] != '_'] names = [n for n in dir(mod) if n[0] != '_']
for k in names: for k in names:
if hasattr(mod, k): if hasattr(mod, k):
globals()[k] = getattr(mod, k) globals[k] = getattr(mod, k)
importAll('graphicsItems') importAll('graphicsItems', globals(), locals())
importAll('widgets', excludes=['MatplotlibWidget', 'RemoteGraphicsView']) importAll('widgets', globals(), locals(), excludes=['MatplotlibWidget', 'RemoteGraphicsView'])
from .imageview import * from .imageview import *
from .WidgetGroup import * from .WidgetGroup import *

View File

@ -14,7 +14,13 @@ import time
class DateAxis(pg.AxisItem): class DateAxis(pg.AxisItem):
def tickStrings(self, values, scale, spacing): def tickStrings(self, values, scale, spacing):
return [time.strftime('%b %Y', time.localtime(x)) for x in values] strns = []
for x in values:
try:
strns.append(time.strftime('%b %Y', time.localtime(x)))
except ValueError: ## Windows can't handle dates before 1970
strns.append('')
return strns
class CustomViewBox(pg.ViewBox): class CustomViewBox(pg.ViewBox):
def __init__(self, *args, **kwds): def __init__(self, *args, **kwds):

View File

@ -1,16 +1,18 @@
Exporters = [] Exporters = []
from pyqtgraph import importModules
import os, sys #from .. import frozenSupport
import os
d = os.path.split(__file__)[0] d = os.path.split(__file__)[0]
files = [] #files = []
for f in os.listdir(d): #for f in frozenSupport.listdir(d):
if os.path.isdir(os.path.join(d, f)) and f != '__pycache__': #if frozenSupport.isdir(os.path.join(d, f)) and f != '__pycache__':
files.append(f) #files.append(f)
elif f[-3:] == '.py' and f not in ['__init__.py', 'Exporter.py']: #elif f[-3:] == '.py' and f not in ['__init__.py', 'Exporter.py']:
files.append(f[:-3]) #files.append(f[:-3])
for modName in files: #for modName in files:
mod = __import__(modName, globals(), locals(), fromlist=['*']) #mod = __import__(modName, globals(), locals(), fromlist=['*'])
for mod in importModules('', globals(), locals(), excludes=['Exporter']).values():
if hasattr(mod, '__all__'): if hasattr(mod, '__all__'):
names = mod.__all__ names = mod.__all__
else: else:

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from pyqtgraph.pgcollections import OrderedDict from pyqtgraph.pgcollections import OrderedDict
from pyqtgraph import importModules
import os, types import os, types
from pyqtgraph.debug import printExc from pyqtgraph.debug import printExc
from ..Node import Node from ..Node import Node
@ -59,29 +60,31 @@ def loadLibrary(reloadLibs=False, libPath=None):
"""Import all Node subclasses found within files in the library module.""" """Import all Node subclasses found within files in the library module."""
global NODE_LIST, NODE_TREE global NODE_LIST, NODE_TREE
if libPath is None: #if libPath is None:
libPath = os.path.dirname(os.path.abspath(__file__)) #libPath = os.path.dirname(os.path.abspath(__file__))
if reloadLibs: if reloadLibs:
reload.reloadAll(libPath) reload.reloadAll(libPath)
for f in os.listdir(libPath):
pathName, ext = os.path.splitext(f)
if ext != '.py' or '__init__' in pathName or '__pycache__' in pathName:
continue
try:
#print "importing from", f
mod = __import__(pathName, globals(), locals())
except:
printExc("Error loading flowchart library %s:" % pathName)
continue
mods = importModules('', globals(), locals())
#for f in frozenSupport.listdir(libPath):
#pathName, ext = os.path.splitext(f)
#if ext not in ('.py', '.pyc') or '__init__' in pathName or '__pycache__' in pathName:
#continue
#try:
##print "importing from", f
#mod = __import__(pathName, globals(), locals())
#except:
#printExc("Error loading flowchart library %s:" % pathName)
#continue
for name, mod in mods.items():
nodes = [] nodes = []
for n in dir(mod): for n in dir(mod):
o = getattr(mod, n) o = getattr(mod, n)
if isNodeClass(o): if isNodeClass(o):
#print " ", str(o) #print " ", str(o)
registerNodeType(o, [(pathName,)], override=reloadLibs) registerNodeType(o, [(name,)], override=reloadLibs)
#nodes.append((o.nodeName, o)) #nodes.append((o.nodeName, o))
#if len(nodes) > 0: #if len(nodes) > 0:
#NODE_TREE[name] = OrderedDict(nodes) #NODE_TREE[name] = OrderedDict(nodes)

52
frozenSupport.py Normal file
View File

@ -0,0 +1,52 @@
## Definitions helpful in frozen environments (eg py2exe)
import os, sys, zipfile
def listdir(path):
"""Replacement for os.listdir that works in frozen environments."""
if not hasattr(sys, 'frozen'):
return os.listdir(path)
(zipPath, archivePath) = splitZip(path)
if archivePath is None:
return os.listdir(path)
with zipfile.ZipFile(zipPath, "r") as zipobj:
contents = zipobj.namelist()
results = set()
for name in contents:
# components in zip archive paths are always separated by forward slash
if name.startswith(archivePath) and len(name) > len(archivePath):
name = name[len(archivePath):].split('/')[0]
results.add(name)
return list(results)
def isdir(path):
"""Replacement for os.path.isdir that works in frozen environments."""
if not hasattr(sys, 'frozen'):
return os.path.isdir(path)
(zipPath, archivePath) = splitZip(path)
if archivePath is None:
return os.path.isdir(path)
with zipfile.ZipFile(zipPath, "r") as zipobj:
contents = zipobj.namelist()
archivePath = archivePath.rstrip('/') + '/' ## make sure there's exactly one '/' at the end
for c in contents:
if c.startswith(archivePath):
return True
return False
def splitZip(path):
"""Splits a path containing a zip file into (zipfile, subpath).
If there is no zip file, returns (path, None)"""
components = os.path.normpath(path).split(os.sep)
for index, component in enumerate(components):
if component.endswith('.zip'):
zipPath = os.sep.join(components[0:index+1])
archivePath = ''.join([x+'/' for x in components[index+1:]])
return (zipPath, archivePath)
else:
return (path, None)

View File

@ -164,7 +164,7 @@ class ViewBox(GraphicsWidget):
ViewBox.NamedViews[name] = self ViewBox.NamedViews[name] = self
ViewBox.updateAllViewLists() ViewBox.updateAllViewLists()
sid = id(self) sid = id(self)
self.destroyed.connect(lambda: ViewBox.forgetView(sid, name)) self.destroyed.connect(lambda: ViewBox.forgetView(sid, name) if ViewBox is not None else None)
#self.destroyed.connect(self.unregister) #self.destroyed.connect(self.unregister)
def unregister(self): def unregister(self):

View File

@ -1,23 +1,24 @@
from .GLViewWidget import GLViewWidget from .GLViewWidget import GLViewWidget
import os from pyqtgraph import importAll
def importAll(path): #import os
d = os.path.join(os.path.split(__file__)[0], path) #def importAll(path):
files = [] #d = os.path.join(os.path.split(__file__)[0], path)
for f in os.listdir(d): #files = []
if os.path.isdir(os.path.join(d, f)) and f != '__pycache__': #for f in os.listdir(d):
files.append(f) #if os.path.isdir(os.path.join(d, f)) and f != '__pycache__':
elif f[-3:] == '.py' and f != '__init__.py': #files.append(f)
files.append(f[:-3]) #elif f[-3:] == '.py' and f != '__init__.py':
#files.append(f[:-3])
for modName in files: #for modName in files:
mod = __import__(path+"."+modName, globals(), locals(), fromlist=['*']) #mod = __import__(path+"."+modName, globals(), locals(), fromlist=['*'])
if hasattr(mod, '__all__'): #if hasattr(mod, '__all__'):
names = mod.__all__ #names = mod.__all__
else: #else:
names = [n for n in dir(mod) if n[0] != '_'] #names = [n for n in dir(mod) if n[0] != '_']
for k in names: #for k in names:
if hasattr(mod, k): #if hasattr(mod, k):
globals()[k] = getattr(mod, k) #globals()[k] = getattr(mod, k)
importAll('items') importAll('items', globals(), locals())