Пример #1
0
def writecfg(which="user", worker=None):
	"""
	Write configuration file.
	
	which: 'user' or 'system'
	worker: worker instance if which == 'system'
	
	"""
	if which == "user":
		# user config - stores everything and overrides system-wide config
		cfgfilename = os.path.join(confighome, appname + ".ini")
		try:
			io = StringIO()
			cfg.write(io)
			io.seek(0)
			lines = io.read().strip("\n").split("\n")
			# Sorting works as long as config has only one section
			lines = [lines[0]] + sorted(lines[1:])
			cfgfile = open(cfgfilename, "wb")
			cfgfile.write("\n".join(lines))
			cfgfile.close()
		except Exception, exception:
			from debughelpers import handle_error
			handle_error(u"Warning - could not write user configuration file "
						 "'%s': %s" % (cfgfilename, safe_unicode(exception)))
			return False
Пример #2
0
def init(set_wx_locale=False):
	"""
	Populate translation dict with found language strings and set locale.
	
	If set_wx_locale is True, set locale also for wxPython.
	
	"""
	langdirs = []
	for dir_ in data_dirs:
		langdirs.append(os.path.join(dir_, "lang"))
	for langdir in langdirs:
		if os.path.exists(langdir) and os.path.isdir(langdir):
			try:
				langfiles = os.listdir(langdir)
			except Exception as exception:
				safe_print("Warning - directory '%s' listing failed: %s" % 
						   tuple(safe_unicode(s) for s in (langdir, exception)))
			else:
				for filename in langfiles:
					name, ext = os.path.splitext(filename)
					if ext.lower() == ".yaml" and name.lower() not in ldict:
						path = os.path.join(langdir, filename)
						ldict[name.lower()] = LazyDict_YAML_UltraLite(path)
	if len(ldict) == 0:
		handle_error(UserWarning("Warning: No language files found. The "
								 "following places have been searched:\n%s" %
								 "\n".join(langdirs)))
Пример #3
0
def makecfgdir(which="user", worker=None):
	if which == "user":
		if not os.path.exists(confighome):
			try:
				os.makedirs(confighome)
			except Exception, exception:
				from debughelpers import handle_error
				handle_error(u"Warning - could not create configuration directory "
							 "'%s': %s" % (confighome, safe_unicode(exception)))
				return False
Пример #4
0
def main(module=None):
    mp.freeze_support()
    if mp.current_process().name != "MainProcess":
        return
    if module:
        name = "%s-%s" % (appbasename, module)
    else:
        name = appbasename
    applockfilename = os.path.join(confighome, "%s.lock" % name)
    try:
        _main(module, name, applockfilename)
    except Exception as exception:
        if isinstance(exception, ResourceError):
            error = exception
        else:
            error = Error("Fatal error: " + safe_unicode(exception))
        handle_error(error)
        _exit(applockfilename, getattr(sys, "_appsocket_port", ""))
Пример #5
0
	def load(self, path=None, encoding=None, errors=None, raise_exceptions=False):
		if not self._isloaded and (path or self.path):
			self._isloaded = True
			if not path:
				path = self.path
			if path and not os.path.isabs(path):
				path = get_data_path(path)
			if path and os.path.isfile(path):
				self.path = path
				if encoding:
					self.encoding = encoding
				if errors:
					self.errors = errors
			else:
				handle_error(UserWarning("Warning - file not found:\n\n%s" % 
										 safe_unicode(path)), tb=False)
				return
			try:
				with codecs.open(path, "rU", self.encoding, self.errors) as f:
					self.parse(f)
			except EnvironmentError as exception:
				if raise_exceptions:
					raise
				handle_error(exception)
			except Exception as exception:
				if raise_exceptions:
					raise
				handle_error(UserWarning("Error parsing file:\n\n%s\n\n%s" %
										 tuple(safe_unicode(s) for s in
											   (path, exception))), tb=False)
Пример #6
0
		try:
			if sys.platform == "win32":
				os.makedirs(config_sys)
			else:
				result = worker.exec_cmd("mkdir", 
										 ["-p", config_sys], 
										 capture_output=True, 
										 low_contrast=False, 
										 skip_scripts=True, 
										 silent=True, 
										 asroot=True)
				if isinstance(result, Exception):
					raise result
		except Exception, exception:
			from debughelpers import handle_error
			handle_error(u"Warning - could not create configuration directory "
						 "'%s': %s" % (config_sys, safe_unicode(exception)))
			return False
	return True


