Commit 5081c97a authored by Luke Campagnola's avatar Luke Campagnola
Browse files

Better support for frozen environments:

  - built in Christian Gavin's os.listdir replacement
  - added os.isdir replacement
Fixed ViewBox causing errors at shutdown
parent a011b345
...@@ -104,36 +104,61 @@ def renamePyc(startDir): ...@@ -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 *
......
...@@ -14,7 +14,13 @@ import time ...@@ -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):
......
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:
......
# -*- 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): ...@@ -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)
......
## 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)
\ No newline at end of file
...@@ -164,7 +164,7 @@ class ViewBox(GraphicsWidget): ...@@ -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):
......
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())
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment