def get_argyll_util(name, paths=None): """ Find a single Argyll utility. Return the full path. """ cfg_argyll_dir = getcfg("argyll.dir") if not paths: paths = getenvu("PATH", os.defpath).split(os.pathsep) argyll_dir = (cfg_argyll_dir or "").rstrip(os.path.sep) if argyll_dir: if argyll_dir in paths: paths.remove(argyll_dir) paths = [argyll_dir] + paths cache_key = os.pathsep.join(paths) exe = argyll_utils.get(cache_key, {}).get(name, None) if exe: return exe elif verbose >= 4: safe_print("Info: Searching for", name, "in", os.pathsep.join(paths)) for path in paths: for altname in argyll_altnames.get(name, []): exe = which(altname + exe_ext, [path]) if exe: break if exe: break if verbose >= 4: if exe: safe_print("Info:", name, "=", exe) else: safe_print("Info:", "|".join(argyll_altnames[name]), "not found in", os.pathsep.join(paths)) if exe: if not cache_key in argyll_utils: argyll_utils[cache_key] = {} argyll_utils[cache_key][name] = exe return exe
def check_argyll_bin(paths=None): """ Check if the Argyll binaries can be found. """ prev_dir = None for name in argyll_names: exe = get_argyll_util(name, paths) if not exe: if name in argyll_optional: continue return False cur_dir = os.path.dirname(exe) if prev_dir: if cur_dir != prev_dir: if name in argyll_optional: if verbose: safe_print("Warning: Optional Argyll " "executable %s is not in the same " "directory as the main executables " "(%s)." % (exe, prev_dir)) else: if verbose: safe_print("Error: Main Argyll " "executable %s is not in the same " "directory as the other executables " "(%s)." % (exe, prev_dir)) return False else: prev_dir = cur_dir if verbose >= 3: safe_print("Argyll binary directory:", cur_dir) if debug: safe_print("[D] check_argyll_bin OK") if debug >= 2: if not paths: paths = getenvu("PATH", os.defpath).split(os.pathsep) argyll_dir = (getcfg("argyll.dir") or "").rstrip(os.path.sep) if argyll_dir: if argyll_dir in paths: paths.remove(argyll_dir) paths = [argyll_dir] + paths safe_print("[D] Searchpath:\n ", "\n ".join(paths)) # Fedora doesn't ship Rec709.icm config.defaults["3dlut.input.profile"] = get_data_path(os.path.join("ref", "Rec709.icm")) or \ get_data_path(os.path.join("ref", "sRGB.icm")) or "" config.defaults["testchart.reference"] = get_data_path( os.path.join("ref", "ColorChecker.cie")) or "" config.defaults["gamap_profile"] = get_data_path( os.path.join("ref", "sRGB.icm")) or "" return True
elif sys.platform == "darwin": library_home = os.path.join(home, "Library") library = os.path.join(os.path.sep, "Library") prefs = os.path.join(os.path.sep, "Library", "Preferences") prefs_home = os.path.join(home, "Library", "Preferences") appdata = os.path.join(home, "Library", "Application Support") commonappdata = [os.path.join(os.path.sep, "Library", "Application Support")] autostart = autostart_home = None iccprofiles = [os.path.join(os.path.sep, "Library", "ColorSync", "Profiles"), os.path.join(os.path.sep, "System", "Library", "ColorSync", "Profiles")] iccprofiles_home = [os.path.join(home, "Library", "ColorSync", "Profiles")] else: xdg_config_home = getenvu("XDG_CONFIG_HOME", expandvarsu("$HOME/.config")) xdg_config_dir_default = "/etc/xdg" xdg_config_dirs = [os.path.normpath(pth) for pth in getenvu("XDG_CONFIG_DIRS", xdg_config_dir_default).split(os.pathsep)] if not xdg_config_dir_default in xdg_config_dirs: xdg_config_dirs += [xdg_config_dir_default] xdg_data_home_default = expandvarsu("$HOME/.local/share") library_home = appdata = xdg_data_home = getenvu("XDG_DATA_HOME", xdg_data_home_default) xdg_data_dirs_default = "/usr/local/share:/usr/share:/var/lib" xdg_data_dirs = [os.path.normpath(pth) for pth in getenvu("XDG_DATA_DIRS", xdg_data_dirs_default).split(os.pathsep)] for dir_ in xdg_data_dirs_default.split(os.pathsep): if not dir_ in xdg_data_dirs: xdg_data_dirs += [dir_]
from meta import (author, author_ascii, description, longdesc, domain, name, py_maxversion, py_minversion, version, version_tuple, wx_minversion, author_email, script2pywname, appstream_id) from util_list import intlist from util_os import getenvu, relpath, safe_glob from util_str import safe_str appname = name bits = platform.architecture()[0][:2] pypath = os.path.abspath(__file__) pydir = os.path.dirname(pypath) basedir = os.path.dirname(pydir) if sys.platform in ("darwin", "win32"): # Adjust PATH so ctypes.util.find_library can find SDL2 DLLs (if present) pth = getenvu("PATH") libpth = os.path.join(pydir, "lib") if not pth.startswith(libpth + os.pathsep): pth = libpth + os.pathsep + pth os.environ["PATH"] = safe_str(pth) config = {"data": ["tests/*.icc"], "doc": ["CHANGES.html", "LICENSE.txt", "README.html", "README-fr.html", "screenshots/*.png", "theme/*.png", "theme/*.css", "theme/*.js", "theme/*.svg",
class XDG: cache_home = getenvu("XDG_CACHE_HOME", expandvarsu("$HOME/.cache")) config_home = getenvu("XDG_CONFIG_HOME", expandvarsu("$HOME/.config")) config_dir_default = "/etc/xdg" config_dirs = list( map( os.path.normpath, getenvu("XDG_CONFIG_DIRS", config_dir_default).split(os.pathsep))) if not config_dir_default in config_dirs: config_dirs.append(config_dir_default) data_home_default = expandvarsu("$HOME/.local/share") data_home = getenvu("XDG_DATA_HOME", data_home_default) data_dirs_default = "/usr/local/share:/usr/share:/var/lib" data_dirs = list( map(os.path.normpath, getenvu("XDG_DATA_DIRS", data_dirs_default).split(os.pathsep))) data_dirs.extend( list( filter(lambda data_dir, data_dirs=data_dirs: not data_dir in data_dirs, data_dirs_default.split(os.pathsep)))) @staticmethod def set_translation(obj): locale_dir = LOCALEDIR if not os.path.isdir(locale_dir): for path in XDG.data_dirs: path = os.path.join(path, "locale") if os.path.isdir(path): locale_dir = path break try: obj.translation = gettext.translation(obj.GETTEXT_PACKAGE, locale_dir, codeset="UTF-8") except IOError as exception: from log import safe_print safe_print("XDG:", exception) obj.translation = gettext.NullTranslations() return False return True @staticmethod def is_true(s): return s == "1" or s.startswith("True") or s.startswith("true") @staticmethod def get_config_files(filename): paths = [] for xdg_config_dir in [XDG.config_home] + XDG.config_dirs: path = os.path.join(xdg_config_dir, filename) if os.path.isfile(path): paths.append(path) return paths @staticmethod def shell_unescape(s): a = [] for i, c in enumerate(s): if c == "\\" and len(s) > i + 1: continue a.append(c) return "".join(a) @staticmethod def config_file_parser(f): for line in f: line = line.strip() if line.startswith("#") or not "=" in line: continue yield tuple(s.strip() for s in line.split("=", 1)) @staticmethod def process_config_file(path, fn): try: with open(path, "r") as f: for key, value in XDG.config_file_parser(f): fn(key, value) except EnvironmentError as exception: from log import safe_print safe_print("XDG: Couldn't read '%s':" % path, exception) return False return True class _UserDirs(object): GETTEXT_PACKAGE = "xdg-user-dirs" enabled = True filename_encoding = "UTF-8" default_dirs = {} user_dirs = {} _initialized = False def __getattribute__(self, name): if (name != "init" and not object.__getattribute__(self, "_initialized")): object.__getattribute__(self, "init")() return object.__getattribute__(self, name) def load_config(self, path): def fn(key, value): if key == "enabled": self.enabled = XDG.is_true(value) elif key == "filename_encoding": value = value.upper() if value == "LOCALE": current_locale = locale.getlocale() locale.setlocale(locale.LC_ALL, "") self.filename_encoding = locale.nl_langinfo( locale.CODESET) locale.setlocale(locale.LC_ALL, current_locale) else: self.filename_encoding = value return XDG.process_config_file(path, fn) def load_all_configs(self): for path in reversed(XDG.get_config_files("user-dirs.conf")): self.load_config(path) def load_default_dirs(self): paths = XDG.get_config_files("user-dirs.defaults") if not paths: from log import safe_print safe_print("XDG.UserDirs: No default user directories") return False def fn(name, path): self.default_dirs[name] = self.localize_path_name(path) return XDG.process_config_file(paths[0], fn) def load_user_dirs(self): path = os.path.join(XDG.config_home, "user-dirs.dirs") if not path or not os.path.isfile(path): return False def fn(key, value): if (key.startswith("XDG_") and key.endswith("_DIR") and value.startswith('"') and value.endswith('"')): name = key[4:-4] if not name: return value = value.strip('"') if value.startswith('$HOME'): value = value[5:] if value.startswith("/"): value = value[1:] elif value: # Not ending after $HOME, nor followed by slash. # Ignore return elif not value.startswith("/"): return self.user_dirs[name] = XDG.shell_unescape( value).decode("UTF-8", "ignore") return XDG.process_config_file(path, fn) def localize_path_name(self, path): elements = path.split(os.path.sep) for i, element in enumerate(elements): elements[i] = self.translation.ugettext(element) return os.path.join(*elements) def init(self): self._initialized = True XDG.set_translation(self) self.load_all_configs() try: codecs.lookup(self.filename_encoding) except LookupError: from log import safe_print safe_print("XDG.UserDirs: Can't convert from UTF-8 to", self.filename_encoding) return False self.load_default_dirs() self.load_user_dirs() UserDirs = _UserDirs()
library_home = appdata = SHGetSpecialFolderPath(0, CSIDL_APPDATA, 1) except Exception as exception: raise Exception( "FATAL - Could not get/create user application data folder: %s" % exception) try: localappdata = SHGetSpecialFolderPath(0, CSIDL_LOCAL_APPDATA, 1) except Exception as exception: localappdata = os.path.join(appdata, "Local") cache = localappdata # Argyll CMS uses ALLUSERSPROFILE for local system wide app related data # Note: On Windows Vista and later, ALLUSERSPROFILE and COMMON_APPDATA # are actually the same ('C:\ProgramData'), but under Windows XP the former # points to 'C:\Documents and Settings\All Users' while COMMON_APPDATA # points to 'C:\Documents and Settings\All Users\Application Data' allusersprofile = getenvu("ALLUSERSPROFILE") if allusersprofile: commonappdata = [allusersprofile] else: try: commonappdata = [ SHGetSpecialFolderPath(0, CSIDL_COMMON_APPDATA, 1) ] except Exception as exception: raise Exception( "FATAL - Could not get/create common application data folder: %s" % exception) library = commonappdata[0] try: commonprogramfiles = SHGetSpecialFolderPath( 0, CSIDL_PROGRAM_FILES_COMMON, 1)
def runtimeconfig(pyfile): """ Configure remaining runtime options and return runtype. You need to pass in a path to the calling script (e.g. use the __file__ attribute). """ from log import setup_logging setup_logging() if debug or verbose >= 1: from log import safe_print if debug: safe_print("[D] pydir:", pydir) if isapp: runtype = ".app" elif isexe: if debug: safe_print("[D] _MEIPASS2 or pydir:", getenvu("_MEIPASS2", exedir)) if getenvu("_MEIPASS2", exedir) not in data_dirs: data_dirs.insert(1, getenvu("_MEIPASS2", exedir)) runtype = exe_ext else: pydir_parent = os.path.dirname(pydir) if debug: safe_print("[D] dirname(os.path.abspath(sys.argv[0])):", os.path.dirname(os.path.abspath(sys.argv[0]))) safe_print("[D] pydir parent:", pydir_parent) if os.path.dirname(os.path.abspath(sys.argv[0])) == pydir_parent and \ pydir_parent not in data_dirs: # Add the parent directory of the package directory to our list # of data directories if it is the directory containing the # currently run script (e.g. when running from source) data_dirs.insert(1, pydir_parent) runtype = pyext for dir_ in sys.path: if not isinstance(dir_, unicode): dir_ = unicode(dir_, fs_enc) dir_ = os.path.abspath(os.path.join(dir_, appname)) if dir_ not in data_dirs and os.path.isdir(dir_): data_dirs.append(dir_) if debug: safe_print("[D] from sys.path:", dir_) if sys.platform not in ("darwin", "win32"): data_dirs.extend([os.path.join(dir_, "doc", appname + "-" + version) for dir_ in xdg_data_dirs + [xdg_data_home]]) data_dirs.extend([os.path.join(dir_, "doc", "packages", appname) for dir_ in xdg_data_dirs + [xdg_data_home]]) data_dirs.extend([os.path.join(dir_, "doc", appname) for dir_ in xdg_data_dirs + [xdg_data_home]]) data_dirs.extend([os.path.join(dir_, "doc", appname.lower()) # Debian for dir_ in xdg_data_dirs + [xdg_data_home]]) data_dirs.extend([os.path.join(dir_, "icons", "hicolor") for dir_ in xdg_data_dirs + [xdg_data_home]]) if debug: safe_print("[D] Data files search paths:\n[D]", "\n[D] ".join(data_dirs)) defaults["3dlut.input.profile"] = get_data_path(os.path.join("ref", "Rec709.icm")) or "" defaultmmode = defaults["measurement_mode"] defaultptype = defaults["profile.type"] defaultchart = testchart_defaults.get(defaultptype, testchart_defaults["s"])[None] defaults["testchart.file"] = get_data_path(os.path.join("ti1", defaultchart)) or "" defaults["testchart.file.backup"] = defaults["testchart.file"] defaults["profile_verification_chart"] = get_data_path(os.path.join("ref", "verify.ti1")) or "" defaults["gamap_profile"] = get_data_path(os.path.join("ref", "sRGB.icm")) or "" return runtype
def init(lib=None, samplerate=22050, channels=2, buffersize=2048, reinit=False): """ (Re-)Initialize sound subsystem """ # Note on buffer size: Too high values cause crackling during fade, too low # values cause choppy playback of ogg files when using pyo (good value for # pyo is >= 2048) global _initialized, _lib, _lib_version, _server, pyglet, pyo, sdl, wx if _initialized and not reinit: # To re-initialize, explicitly set reinit to True return # Select the audio library we're going to use. # User choice or SDL > pyglet > pyo > wx if not lib: if sys.platform in ("darwin", "win32"): # Mac OS X, Windows libs = ("pyglet", "SDL", "pyo", "wx") else: # Linux libs = ("SDL", "pyglet", "pyo", "wx") for lib in libs: try: return init(lib, samplerate, channels, buffersize, reinit) except Exception as exception: pass raise exception elif lib == "pyglet": if not getattr(sys, "frozen", False): # Use included pyglet lib_dir = os.path.join(os.path.dirname(__file__), "lib") if not lib_dir in sys.path: sys.path.insert(0, lib_dir) try: import pyglet version = [] for item in pyglet.version.split("."): try: version.append(int(item)) except ValueError: version.append(item) if version < [1, 2, 2]: raise ImportError("pyglet version %s is too old" % pyglet.version) _lib = "pyglet" except ImportError: _lib = None else: # Work around localization preventing fallback to RIFFSourceLoader pyglet.lib.LibraryLoader.darwin_not_found_error = "" pyglet.lib.LibraryLoader.linux_not_found_error = "" # Set audio driver preference pyglet.options["audio"] = ("pulse", "openal", "directsound", "silent") _server = pyglet.media _lib_version = pyglet.version elif lib == "pyo": try: import pyo _lib = "pyo" except ImportError: _lib = None else: if isinstance(_server, pyo.Server): _server.reinit(sr=samplerate, nchnls=channels, buffersize=buffersize, duplex=0) else: _server = pyo.Server(sr=samplerate, nchnls=channels, buffersize=buffersize, duplex=0, winhost="asio").boot() _server.start() _lib_version = ".".join(str(v) for v in pyo.getVersion()) elif lib == "SDL": SDL_INIT_AUDIO = 16 AUDIO_S16LSB = 0x8010 AUDIO_S16MSB = 0x9010 if sys.byteorder == "little": MIX_DEFAULT_FORMAT = AUDIO_S16LSB else: MIX_DEFAULT_FORMAT = AUDIO_S16MSB if sys.platform == "win32": pth = getenvu("PATH") libpth = os.path.join(pydir, "lib") if not pth.startswith(libpth + os.pathsep): pth = libpth + os.pathsep + pth os.environ["PATH"] = safe_str(pth) elif sys.platform == "darwin": x_framework_pth = os.getenv("X_DYLD_FALLBACK_FRAMEWORK_PATH") if x_framework_pth: framework_pth = os.getenv("DYLD_FALLBACK_FRAMEWORK_PATH") if framework_pth: x_framework_pth = os.pathsep.join( [x_framework_pth, framework_pth]) os.environ["DYLD_FALLBACK_FRAMEWORK_PATH"] = x_framework_pth for libname in ("SDL2", "SDL2_mixer", "SDL", "SDL_mixer"): handle = None if sys.platform in ("darwin", "win32"): libfn = ctypes.util.find_library(libname) if sys.platform == "win32": if libfn and win32api: # Support for unicode paths libfn = safe_unicode(libfn) try: handle = win32api.LoadLibrary(libfn) except pywintypes.error: pass elif sys.platform != "darwin": # Hard-code lib names for Linux libfn = "lib" + libname if libname.startswith("SDL2"): # SDL 2.0 libfn += "-2.0.so.0" else: # SDL 1.2 libfn += "-1.2.so.0" dll = dlopen(libfn, handle=handle) if dll: safe_print("%s:" % libname, libfn) if libname.endswith("_mixer"): if not dll: continue if not sdl: raise RuntimeError("SDL library not loaded") sdl.SDL_RWFromFile.restype = POINTER(SDL_RWops) _server = dll _server.Mix_OpenAudio.argtypes = [ c_int, c_uint16, c_int, c_int ] _server.Mix_LoadWAV_RW.argtypes = [POINTER(SDL_RWops), c_int] _server.Mix_LoadWAV_RW.restype = POINTER(Mix_Chunk) _server.Mix_PlayChannelTimed.argtypes = [ c_int, POINTER(Mix_Chunk), c_int, c_int ] _server.Mix_VolumeChunk.argtypes = [POINTER(Mix_Chunk), c_int] if _initialized: _server.Mix_Quit() sdl.SDL_Quit() sdl.SDL_Init(SDL_INIT_AUDIO) _server.Mix_OpenAudio(samplerate, MIX_DEFAULT_FORMAT, channels, buffersize) _lib = "SDL" if libname.startswith("SDL2"): _lib_version = "2.0" else: _lib_version = "1.2" break else: sdl = dll _server = None elif lib == "wx": try: import wx _lib = "wx" except ImportError: _lib = None else: _server = wx _lib_version = wx.__version__ if not _lib: raise RuntimeError("No audio library available") _initialized = True return _server
def trash(paths): """ Move files and folders to the trash. If a trashcan facility does not exist, do not touch the files. Return a list of successfully processed paths. """ if isinstance(paths, str): paths = [paths] if not isinstance(paths, list): raise TypeError(str(type(paths)) + " is not list") deleted = [] if sys.platform == "win32": for path in paths: path = os.path.abspath(path) if not os.path.exists(path): raise IOError("No such file or directory: " + path) if recycle(path): deleted.append(path) else: # http://freedesktop.org/wiki/Specifications/trash-spec trashroot = os.path.join( getenvu("XDG_DATA_HOME", os.path.join(expanduseru("~"), ".local", "share")), "Trash") trashinfo = os.path.join(trashroot, "info") # Older Linux distros and Mac OS X trashcan = os.path.join(expanduseru("~"), ".Trash") if sys.platform != "darwin" and not os.path.isdir(trashcan): # Modern Linux distros trashcan = os.path.join(trashroot, "files") if not os.path.isdir(trashcan): try: os.makedirs(trashcan) except OSError: raise TrashcanUnavailableError("Not a directory: '%s'" % trashcan) for path in paths: if os.path.isdir(trashcan): n = 1 dst = os.path.join(trashcan, os.path.basename(path)) while os.path.exists(dst): # avoid name clashes n += 1 dst = os.path.join(trashcan, os.path.basename(path) + "." + str(n)) if os.path.isdir(trashinfo): info = open( os.path.join(trashinfo, os.path.basename(dst) + ".trashinfo"), "w") info.write("[Trash Info]\n") info.write("Path=%s\n" % quote(path.encode(sys.getfilesystemencoding()))) info.write("DeletionDate=" + strftime("%Y-%m-%dT%H:%M:%S")) info.close() shutil.move(path, dst) else: # if trashcan does not exist, simply delete file/folder? pass # if os.path.isdir(path) and not os.path.islink(path): # shutil.rmtree(path) # else: # os.remove(path) deleted.append(path) return deleted