def initcfg():
	"""
	Initialize the configuration.
	
	Read in settings if the configuration file exists, else create the 
	settings directory if nonexistent.
	
	"""
	# read pre-v0.2.2b configuration if present
	if sys.platform == "darwin":
		oldcfg = os.path.join(expanduseru("~"), "Library", "Preferences", 
Пример #7
0
def get_default_size():
    """
	Get and return the default size for the window in pixels.
	
	The default size is always equivalent to 100 x 100 mm according 
	to the display's size as returned by the RealDisplaySizeMM function, 
	which uses the same code as Argyll to determine that size.
	
	This function is used internally.
	
	"""
    display_sizes = []
    display_sizes_mm = []
    for display_no in range(len(getcfg("displays"))):
        display_no = get_display_number(display_no)
        display_size = wx.Display(display_no).Geometry[2:]
        display_size_mm = []
        if RDSMM:
            try:
                display_size_mm = RDSMM.RealDisplaySizeMM(display_no)
            except Exception as exception:
                handle_error("Error - RealDisplaySizeMM() failed: " +
                             safe_unicode(exception),
                             silent=True)
            else:
                display_size_mm = floatlist(display_size_mm)
        if debug:
            safe_print("[D]  display_size_mm:", display_size_mm)
        if not len(display_size_mm) or 0 in display_size_mm:
            ppi_def = get_default_dpi()
            method = 1
            if method == 0:
                # use configurable screen diagonal
                inch = 20.0
                mm = inch * 25.4
                f = mm / math.sqrt(math.pow(display_size[0], 2) + \
                 math.pow(display_size[1], 2))
                w_mm = math.sqrt(math.pow(mm, 2) - \
                    math.pow(display_size[1] * f, 2))
                h_mm = math.sqrt(math.pow(mm, 2) - \
                    math.pow(display_size[0] * f, 2))
                display_size_mm = w_mm, h_mm
            elif method == 1:
                # use the first display
                display_size_1st = wx.DisplaySize()
                display_size_mm = floatlist(wx.DisplaySizeMM())
                if 0 in display_size_mm:
                    # bogus
                    display_size_mm = [
                        display_size_1st[0] / ppi_def * 25.4,
                        display_size_1st[1] / ppi_def * 25.4
                    ]
                if display_no > 0:
                    display_size_mm[0] = display_size[0] / (
                        display_size_1st[0] / display_size_mm[0])
                    display_size_mm[1] = display_size[1] / (
                        display_size_1st[1] / display_size_mm[1])
            else:
                # use assumed ppi
                display_size_mm = (display_size[0] / ppi_def * 25.4,
                                   display_size[1] / ppi_def * 25.4)
        display_sizes.append(display_size)
        display_sizes_mm.append(display_size_mm)
    if sum(mm[0] for mm in display_sizes_mm) / \
        len(display_sizes_mm) == display_sizes_mm[0][0] and \
       sum(mm[1] for mm in display_sizes_mm) / \
        len(display_sizes_mm) == display_sizes_mm[0][1]:
        # display_size_mm is the same for all screens, use the 1st one
        display_size = display_sizes[0]
        display_size_mm = display_sizes_mm[0]
    else:
        if getcfg("display_lut.link"):
            display_no = getcfg("display.number") - 1
        else:
            display_no = getcfg("display_lut.number") - 1
        display_size = display_sizes[display_no]
        display_size_mm = display_sizes_mm[display_no]
    px_per_mm = (display_size[0] / display_size_mm[0],
                 display_size[1] / display_size_mm[1])
    if debug:
        safe_print("[D]  H px_per_mm:", px_per_mm[0])
        safe_print("[D]  V px_per_mm:", px_per_mm[1])
    return round(100.0 * max(px_per_mm))
Пример #8
0
def _main(module, name, applockfilename, probe_ports=True):
    # Allow multiple instances only for curve viewer, profile info,
    # scripting client, synthetic profile creator and testchart editor
    multi_instance = ("curve-viewer", "profile-info", "scripting-client",
                      "synthprofile", "testchart-editor")
    lock = AppLock(applockfilename, "a+", True, module in multi_instance)
    if not lock:
        # If a race condition occurs, do not start another instance
        safe_print("Not starting another instance.")
        return
    log("=" * 80)
    if verbose >= 1:
        version = VERSION_STRING
        if VERSION > VERSION_BASE:
            version += " Beta"
        safe_print(pyname + runtype, version, build)
    if sys.platform == "darwin":
        # Python's platform.platform output is useless under Mac OS X
        # (e.g. 'Darwin-15.0.0-x86_64-i386-64bit' for Mac OS X 10.11 El Capitan)
        safe_print("Mac OS X %s %s" % (mac_ver()[0], mac_ver()[-1]))
    elif sys.platform == "win32":
        machine = platform.machine()
        safe_print(*[v for v in win_ver() if v] + ({
            "AMD64": "x86_64"
        }.get(machine, machine), ))
    else:
        # Linux
        safe_print(' '.join(platform.dist()), platform.machine())
    safe_print("Python " + sys.version)
    cafile = os.getenv("SSL_CERT_FILE")
    if cafile:
        safe_print("CA file", cafile)
    # Enable faulthandler
    try:
        import faulthandler
    except Exception as exception:
        safe_print(exception)
    else:
        try:
            faulthandler.enable(
                open(os.path.join(logdir, pyname + "-fault.log"), "w"))
        except Exception as exception:
            safe_print(exception)
        else:
            safe_print("Faulthandler", getattr(faulthandler, "__version__",
                                               ""))
    from wxaddons import wx
    if "phoenix" in wx.PlatformInfo:
        # py2exe helper so wx.xml gets picked up
        from wx import xml
    safe_print("wxPython " + wx.version())
    safe_print("Encoding: " + enc)
    safe_print("File system encoding: " + fs_enc)
    if sys.platform == "win32" and sys.getwindowsversion() >= (6, 2):
        # HighDPI support
        try:
            shcore = ctypes.windll.shcore
        except Exception as exception:
            safe_print("Warning - could not load shcore:", exception)
        else:
            if hasattr(shcore, "SetProcessDpiAwareness"):
                try:
                    # 1 = System DPI aware (wxWpython currently does not
                    # support per-monitor DPI)
                    shcore.SetProcessDpiAwareness(1)
                except Exception as exception:
                    safe_print("Warning - SetProcessDpiAwareness() failed:",
                               exception)
            else:
                safe_print(
                    "Warning - SetProcessDpiAwareness not found in shcore")
    initcfg(module)
    host = "127.0.0.1"
    defaultport = getcfg("app.port")
    lock2pids_ports = {}
    opid = os.getpid()
    if probe_ports:
        # Check for currently used ports
        lockfilenames = glob.glob(os.path.join(confighome, "*.lock"))
        for lockfilename in lockfilenames:
            safe_print("Lockfile", lockfilename)
            try:
                if lock and lockfilename == applockfilename:
                    lockfile = lock
                    lock.seek(0)
                else:
                    lockfile = AppLock(lockfilename, "r", True, True)
                if lockfile:
                    if not lockfilename in lock2pids_ports:
                        lock2pids_ports[lockfilename] = []
                    for ln, line in enumerate(lockfile.read().splitlines(), 1):
                        if ":" in line:
                            # DisplayCAL >= 3.8.8.2 with localhost blocked
                            pid, port = line.split(":", 1)
                            if pid:
                                try:
                                    pid = int(pid)
                                except ValueError as exception:
                                    # This shouldn't happen
                                    safe_print("Warning - couldn't parse PID "
                                               "as int: %r (%s line %i)" %
                                               (pid, lockfilename, ln))
                                    pid = None
                                else:
                                    safe_print("Existing client using PID",
                                               pid)
                        else:
                            # DisplayCAL <= 3.8.8.1 or localhost ok
                            pid = None
                            port = line
                        if port:
                            try:
                                port = int(port)
                            except ValueError as exception:
                                # This shouldn't happen
                                safe_print(
                                    "Warning - couldn't parse port as int: %r "
                                    "(%s line %i)" % (port, lockfilename, ln))
                                port = None
                            else:
                                safe_print("Existing client using port", port)
                        if pid or port:
                            lock2pids_ports[lockfilename].append((pid, port))
                if not lock or lockfilename != applockfilename:
                    lockfile.unlock()
            except EnvironmentError as exception:
                # This shouldn't happen
                safe_print(
                    "Warning - could not read lockfile %s:" % lockfilename,
                    exception)
        if module not in multi_instance:
            # Check lockfile(s) and probe port(s)
            for lockfilename in [applockfilename]:
                incoming = None
                pids_ports = lock2pids_ports.get(lockfilename)
                if pids_ports:
                    pid, port = pids_ports[0]
                    appsocket = AppSocket()
                    if appsocket and port:
                        safe_print("Connecting to %s..." % port)
                        if appsocket.connect(host, port):
                            safe_print("Connected to", port)
                            # Other instance already running?
                            # Get appname to check if expected app is actually
                            # running under that port
                            safe_print("Getting instance name")
                            if appsocket.send("getappname"):
                                safe_print(
                                    "Sent scripting request, awaiting response..."
                                )
                                incoming = appsocket.read().rstrip("\4")
                                safe_print("Got response: %r" % incoming)
                                if incoming:
                                    if incoming != pyname:
                                        incoming = None
                                else:
                                    incoming = False
                        while incoming:
                            # Send args as UTF-8
                            if module == "apply-profiles":
                                # Always try to close currently running instance
                                safe_print("Closing existing instance")
                                cmd = "exit" if incoming == pyname else "close"
                                data = [cmd]
                                lock.unlock()
                            else:
                                # Send module/appname to notify running app
                                safe_print("Notifying existing instance")
                                data = [module or appname]
                                if module != "3DLUT-maker":
                                    for arg in sys.argv[1:]:
                                        data.append(
                                            safe_str(safe_unicode(arg),
                                                     "UTF-8"))
                            data = sp.list2cmdline(data)
                            if appsocket.send(data):
                                safe_print(
                                    "Sent scripting request, awaiting response..."
                                )
                                incoming = appsocket.read().rstrip("\4")
                                safe_print("Got response: %r" % incoming)
                                if module == "apply-profiles":
                                    if incoming == "":
                                        # Successfully sent our close request.
                                        incoming = "ok"
                                    elif incoming == "invalid" and cmd == "exit":
                                        # < 3.8.8.1 didn't have exit command
                                        continue
                            break
                        appsocket.close()
                else:
                    pid = None
                if not incoming:
                    if sys.platform == "win32":
                        import pywintypes
                        import win32ts
                        try:
                            osid = win32ts.ProcessIdToSessionId(opid)
                        except pywintypes.error as exception:
                            safe_print("Enumerating processes failed:",
                                       exception)
                            osid = None
                        try:
                            processes = win32ts.WTSEnumerateProcesses()
                        except pywintypes.error as exception:
                            safe_print("Enumerating processes failed:",
                                       exception)
                        else:
                            appname_lower = appname.lower()
                            exename_lower = exename.lower()
                            if module:
                                pyexe_lower = appname_lower + "-" + module + exe_ext
                            else:
                                pyexe_lower = appname_lower + exe_ext
                            incoming = None
                            for (sid, pid2, basename, usid) in processes:
                                basename_lower = basename.lower()
                                if ((pid and pid2 == pid
                                     and basename_lower == exename_lower) or
                                    ((osid is None or sid == osid)
                                     and basename_lower
                                     == pyexe_lower)) and pid2 != opid:
                                    # Other instance running
                                    incoming = False
                                    if module == "apply-profiles":
                                        if not os.path.isfile(lockfilename):
                                            # Create dummy lockfile
                                            try:
                                                with open(lockfilename, "w"):
                                                    pass
                                            except EnvironmentError as exception:
                                                safe_print(
                                                    "Warning - could "
                                                    "not create dummy "
                                                    "lockfile %s: %r" %
                                                    (lockfilename, exception))
                                            else:
                                                safe_print(
                                                    "Warning - had to "
                                                    "create dummy "
                                                    "lockfile", lockfilename)
                                        safe_print(
                                            "Closing existing instance "
                                            "with PID", pid2)
                                        startupinfo = sp.STARTUPINFO()
                                        startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW
                                        startupinfo.wShowWindow = sp.SW_HIDE
                                        lock.unlock()
                                        try:
                                            p = sp.Popen(
                                                [
                                                    "taskkill", "/PID",
                                                    "%s" % pid2
                                                ],
                                                stdin=sp.PIPE,
                                                stdout=sp.PIPE,
                                                stderr=sp.STDOUT,
                                                startupinfo=startupinfo)
                                            stdout, stderr = p.communicate()
                                        except Exception as exception:
                                            safe_print(exception)
                                        else:
                                            safe_print(stdout)
                                            if not p.returncode:
                                                # Successfully sent our close
                                                # request.
                                                incoming = "ok"
                if incoming == "ok":
                    # Successfully sent our request
                    if module == "apply-profiles":
                        # Wait for lockfile to be removed, in which case
                        # we know the running instance has successfully
                        # closed.
                        safe_print(
                            "Waiting for existing instance to exit and "
                            "delete lockfile", lockfilename)
                        while os.path.isfile(lockfilename):
                            sleep(.05)
                        lock.lock()
                        safe_print("Existing instance exited.")
                        incoming = None
                        if lockfilename in lock2pids_ports:
                            del lock2pids_ports[lockfilename]
                    break
            if incoming is not None:
                # Other instance running?
                import localization as lang
                lang.init()
                if incoming == "ok":
                    # Successfully sent our request
                    safe_print(lang.getstr("app.otherinstance.notified"))
                elif module == "apply-profiles":
                    safe_print("Not starting another instance.")
                else:
                    # Other instance busy?
                    handle_error(lang.getstr("app.otherinstance", name))
                # Exit
                return
    # Use exclusive lock during app startup
    with lock:
        # Create listening socket
        appsocket = AppSocket()
        if appsocket:
            if sys.platform != "win32":
                # https://docs.microsoft.com/de-de/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse#using-so_reuseaddr
                # From the above link: "The SO_REUSEADDR socket option allows
                # a socket to forcibly bind to a port in use by another socket".
                # Note that this is different from the behavior under Linux/BSD,
                # where a socket can only be (re-)bound if no active listening
                # socket is already bound to the address.
                # Consequently, we don't use SO_REUSEADDR under Windows.
                appsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            sys._appsocket = appsocket.socket
            if getcfg("app.allow_network_clients"):
                host = ""
            used_ports = [
                pid_port[1] for pids_ports in list(lock2pids_ports.values())
                for pid_port in pids_ports
            ]
            candidate_ports = [0]
            if not defaultport in used_ports:
                candidate_ports.insert(0, defaultport)
            for port in candidate_ports:
                try:
                    sys._appsocket.bind((host, port))
                except socket.error as exception:
                    if port == 0:
                        safe_print(
                            "Warning - could not bind to %s:%s:" %
                            (host, port), exception)
                        del sys._appsocket
                        break
                else:
                    try:
                        sys._appsocket.settimeout(.2)
                    except socket.error as exception:
                        safe_print(
                            "Warning - could not set socket "
                            "timeout:", exception)
                        del sys._appsocket
                        break
                    try:
                        sys._appsocket.listen(1)
                    except socket.error as exception:
                        safe_print("Warning - could not listen on "
                                   "socket:", exception)
                        del sys._appsocket
                        break
                    try:
                        port = sys._appsocket.getsockname()[1]
                    except socket.error as exception:
                        safe_print(
                            "Warning - could not get socket "
                            "address:", exception)
                        del sys._appsocket
                        break
                    sys._appsocket_port = port
                    break
        if not hasattr(sys, "_appsocket_port"):
            port = ""
        lock.seek(0)
        if module not in multi_instance:
            lock.truncate(0)
        if not port:
            lock.write("%s:%s" % (opid, port))
        else:
            lock.write(port)
        atexit.register(lambda: safe_print("Ran application exit handlers"))
        from wxwindows import BaseApp
        BaseApp.register_exitfunc(_exit, applockfilename, port)
        # Check for required resource files
        mod2res = {
            "3DLUT-maker": ["xrc/3dlut.xrc"],
            "curve-viewer": [],
            "profile-info": [],
            "scripting-client": [],
            "synthprofile": ["xrc/synthicc.xrc"],
            "testchart-editor": [],
            "VRML-to-X3D-converter": []
        }
        for filename in mod2res.get(module, resfiles):
            path = get_data_path(os.path.sep.join(filename.split("/")))
            if not path or not os.path.isfile(path):
                import localization as lang
                lang.init()
                raise ResourceError(
                    lang.getstr("resources.notfound.error") + "\n" + filename)
        # Create main data dir if it does not exist
        if not os.path.exists(datahome):
            try:
                os.makedirs(datahome)
            except Exception as exception:
                handle_error(
                    UserWarning("Warning - could not create "
                                "directory '%s'" % datahome))
        elif sys.platform == "darwin":
            # Check & fix permissions if necessary
            import getpass
            user = getpass.getuser().decode(fs_enc)
            script = []
            for directory in (confighome, datahome, logdir):
                if (os.path.isdir(directory)
                        and not os.access(directory, os.W_OK)):
                    script.append("chown -R '%s' '%s'" % (user, directory))
            if script:
                sp.call([
                    'osascript', '-e',
                    'do shell script "%s" with administrator privileges' %
                    ";".join(script).encode(fs_enc)
                ])
        # Initialize & run
        if module == "3DLUT-maker":
            from wxLUT3DFrame import main
        elif module == "curve-viewer":
            from wxLUTViewer import main
        elif module == "profile-info":
            from wxProfileInfo import main
        elif module == "scripting-client":
            from wxScriptingClient import main
        elif module == "synthprofile":
            from wxSynthICCFrame import main
        elif module == "testchart-editor":
            from wxTestchartEditor import main
        elif module == "VRML-to-X3D-converter":
            from wxVRML2X3D import main
        elif module == "apply-profiles":
            from profile_loader import main
        else:
            from DisplayCAL import main
    # Run main after releasing lock
    main()
Пример #9
0
def _excepthook(etype, value, tb):
    handle_error((etype, value, tb))