## 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)
    
    