diff --git a/__init__.py b/__init__.py index fdaf2a86..bd7c2e76 100644 --- a/__init__.py +++ b/__init__.py @@ -104,36 +104,61 @@ def renamePyc(startDir): import os 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 ## don't import the more complex systems--canvas, parametertree, flowchart, dockarea ## these must be imported separately. - -def importAll(path, excludes=()): - d = os.path.join(os.path.split(__file__)[0], path) - files = [] - for f in os.listdir(d): - if os.path.isdir(os.path.join(d, f)) and f != '__pycache__': - files.append(f) +import frozenSupport +def importModules(path, globals, locals, excludes=()): + """Import all modules residing within *path*, return a dict of name: module pairs. + + Note that *path* MUST be relative to the module doing the import. + """ + 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': - 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: if modName in excludes: 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__'): names = mod.__all__ else: names = [n for n in dir(mod) if n[0] != '_'] for k in names: if hasattr(mod, k): - globals()[k] = getattr(mod, k) + globals[k] = getattr(mod, k) -importAll('graphicsItems') -importAll('widgets', excludes=['MatplotlibWidget', 'RemoteGraphicsView']) +importAll('graphicsItems', globals(), locals()) +importAll('widgets', globals(), locals(), excludes=['MatplotlibWidget', 'RemoteGraphicsView']) from .imageview import * from .WidgetGroup import * diff --git a/examples/customPlot.py b/examples/customPlot.py index 86ed4829..451ae501 100644 --- a/examples/customPlot.py +++ b/examples/customPlot.py @@ -14,7 +14,13 @@ import time class DateAxis(pg.AxisItem): 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): def __init__(self, *args, **kwds): diff --git a/exporters/__init__.py b/exporters/__init__.py index 99fbdf20..3f3c1f1d 100644 --- a/exporters/__init__.py +++ b/exporters/__init__.py @@ -1,16 +1,18 @@ Exporters = [] - -import os, sys +from pyqtgraph import importModules +#from .. import frozenSupport +import os d = os.path.split(__file__)[0] -files = [] -for f in os.listdir(d): - if os.path.isdir(os.path.join(d, f)) and f != '__pycache__': - files.append(f) - elif f[-3:] == '.py' and f not in ['__init__.py', 'Exporter.py']: - files.append(f[:-3]) +#files = [] +#for f in frozenSupport.listdir(d): + #if frozenSupport.isdir(os.path.join(d, f)) and f != '__pycache__': + #files.append(f) + #elif f[-3:] == '.py' and f not in ['__init__.py', 'Exporter.py']: + #files.append(f[:-3]) -for modName in files: - mod = __import__(modName, globals(), locals(), fromlist=['*']) +#for modName in files: + #mod = __import__(modName, globals(), locals(), fromlist=['*']) +for mod in importModules('', globals(), locals(), excludes=['Exporter']).values(): if hasattr(mod, '__all__'): names = mod.__all__ else: diff --git a/flowchart/library/__init__.py b/flowchart/library/__init__.py index 5b8df612..1e44edff 100644 --- a/flowchart/library/__init__.py +++ b/flowchart/library/__init__.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- from pyqtgraph.pgcollections import OrderedDict +from pyqtgraph import importModules import os, types from pyqtgraph.debug import printExc 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.""" global NODE_LIST, NODE_TREE - if libPath is None: - libPath = os.path.dirname(os.path.abspath(__file__)) + #if libPath is None: + #libPath = os.path.dirname(os.path.abspath(__file__)) if reloadLibs: 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 = [] for n in dir(mod): o = getattr(mod, n) if isNodeClass(o): #print " ", str(o) - registerNodeType(o, [(pathName,)], override=reloadLibs) + registerNodeType(o, [(name,)], override=reloadLibs) #nodes.append((o.nodeName, o)) #if len(nodes) > 0: #NODE_TREE[name] = OrderedDict(nodes) diff --git a/frozenSupport.py b/frozenSupport.py new file mode 100644 index 00000000..385bb435 --- /dev/null +++ b/frozenSupport.py @@ -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) + + \ No newline at end of file diff --git a/graphicsItems/ViewBox/ViewBox.py b/graphicsItems/ViewBox/ViewBox.py index 9ddee54d..5eca742c 100644 --- a/graphicsItems/ViewBox/ViewBox.py +++ b/graphicsItems/ViewBox/ViewBox.py @@ -164,7 +164,7 @@ class ViewBox(GraphicsWidget): ViewBox.NamedViews[name] = self ViewBox.updateAllViewLists() 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) def unregister(self): diff --git a/opengl/__init__.py b/opengl/__init__.py index bb9f25b1..1335b35a 100644 --- a/opengl/__init__.py +++ b/opengl/__init__.py @@ -1,23 +1,24 @@ from .GLViewWidget import GLViewWidget -import os -def importAll(path): - d = os.path.join(os.path.split(__file__)[0], path) - files = [] - for f in os.listdir(d): - if os.path.isdir(os.path.join(d, f)) and f != '__pycache__': - files.append(f) - elif f[-3:] == '.py' and f != '__init__.py': - files.append(f[:-3]) +from pyqtgraph import importAll +#import os +#def importAll(path): + #d = os.path.join(os.path.split(__file__)[0], path) + #files = [] + #for f in os.listdir(d): + #if os.path.isdir(os.path.join(d, f)) and f != '__pycache__': + #files.append(f) + #elif f[-3:] == '.py' and f != '__init__.py': + #files.append(f[:-3]) - for modName in files: - mod = __import__(path+"."+modName, globals(), locals(), fromlist=['*']) - if hasattr(mod, '__all__'): - names = mod.__all__ - else: - names = [n for n in dir(mod) if n[0] != '_'] - for k in names: - if hasattr(mod, k): - globals()[k] = getattr(mod, k) + #for modName in files: + #mod = __import__(path+"."+modName, globals(), locals(), fromlist=['*']) + #if hasattr(mod, '__all__'): + #names = mod.__all__ + #else: + #names = [n for n in dir(mod) if n[0] != '_'] + #for k in names: + #if hasattr(mod, k): + #globals()[k] = getattr(mod, k) -importAll('items') +importAll('items', globals(), locals())