Exemple #1
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)
def can_update_cal(path):
    """ Check if cal can be updated by checking for required fields. """
    try:
        calstat = os.stat(path)
    except Exception as exception:
        safe_print("Warning - os.stat('%s') failed: %s" %
                   tuple(safe_unicode(s) for s in (path, exception)))
        return False
    if not path in cals or cals[path].mtime != calstat.st_mtime:
        try:
            cal = CGATS.CGATS(path)
        except (IOError, CGATS.CGATSInvalidError,
                CGATS.CGATSInvalidOperationError, CGATS.CGATSKeyError,
                CGATS.CGATSTypeError, CGATS.CGATSValueError) as exception:
            if path in cals:
                del cals[path]
            safe_print("Warning - couldn't process CGATS file '%s': %s" %
                       tuple(safe_unicode(s) for s in (path, exception)))
        else:
            if cal.queryv1("DEVICE_CLASS") == "DISPLAY" and not None in \
               (cal.queryv1("TARGET_WHITE_XYZ"),
             cal.queryv1("TARGET_GAMMA"),
             cal.queryv1("BLACK_POINT_CORRECTION"),
             cal.queryv1("QUALITY")):
                cals[path] = cal
    return path in cals and cals[path].mtime == calstat.st_mtime
 def write(self, *args, **kwargs):
     pad = kwargs.get("pad", self.pad)
     padchar = kwargs.get("padchar", self.padchar)
     sep = kwargs.get("sep", self.sep)
     end = kwargs.get("end", self.end)
     file_ = kwargs.get("file_", self.file)
     fn = kwargs.get("fn", self.fn)
     encoding = kwargs.get("encoding", self.encoding)
     strargs = []
     if encoding:
         cls = str
     else:
         cls = str
     for arg in args:
         if not isinstance(arg, cls):
             arg = safe_unicode(arg)
         if isinstance(arg, str) and encoding:
             arg = arg.encode(encoding, "asciize")
         strargs.append(arg)
     line = sep.join(strargs).rstrip(end)
     if pad is not False:
         if pad is True:
             width = _get_console_width()
         else:
             width = int(pad)
         line = line.ljust(width, padchar)
     if fn:
         fn(line)
     else:
         try:
             file_.write(line)
             if end:
                 file_.write(end)
         except IOError:
             pass
Exemple #4
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
Exemple #5
0
def get_data_path(relpath, rex=None):
	"""
	Search data_dirs for relpath and return the path or a file list.
	
	If relpath is a file, return the full path, if relpath is a directory,
	return a list of files in the intersection of searched directories.
	
	"""
	if (not relpath or relpath.endswith(os.path.sep) or
		(isinstance(os.path.altsep, basestring) and
		 relpath.endswith(os.path.altsep))):
		return None
	intersection = []
	paths = []
	for dir_ in data_dirs:
		curpath = os.path.join(dir_, relpath)
		if os.path.exists(curpath):
			if os.path.isdir(curpath):
				try:
					filelist = listdir_re(curpath, rex)
				except Exception, exception:
					from log import safe_print
					safe_print(u"Error - directory '%s' listing failed: %s" % 
							   tuple(safe_unicode(s) for s in (curpath, exception)))
				else:
					for filename in filelist:
						if not filename in intersection:
							intersection += [filename]
							paths += [os.path.join(curpath, filename)]
			else:
				return curpath
 def _schtasks(self, args, elevated=False, echo=False):
     if elevated:
         try:
             p = run_as_admin("schtasks.exe",
                              args,
                              close_process=False,
                              show=False)
         except pywintypes.error as exception:
             if exception.args[0] == winerror.ERROR_CANCELLED:
                 self.lastreturncode = winerror.ERROR_CANCELLED
             else:
                 raise
         else:
             self.lastreturncode = int(p["hProcess"].handle == 0)
             p["hProcess"].Close()
         finally:
             self.stdout = ""
     else:
         args.insert(0, "schtasks.exe")
         startupinfo = sp.STARTUPINFO()
         startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW
         startupinfo.wShowWindow = sp.SW_HIDE
         p = sp.Popen([safe_str(arg) for arg in args],
                      stdin=sp.PIPE,
                      stdout=sp.PIPE,
                      stderr=sp.STDOUT,
                      startupinfo=startupinfo)
         self.stdout, stderr = p.communicate()
         if echo:
             safe_print(safe_unicode(self.stdout, enc))
         self.lastreturncode = p.returncode
     return self.lastreturncode == 0
Exemple #7
0
 def wait(self):
     self.listening = True
     if self.logfile:
         self.logfile.write(
             lang.getstr("connecting.to", ("Chromecast", " " + self.name)) +
             "\n")
     if not hasattr(self, "_cc"):
         # Find our ChromeCast
         try:
             self._cc = next(cc for cc in get_chromecasts() if safe_unicode(
                 cc.device.friendly_name, "UTF-8") == self.name)
         except StopIteration:
             self.listening = False
             raise
         self._cc.register_handler(self._controller)
     # Wait for ChromeCast device to be ready
     while self.listening:
         self._cc.wait(0.05)
         if self._cc.status:
             break
     if self.listening:
         # Launch pattern generator app
         self._controller.launch()
         # Wait for it
         while (self.listening
                and self._cc.app_id != self._controller.supporting_app_id):
             sleep(0.05)
         self.conn = True
         safe_print(lang.getstr("connection.established"))
Exemple #8
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)))
def main():
    if "--help" in sys.argv[1:] or (not sys.argv[1:] and not gui):
        safe_print("Convert VRML file to X3D")
        safe_print("Author: Florian Hoech, licensed under the GPL version 3")
        safe_print("Usage: %s [OPTION]... FILE..." %
                   os.path.basename(sys.argv[0]))
        safe_print("The output is written to FILENAME.x3d(.html)")
        safe_print("")
        safe_print("  --embed      Embed viewer components in HTML instead of "
                   "referencing them")
        safe_print("  --force      Force fresh download of viewer components")
        safe_print("  --no-cache   Don't use viewer components cache (only "
                   "uses existing cache if")
        safe_print("               embedding components, can be overridden "
                   "with --force)")
        if gui:
            safe_print("  --no-gui     Don't use GUI (console mode)")
        safe_print("  --no-html    Don't generate HTML file")
        safe_print("  --view       View the generated file (if no GUI)")
        if not gui:
            safe_print("  --batch      Don't pause after processing")
        safe_print("  FILE         Filename of VRML file to convert")
        if gui:
            return
    if gui:
        config.initcfg("VRML-to-X3D-converter")
        lang.init()
        lang.update_defaults()
    cache = not "--no-cache" in sys.argv[1:]
    embed = "--embed" in sys.argv
    force = "--force" in sys.argv
    html = not "--no-html" in sys.argv[1:]
    if not gui:
        result = None
        view = "--view" in sys.argv[1:]
        for arg in sys.argv[1:]:
            if not arg.startswith("--"):
                result = vrmlfile2x3dfile(safe_unicode(arg),
                                          html=html,
                                          embed=embed,
                                          view=view,
                                          force=force,
                                          cache=cache,
                                          gui=gui)
        if result is None:
            safe_print("No filename given.")
        if sys.stdout.isatty() and not "--batch" in sys.argv[1:]:
            input("Press RETURN to exit")
        sys.exit(int(not result))
    else:
        view = not "--no-view" in sys.argv[1:]
        app = BaseApp(0)
        app.TopWindow = VRML2X3DFrame(html, embed, view, force, cache)
        if sys.platform == "darwin":
            app.TopWindow.init_menubar()
        wx.CallLater(1, _main, app)
        app.MainLoop()
Exemple #10
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
Exemple #11
0
def create(report_path, placeholders2data, pack=True, templatename="report"):
    """ Create a report with all placeholders substituted by data. """
    # read report template
    templatefilename = "%s.html" % templatename
    report_html_template_path = get_data_path(
        os.path.join("report", templatefilename))
    if not report_html_template_path:
        raise IOError(lang.getstr("file.missing", templatefilename))
    try:
        report_html_template = codecs.open(report_html_template_path, "r",
                                           "UTF-8")
    except (IOError, OSError) as exception:
        raise exception.__class__(
            lang.getstr("error.file.open", report_html_template_path))
    report_html = report_html_template.read()
    report_html_template.close()

    # create report
    for placeholder, data in placeholders2data.items():
        report_html = report_html.replace(placeholder, data)

    for include in ("base.css", "compare.css", "print.css",
                    "jsapi-packages.js", "jsapi-patches.js",
                    "compare.constants.js", "compare.variables.js",
                    "compare.functions.js", "compare.init.js",
                    "uniformity.functions.js"):
        path = get_data_path(os.path.join("report", include))
        if not path:
            raise IOError(lang.getstr("file.missing", include))
        try:
            f = codecs.open(path, "r", "UTF-8")
        except (IOError, OSError) as exception:
            raise exception.__class__(lang.getstr("error.file.open", path))
        if include.endswith(".js"):
            js = f.read()
            if pack:
                packer = jspacker.JavaScriptPacker()
                js = packer.pack(js, 62, True).strip()
            report_html = report_html.replace(
                'src="%s">' % include, ">/*<![CDATA[*/\n" + js + "\n/*]]>*/")
        else:
            report_html = report_html.replace('@import "%s";' % include,
                                              f.read().strip())
        f.close()

    # write report
    try:
        report_html_file = codecs.open(report_path, "w", "UTF-8")
    except (IOError, OSError) as exception:
        raise exception.__class__(
            lang.getstr("error.file.create", report_path) + "\n\n" +
            safe_unicode(exception))
    report_html_file.write(report_html)
    report_html_file.close()
def add_dispcal_options_to_cal(cal, options_dispcal):
    # Add dispcal options to cal
    options_dispcal = quote_nonoption_args(options_dispcal)
    try:
        cgats = CGATS.CGATS(cal)
        cgats[0].add_section(
            "ARGYLL_DISPCAL_ARGS",
            " ".join(options_dispcal).encode("UTF-7", "replace"))
        return cgats
    except Exception as exception:
        safe_print(safe_unicode(traceback.format_exc()))
Exemple #13
0
	def get_single_response(self):
		# Buffer received data until EOT (response end marker) and return
		# single response (additional data will still be in the buffer)
		while not "\4" in self.recv_buffer:
			incoming = self.recv(4096)
			if incoming == "":
				raise socket.error(lang.getstr("connection.broken"))
			self.recv_buffer += incoming
		end = self.recv_buffer.find("\4")
		single_response = self.recv_buffer[:end]
		self.recv_buffer = self.recv_buffer[end + 1:]
		return safe_unicode(single_response, "UTF-8")
Exemple #14
0
 def exit(self, raise_exception=True):
     self.close(raise_exception)
     if self.temp and os.path.isfile(self.profile_path):
         os.remove(self.profile_path)
         if self.tempdir and not os.listdir(self.tempdir):
             try:
                 shutil.rmtree(self.tempdir, True)
             except Exception as exception:
                 safe_print("Warning - temporary directory '%s' could "
                            "not be removed: %s" % tuple(
                                safe_unicode(s)
                                for s in (self.tempdir, exception)))
def cal_to_fake_profile(cal):
    """ 
	Create and return a 'fake' ICCProfile with just a vcgt tag.
	
	cal must refer to a valid Argyll CAL file and can be a CGATS instance 
	or a filename.
	
	"""
    vcgt, cal = cal_to_vcgt(cal, True)
    if not vcgt:
        return
    profile = ICCP.ICCProfile()
    profile.fileName = cal.filename
    profile._data = "\0" * 128
    profile._tags.desc = ICCP.TextDescriptionType("", "desc")
    profile._tags.desc.ASCII = safe_unicode(os.path.basename(
        cal.filename)).encode("ascii", "asciize")
    profile._tags.desc.Unicode = safe_unicode(os.path.basename(cal.filename))
    profile._tags.vcgt = vcgt
    profile.size = len(profile.data)
    profile.is_loaded = True
    return profile
Exemple #16
0
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", 
							  appname + " Preferences")
	else:
		oldcfg = os.path.join(expanduseru("~"), "." + appname)
	makecfgdir()
	if os.path.exists(confighome) and \
	   not os.path.exists(os.path.join(confighome, appname + ".ini")):
		try:
			if os.path.isfile(oldcfg):
				oldcfg_file = open(oldcfg, "rb")
				oldcfg_contents = oldcfg_file.read()
				oldcfg_file.close()
				cfg_file = open(os.path.join(confighome, appname + ".ini"), 
								"wb")
				cfg_file.write("[Default]\n" + oldcfg_contents)
				cfg_file.close()
			elif sys.platform == "win32":
				key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, 
									  "Software\\" + appname)
				numsubkeys, numvalues, mtime = _winreg.QueryInfoKey(key)
				cfg_file = open(os.path.join(confighome, appname + ".ini"), 
								"wb")
				cfg_file.write("[Default]\n")
				for i in range(numvalues):
					name, value, type_ = _winreg.EnumValue(key, i)
					if type_ == 1: cfg_file.write((u"%s = %s\n" % (name, 
												   value)).encode("UTF-8"))
				cfg_file.close()
		except Exception, exception:
			# WindowsError 2 means registry key does not exist, do not show 
			# warning in that case
			if sys.platform != "win32" or not hasattr(exception, "errno") or \
			   exception.errno != 2:
				from log import safe_print
				safe_print("Warning - could not process old configuration:", 
						   safe_unicode(exception))
		# Set a few defaults which have None as possible value and thus cannot
		# be set in the 'defaults' collection
		setcfg("gamap_src_viewcond", "mt")
		setcfg("gamap_out_viewcond", "mt")
Exemple #17
0
def get_file_logger(name, level=logging.DEBUG, when="midnight", backupCount=0):
	logger = logging.getLogger(name)
	logger.setLevel(level)
	logfile = os.path.join(logdir, name + ".log")
	for handler in logger.handlers:
		if (isinstance(handler, logging.handlers.TimedRotatingFileHandler) and
			handler.baseFilename == os.path.abspath(logfile)):
			return logger
	if not os.path.exists(logdir):
		try:
			os.makedirs(logdir)
		except Exception, exception:
			safe_print(u"Warning - log directory '%s' could not be created: %s" 
					   % tuple(safe_unicode(s) for s in (logdir, exception)))
Exemple #18
0
 def disconnect(self):
     if self.conn:
         try:
             peer = self.conn.getpeername()
             self.conn.shutdown(socket.SHUT_RDWR)
         except socket.error as exception:
             if exception.errno != errno.ENOTCONN:
                 self.add_text(safe_unicode(exception) + "\n")
         else:
             self.add_text(lang.getstr("disconnected.from", peer) + "\n")
         self.conn.close()
         del self.conn
         self.conn = None
         self.commands = []
     else:
         self.add_error_text(lang.getstr("not_connected") + "\n")
def add_options_to_ti3(ti3, options_dispcal=None, options_colprof=None):
    # Add dispcal and colprof options to ti3
    try:
        cgats = CGATS.CGATS(ti3)
        if options_colprof:
            options_colprof = quote_nonoption_args(options_colprof)
            cgats[0].add_section(
                "ARGYLL_COLPROF_ARGS",
                " ".join(options_colprof).encode("UTF-7", "replace"))
        if options_dispcal and 1 in cgats:
            options_dispcal = quote_nonoption_args(options_dispcal)
            cgats[1].add_section(
                "ARGYLL_DISPCAL_ARGS",
                " ".join(options_dispcal).encode("UTF-7", "replace"))
        return cgats
    except Exception as exception:
        safe_print(safe_unicode(traceback.format_exc()))
def cal_to_vcgt(cal, return_cgats=False):
    """ 
	Create a vcgt tag from calibration data.
	
	cal must refer to a valid Argyll CAL file and can be a CGATS instance 
	or a filename.
	
	"""
    if not isinstance(cal, CGATS.CGATS):
        try:
            cal = CGATS.CGATS(cal)
        except (IOError, CGATS.CGATSInvalidError,
                CGATS.CGATSInvalidOperationError, CGATS.CGATSKeyError,
                CGATS.CGATSTypeError, CGATS.CGATSValueError) as exception:
            safe_print("Warning - couldn't process CGATS file '%s': %s" %
                       tuple(safe_unicode(s) for s in (cal, exception)))
            return None
    required_fields = ("RGB_I", "RGB_R", "RGB_G", "RGB_B")
    data_format = cal.queryv1("DATA_FORMAT")
    if data_format:
        for field in required_fields:
            if not field in list(data_format.values()):
                if debug: safe_print("[D] Missing required field:", field)
                return None
        for field in list(data_format.values()):
            if not field in required_fields:
                if debug: safe_print("[D] Unknown field:", field)
                return None
    entries = cal.queryv(required_fields)
    if len(entries) < 1:
        if debug:
            safe_print("[D] No entries found in calibration", cal.filename)
        return None
    vcgt = ICCP.VideoCardGammaTableType("", "vcgt")
    vcgt.update({
        "channels": 3,
        "entryCount": len(entries),
        "entrySize": 2,
        "data": [[], [], []]
    })
    for n in entries:
        for i in range(3):
            vcgt.data[i].append(entries[n][i + 1] * 65535.0)
    if return_cgats:
        return vcgt, cal
    return vcgt
Exemple #21
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", ""))
Exemple #22
0
def getstr(id_str, strvars=None, lcode=None, default=None):
	""" Get a translated string from the dictionary """
	if not lcode:
		lcode = getcode()
	if not lcode in ldict or not id_str in ldict[lcode]:
		# fall back to english
		lcode = "en"
	if lcode in ldict and id_str in ldict[lcode]:
		lstr = ldict[lcode][id_str]
		if debug:
			if not id_str in usage or not isinstance(usage[id_str], int):
				usage[id_str] = 1
			else:
				usage[id_str] += 1
		if strvars is not None:
			if not isinstance(strvars, (list, tuple)):
				strvars = [strvars]
			fmt = re.findall(r"%\d?(?:\.\d+)?[deEfFgGiorsxX]", lstr)
			if len(fmt) == len(strvars):
				if not isinstance(strvars, list):
					strvars = list(strvars)
				for i, s in enumerate(strvars):
					if fmt[i].endswith("s"):
						s = safe_unicode(s)
					elif not fmt[i].endswith("r"):
						try:
							if fmt[i][-1] in "dioxX":
								s = int(s)
							else:
								s = float(s)
						except (TypeError, ValueError):
							s = 0
					strvars[i] = s
				lstr %= tuple(strvars)
		return lstr
	else:
		if (debug and id_str and not isinstance(id_str, str) and
			not " " in id_str):
			usage[id_str] = 0
		return default or id_str
Exemple #23
0
 def check_result(self,
                  delayedResult,
                  get_response=False,
                  additional_commands=None,
                  colorize=True):
     try:
         result = delayedResult.get()
     except Exception as exception:
         if hasattr(exception, "originalTraceback"):
             self.add_text(exception.originalTraceback)
         result = exception
     if result:
         if isinstance(result, socket.socket):
             self.conn = result
             result = lang.getstr("connection.established")
         text = "%s\n" % safe_unicode(result)
         self.add_text(text)
         if colorize or isinstance(result, Exception):
             end = self.console.GetLastPosition()
             start = end - len(text)
             if isinstance(result, Exception):
                 color = ERRORCOLOR
             else:
                 color = RESPONSECOLOR
             self.mark_text(start, end, color)
     if get_response and not isinstance(result, Exception):
         delayedresult.startWorker(self.check_result,
                                   get_response,
                                   cargs=(False, additional_commands))
     else:
         self.add_text("> ")
         if additional_commands:
             self.add_text(additional_commands[0].rstrip("\n"))
             if additional_commands[0].endswith("\n"):
                 self.send_command_handler(additional_commands[0],
                                           additional_commands[1:])
                 return
         self.console.SetFocus()
         self.busy = False
Exemple #24
0
    def html(self,
             title="Untitled",
             xhtml=False,
             embed=False,
             force=False,
             cache=True):
        """
		Convert X3D to HTML
		
		This will generate HTML5 by default unless you set xhtml=True.
		
		If embed is True, the X3DOM runtime and X3D viewer will be embedded in
		the HTML (increases filesize considerably)
		
		"""
        # Get children of X3D document
        x3d_html = re.sub("\s*</?X3D(?:\s+[^>]*)?>\s*", "",
                          self.markup(xhtml, True))
        if not xhtml:
            # Convert uppercase letters at start of tag name to lowercase
            x3d_html = re.sub("(</?[0-9A-Z]+)",
                              lambda match: match.groups()[0].lower(),
                              x3d_html)
        # Indent
        x3d_html = "\n".join(
            ["\t" * 2 + line for line in x3d_html.splitlines()]).lstrip()

        # Collect resources
        def get_resource(url, source=True):
            baseurl, basename = os.path.split(url)
            # Strip protocol
            cache_uri = re.sub("^\w+://", "", baseurl)
            # Strip www
            cache_uri = re.sub("^(?:www\.)?", "", cache_uri)
            # domain.com -> com.domain
            domain, path = cache_uri.split("/", 1)
            cache_uri = "/".join([".".join(reversed(domain.split("."))), path])
            # com.domain/path -> com.domain.path
            cache_uri = re.sub("^([^/]+)/", "\\1.", cache_uri)
            cachedir = os.path.join(cachepath,
                                    os.path.join(*cache_uri.split("/")))
            if not os.path.isdir(cachedir):
                _safe_print("Creating cache directory:", cachedir)
                os.makedirs(cachedir)
            cachefilename = os.path.join(cachedir, basename)
            body = ""
            if not force and os.path.isfile(cachefilename):
                _safe_print("Using cached file:", cachefilename)
                with open(cachefilename, "rb") as cachefile:
                    body = cachefile.read()
            if not body.strip():
                for url in (url, url.replace("https://", "http://")):
                    _safe_print("Requesting:", url)
                    try:
                        response = urllib.request.urlopen(url)
                    except (socket.error, urllib.error.URLError,
                            http.client.HTTPException) as exception:
                        _safe_print(exception)
                    else:
                        body = response.read()
                        response.close()
                        break
            if not body.strip():
                # Fallback to local copy
                url = get_data_path("x3d-viewer/" + basename)
                if not url:
                    _safe_print("Error: Resource not found:", basename)
                    return
                with open(url, "rb") as resource_file:
                    body = resource_file.read()
            if body.strip():
                if cache and (force or not os.path.isfile(cachefilename)):
                    with open(cachefilename, "wb") as cachefile:
                        cachefile.write(body)
                if source and not basename.endswith(".swf"):
                    if basename.endswith(".css"):
                        return "<style>%s</style>" % body
                    elif basename.endswith(".js"):
                        return "<script>%s" % body
                    else:
                        return body
                else:
                    return "file:///" + safe_unicode(cachefilename).encode(
                        "UTF-8").lstrip("/").replace(os.path.sep, "/")
            else:
                _safe_print("Error: Empty document:", url)
                if os.path.isfile(cachefilename):
                    _safe_print("Removing", cachefilename)
                    os.remove(cachefilename)

        # Get HTML template from cache or online
        html = get_resource(
            "https://%s/x3d-viewer/release/x3d-viewer.html" % domain.lower(),
            True)
        if cache or embed:
            # Update resources in HTML
            restags = re.findall("<[^>]+\s+data-fallback-\w+=[^>]*>", html)
            for restag in restags:
                attrname = re.search(r"\s+data-fallback-(\w+)=",
                                     restag).groups()[0]
                url = re.search(r"\s+%s=([\"'])(.+?)\1" % attrname,
                                restag).groups()[1]
                if url.endswith(".swf") and not cache:
                    continue
                resource = get_resource(url, embed)
                if not resource:
                    continue
                if embed and not url.endswith(".swf"):
                    html = html.replace(restag, resource)
                else:
                    updated_restag = re.sub(
                        r"(\s+data-fallback-%s=)([\"']).+?\2" % attrname,
                        create_replace_function(r"\1\2%s\2", resource), restag)
                    html = html.replace(restag, updated_restag)
        # Update title
        html = re.sub(
            "(<title>)[^<]*(</title>)",
            create_replace_function(r"\1%s\2",
                                    safe_unicode(title).encode("UTF-8")), html)
        # Insert X3D
        html = html.replace("</x3d>", "\t" + x3d_html + "\n\t\t</x3d>")
        # Finish
        if xhtml:
            html = "<?xml version='1.0' encoding='UTF-8'?>\n" + html
            html = re.sub("\s*/>", " />", html)
        else:
            html = re.sub("\s*/>", ">", html)
        return html
Exemple #25
0
 def get_resource(url, source=True):
     baseurl, basename = os.path.split(url)
     # Strip protocol
     cache_uri = re.sub("^\w+://", "", baseurl)
     # Strip www
     cache_uri = re.sub("^(?:www\.)?", "", cache_uri)
     # domain.com -> com.domain
     domain, path = cache_uri.split("/", 1)
     cache_uri = "/".join([".".join(reversed(domain.split("."))), path])
     # com.domain/path -> com.domain.path
     cache_uri = re.sub("^([^/]+)/", "\\1.", cache_uri)
     cachedir = os.path.join(cachepath,
                             os.path.join(*cache_uri.split("/")))
     if not os.path.isdir(cachedir):
         _safe_print("Creating cache directory:", cachedir)
         os.makedirs(cachedir)
     cachefilename = os.path.join(cachedir, basename)
     body = ""
     if not force and os.path.isfile(cachefilename):
         _safe_print("Using cached file:", cachefilename)
         with open(cachefilename, "rb") as cachefile:
             body = cachefile.read()
     if not body.strip():
         for url in (url, url.replace("https://", "http://")):
             _safe_print("Requesting:", url)
             try:
                 response = urllib.request.urlopen(url)
             except (socket.error, urllib.error.URLError,
                     http.client.HTTPException) as exception:
                 _safe_print(exception)
             else:
                 body = response.read()
                 response.close()
                 break
     if not body.strip():
         # Fallback to local copy
         url = get_data_path("x3d-viewer/" + basename)
         if not url:
             _safe_print("Error: Resource not found:", basename)
             return
         with open(url, "rb") as resource_file:
             body = resource_file.read()
     if body.strip():
         if cache and (force or not os.path.isfile(cachefilename)):
             with open(cachefilename, "wb") as cachefile:
                 cachefile.write(body)
         if source and not basename.endswith(".swf"):
             if basename.endswith(".css"):
                 return "<style>%s</style>" % body
             elif basename.endswith(".js"):
                 return "<script>%s" % body
             else:
                 return body
         else:
             return "file:///" + safe_unicode(cachefilename).encode(
                 "UTF-8").lstrip("/").replace(os.path.sep, "/")
     else:
         _safe_print("Error: Empty document:", url)
         if os.path.isfile(cachefilename):
             _safe_print("Removing", cachefilename)
             os.remove(cachefilename)
Exemple #26
0
 def __init__(self,
              profile,
              intent="r",
              direction="f",
              order="n",
              pcs=None,
              scale=1,
              cwd=None,
              startupinfo=None,
              use_icclu=False,
              use_cam_clipping=False,
              logfile=None,
              worker=None,
              show_actual_if_clipped=False,
              input_encoding=None,
              output_encoding=None,
              convert_video_rgb_to_clut65=False,
              verbose=1):
     if not profile:
         raise Error("Xicclu: Profile is %r" % profile)
     WorkerBase.__init__(self)
     self.scale = scale
     self.convert_video_rgb_to_clut65 = convert_video_rgb_to_clut65
     self.logfile = logfile
     self.worker = worker
     self.temp = False
     utilname = "icclu" if use_icclu else "xicclu"
     xicclu = get_argyll_util(utilname)
     if not xicclu:
         raise Error(lang.getstr("argyll.util.not_found", utilname))
     if not isinstance(profile, (CGATS.CGATS, ICCP.ICCProfile)):
         if profile.lower().endswith(".cal"):
             profile = CGATS.CGATS(profile)
         else:
             profile = ICCP.ICCProfile(profile)
     is_profile = isinstance(profile, ICCP.ICCProfile)
     if (is_profile and profile.version >= 4
             and not profile.convert_iccv4_tags_to_iccv2()):
         raise Error("\n".join([
             lang.getstr("profile.iccv4.unsupported"),
             profile.getDescription()
         ]))
     if not profile.fileName or not os.path.isfile(profile.fileName):
         if profile.fileName:
             prefix = os.path.basename(profile.fileName)
         elif is_profile:
             prefix = make_filename_safe(profile.getDescription(),
                                         concat=False) + profile_ext
         else:
             # CGATS (.cal)
             prefix = "cal"
         prefix += "-"
         if not cwd:
             cwd = self.create_tempdir()
             if isinstance(cwd, Exception):
                 raise cwd
         fd, profile.fileName = tempfile.mkstemp("", prefix, dir=cwd)
         stream = os.fdopen(fd, "wb")
         profile.write(stream)
         stream.close()
         self.temp = True
     elif not cwd:
         cwd = os.path.dirname(profile.fileName)
     profile_basename = safe_unicode(os.path.basename(profile.fileName))
     profile_path = profile.fileName
     if sys.platform == "win32":
         profile_path = win32api.GetShortPathName(profile_path)
     self.profile_path = safe_str(profile_path)
     if sys.platform == "win32" and not startupinfo:
         startupinfo = sp.STARTUPINFO()
         startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW
         startupinfo.wShowWindow = sp.SW_HIDE
     xicclu = safe_str(xicclu)
     cwd = safe_str(cwd)
     self.verbose = verbose
     args = [xicclu, "-v%i" % verbose, "-s%s" % scale]
     self.show_actual_if_clipped = False
     if utilname == "xicclu":
         if (is_profile and show_actual_if_clipped
                 and "A2B0" in profile.tags
                 and ("B2A0" in profile.tags or direction == "if")):
             args.append("-a")
             self.show_actual_if_clipped = True
         if use_cam_clipping:
             args.append("-b")
         if get_argyll_version("xicclu") >= [1, 6]:
             # Add encoding parameters
             # Note: Not adding -e -E can cause problems due to unitialized
             # in_tvenc and out_tvenc variables in xicclu.c for Argyll 1.6.x
             if not input_encoding:
                 input_encoding = "n"
             if not output_encoding:
                 output_encoding = "n"
             args += [
                 "-e" + safe_str(input_encoding),
                 "-E" + safe_str(output_encoding)
             ]
     args.append("-f" + direction)
     self.output_scale = 1.0
     if is_profile:
         if profile.profileClass not in ("abst", "link"):
             args.append("-i" + intent)
             if order != "n":
                 args.append("-o" + order)
         if profile.profileClass != "link":
             if (direction in ("f", "ib") and
                 (pcs == "x" or
                  (profile.connectionColorSpace == "XYZ" and not pcs))):
                 # In case of forward lookup with XYZ PCS, use 0..100 scaling
                 # internally so we get extra precision from xicclu for the
                 # decimal part. Scale back to 0..1 later.
                 pcs = "X"
                 self.output_scale = 100.0
             if pcs:
                 args.append("-p" + pcs)
     args.append(self.profile_path)
     if debug or verbose > 1:
         self.sessionlogfile = LogFile(profile_basename + ".xicclu",
                                       os.path.dirname(profile.fileName))
         if is_profile:
             profile_act = ICCP.ICCProfile(profile.fileName)
             self.sessionlogfile.write(
                 "Profile ID %s (actual %s)" % (hexlify(
                     profile.ID), hexlify(profile_act.calculateID(False))))
         if cwd:
             self.log(lang.getstr("working_dir"))
             indent = "  "
             for name in cwd.split(os.path.sep):
                 self.log(
                     textwrap.fill(name + os.path.sep,
                                   80,
                                   expand_tabs=False,
                                   replace_whitespace=False,
                                   initial_indent=indent,
                                   subsequent_indent=indent))
                 indent += " "
             self.log("")
         self.log(lang.getstr("commandline"))
         printcmdline(xicclu, args[1:], fn=self.log, cwd=cwd)
         self.log("")
     self.startupinfo = startupinfo
     self.args = args
     self.cwd = cwd
     self.spawn()
Exemple #27
0
	for handler in logger.handlers:
		if (isinstance(handler, logging.handlers.TimedRotatingFileHandler) and
			handler.baseFilename == os.path.abspath(logfile)):
			return logger
	if not os.path.exists(logdir):
		try:
			os.makedirs(logdir)
		except Exception, exception:
			safe_print(u"Warning - log directory '%s' could not be created: %s" 
					   % tuple(safe_unicode(s) for s in (logdir, exception)))
	elif os.path.exists(logfile):
		try:
			logstat = os.stat(logfile)
		except Exception, exception:
			safe_print(u"Warning - os.stat('%s') failed: %s" % 
					   tuple(safe_unicode(s) for s in (logfile, exception)))
		else:
			# rollover needed?
			try:
				mtime = localtime(logstat.st_mtime)
			except ValueError, exception:
				# This can happen on Windows because localtime() is buggy on
				# that platform. See:
				# http://stackoverflow.com/questions/4434629/zipfile-module-in-python-runtime-problems
				# http://bugs.python.org/issue1760357
				# To overcome this problem, we ignore the real modification
				# date and force a rollover
				mtime = localtime(time() - 60 * 60 * 24)
			if localtime()[:3] > mtime[:3]:
				# do rollover
				logbackup = logfile + strftime(".%Y-%m-%d", mtime)
    def __init__(self, parent, cgats, worker=None):
        """
		Init new CCXPlot window.

		parent   Parent window (only used for error dialogs)
		cgats    A CCMX/CCSS CGATS instance
		worker   Worker instance
		
		"""

        self.is_ccss = cgats[0].type == "CCSS"

        desc = cgats.get_descriptor()

        if cgats.filename:
            fn, ext = os.path.splitext(os.path.basename(cgats.filename))
        else:
            fn = desc
            if self.is_ccss:
                ext = ".ccss"
            else:
                ext = ".ccmx"

        desc = lang.getstr(ext[1:] + "." + fn, default=desc)

        if self.is_ccss:
            ccxx_type = "spectral"
        else:
            ccxx_type = "matrix"

        title = "%s: %s" % (lang.getstr(ccxx_type), desc)

        if self.is_ccss:
            # Convert to TI3 so we can get XYZ from spectra for coloring

            temp = worker.create_tempdir()
            if isinstance(temp, Exception):
                show_result_dialog(temp, parent)
            else:
                basename = make_filename_safe(desc)
                temp_path = os.path.join(temp, basename + ".ti3")

                cgats[0].type = "CTI3"
                cgats[0].DEVICE_CLASS = "DISPLAY"
                cgats.write(temp_path)

                temp_out_path = os.path.join(temp, basename + ".CIE.ti3")

                result = worker.exec_cmd(get_argyll_util("spec2cie"),
                                         [temp_path, temp_out_path],
                                         capture_output=True)
                if isinstance(result, Exception) or not result:
                    show_result_dialog(
                        UnloggedError(result or "".join(worker.errors)),
                        parent)
                    worker.wrapup(False)
                else:
                    try:
                        cgats = CGATS.CGATS(temp_out_path)
                    except Exception as exception:
                        show_result_dialog(exception, parent)
                    finally:
                        worker.wrapup(False)

        data_format = cgats.queryv1("DATA_FORMAT")
        data = cgats.queryv1("DATA")

        XYZ_max = 0
        self.samples = []

        if self.is_ccss:
            x_min = cgats.queryv1("SPECTRAL_START_NM")
            x_max = cgats.queryv1("SPECTRAL_END_NM")
            bands = cgats.queryv1("SPECTRAL_BANDS")
            lores = bands <= 40
            if lores:
                # Interpolate if lores
                # 1nm intervals
                steps = int(x_max - x_min) + 1
                safe_print("Up-interpolating", bands, "spectral bands to",
                           steps)
                step = (x_max - x_min) / (steps - 1.)
            else:
                step = (x_max - x_min) / (bands - 1.)
            y_min = 0
            y_max = 1

            Y_max = 0
            for i, sample in data.items():
                # Get nm and spectral power
                values = []
                x = x_min
                for k in data_format.values():
                    if k.startswith("SPEC_"):
                        y = sample[k]
                        y_min = min(y, y_min)
                        y_max = max(y, y_max)
                        if lores:
                            values.append(y)
                        else:
                            values.append((x, y))
                            x += step
                if lores:
                    # Interpolate if lores. Use Catmull-Rom instead of
                    # PolySpline as we want curves to go through points exactly
                    numvalues = len(values)
                    interp = ICCP.CRInterpolation(values)
                    values = []
                    for i in range(steps):
                        values.append(
                            (x, interp(i / (steps - 1.) * (numvalues - 1.))))
                        x += step
                # Get XYZ for colorization
                XYZ = []
                for component in "XYZ":
                    label = "XYZ_" + component
                    if label in sample:
                        v = sample[label]
                        XYZ_max = max(XYZ_max, v)
                        if label == "XYZ_Y":
                            Y_max = max(Y_max, v)
                        XYZ.append(v)
                self.samples.append((XYZ, values, {}))

            Plot = plot.PolyLine
            Plot._attributes["width"] = 1
        else:
            # CCMX
            cube_size = 2

            x_min = 0

            y_min = 0

            mtx = colormath.Matrix3x3(
                [[sample[k] for k in data_format.values()]
                 for sample in data.values()])
            imtx = mtx.inverted()

            # Get XYZ that colorimeter would measure without matrix (sRGB ref,
            # so not accurate, but useful for visual representation which is all
            # we care about here)
            if cube_size == 2:
                scale = 1
                x_max = 100 * scale
                y_max = x_max * (74.6 / 67.4)
                if sys.platform != "win32":
                    x_center = x_max / 2.
                else:
                    x_center = x_max / 2. - 2.5
                y_center = y_max / 2.
                x_center *= scale
                y_center *= scale
                pos2rgb = [((x_center - 23.7, y_center - 13.7), (0, 0, 1)),
                           ((x_center, y_center + 27.3), (0, 1, 0)),
                           ((x_center + 23.7, y_center - 13.7), (1, 0, 0)),
                           ((x_center - 23.7, y_center + 13.7), (0, 1, 1)),
                           ((x_center, y_center - 27.3), (1, 0, 1)),
                           ((x_center + 23.7, y_center + 13.7), (1, 1, 0)),
                           ((x_center, y_center), (1, 1, 1))]
                attrs_c = {'size': 10}
                attrs_r = {'size': 5}
            else:
                x_max = 100
                y_max = 100
                y = -5
                pos2rgb = []
                for R in range(cube_size):
                    for G in range(cube_size):
                        x = -5
                        y += 10
                        for B in range(cube_size):
                            x += 10
                            pos2rgb.append(((x, y), (v / (cube_size - 1.0)
                                                     for v in (R, G, B))))
                attrs_c = {'marker': 'square', 'size': 10}
                attrs_r = {'marker': 'square', 'size': 5}
            Y_max = (imtx * colormath.get_whitepoint("D65"))[1]
            for i, ((x, y), (R, G, B)) in enumerate(pos2rgb):
                XYZ = list(colormath.RGB2XYZ(R, G, B))
                X, Y, Z = imtx * XYZ
                XYZ_max = max(XYZ_max, X, Y, Z)
                self.samples.append(([X, Y, Z], [(x, y)], attrs_c))
                self.samples.append((XYZ, [(x, y)], attrs_r))

            Plot = plot.PolyMarker

        if self.is_ccss:
            # Protect against division by zero when range is zero
            if not x_max - x_min:
                x_min = 350.0
                x_max = 750.0
            if not y_max - y_min:
                y_min = 0.0
                y_max = 10.0

            y_zero = 0

            self.ccxx_axis_x = (math.floor(x_min / 50.) * 50,
                                math.ceil(x_max / 50.) * 50)
            self.spec_x = (self.ccxx_axis_x[1] - self.ccxx_axis_x[0]) / 50.
            graph_range = nicenum(y_max - y_zero, False)
            d = nicenum(graph_range / (NTICK - 1.0), True)
            self.spec_y = math.ceil(y_max / d)
            self.ccxx_axis_y = (math.floor(y_zero / d) * d, self.spec_y * d)
        else:
            self.ccxx_axis_x = (math.floor(x_min / 20.) * 20,
                                math.ceil(x_max / 20.) * 20)
            self.ccxx_axis_y = (math.floor(y_min), math.ceil(y_max))

        self.gfx = []
        for XYZ, values, attrs in self.samples:
            if len(XYZ) == 3:
                # Got XYZ
                if attrs.get("size") > 11.25:
                    # Colorimeter XYZ
                    if Y_max > 1:
                        # Colorimeter brighter than ref
                        XYZ[:] = [v / Y_max for v in XYZ]
                    else:
                        # Colorimeter dimmer than ref
                        XYZ[:] = [v * Y_max for v in XYZ]
                else:
                    # Ref XYZ
                    if Y_max > 1:
                        # Colorimeter brighter than ref
                        XYZ[:] = [v / Y_max for v in XYZ]
                RGB = tuple(
                    int(v)
                    for v in colormath.XYZ2RGB(*XYZ, scale=255, round_=True))
            else:
                RGB = (153, 153, 153)
            self.gfx.append(Plot(values, colour=wx.Colour(*RGB), **attrs))
        if self.is_ccss:
            # Add a few points at the extremes to define a bounding box
            self.gfx.append(
                plot.PolyLine(
                    [(self.ccxx_axis_x[0], self.ccxx_axis_y[0]),
                     (self.ccxx_axis_x[1], self.ccxx_axis_y[1] - y_min)],
                    colour=wx.Colour(0, 0, 0, 0)))

        ref = cgats.queryv1("REFERENCE")
        if ref:
            ref = get_canonical_instrument_name(safe_unicode(ref, "UTF-8"))

        if not self.is_ccss:
            observers_ab = {}
            for observer in config.valid_values["observer"]:
                observers_ab[observer] = lang.getstr("observer." + observer)
            x_label = [lang.getstr("matrix")]
            x_label.extend(["%9.6f %9.6f %9.6f" % tuple(row) for row in mtx])
            if ref:
                ref_observer = cgats.queryv1("REFERENCE_OBSERVER")
                if ref_observer:
                    ref += ", " + observers_ab.get(ref_observer, ref_observer)
                x_label.append("")
                x_label.append(ref)
            fit_method = cgats.queryv1("FIT_METHOD")
            if fit_method == "xy":
                fit_method = lang.getstr("ccmx.use_four_color_matrix_method")
            elif fit_method:
                fit_method = lang.getstr("perceptual")
            fit_de00_avg = cgats.queryv1("FIT_AVG_DE00")
            if not isinstance(fit_de00_avg, float):
                fit_de00_avg = None
            fit_de00_max = cgats.queryv1("FIT_MAX_DE00")
            if not isinstance(fit_de00_max, float):
                fit_de00_max = None
            if fit_method:
                x_label.append(fit_method)
            fit_de00 = []
            if fit_de00_avg:
                fit_de00.append(
                    "ΔE*00 %s %.4f" %
                    (lang.getstr("profile.self_check.avg"), fit_de00_avg))
            if fit_de00_max:
                fit_de00.append(
                    "ΔE*00 %s %.4f" %
                    (lang.getstr("profile.self_check.max"), fit_de00_max))
            if fit_de00:
                x_label.append("\n".join(fit_de00))
            x_label = "\n".join(x_label)
        else:
            x_label = ""
            if ref:
                x_label += ref + ", "
            x_label += "%.1fnm, %i-%inm" % ((x_max - x_min) /
                                            (bands - 1.0), x_min, x_max)

        scale = max(getcfg("app.dpi") / config.get_default_dpi(), 1)

        style = wx.DEFAULT_FRAME_STYLE

        wx.Frame.__init__(self, None, -1, title, style=style)
        self.SetIcons(config.get_icon_bundle([256, 48, 32, 16], appname))
        self.SetBackgroundColour(BGCOLOUR)
        self.Sizer = wx.GridSizer(1, 1, 0, 0)
        bg = wx.Panel(self)
        bg.SetBackgroundColour(BGCOLOUR)
        bg.Sizer = wx.BoxSizer(wx.VERTICAL)
        self.canvas = canvas = LUTCanvas(bg)
        if self.is_ccss:
            bg.MinSize = (513 * scale, 557 * scale)
            btnsizer = wx.BoxSizer(wx.HORIZONTAL)
            bg.Sizer.Add(btnsizer,
                         flag=wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT,
                         border=16)
            self.toggle_btn = FlatShadedButton(bg,
                                               -1,
                                               label=lang.getstr("spectral"))
            btnsizer.Add(self.toggle_btn, 1)
            self.Sizer.Add(bg, 1, flag=wx.EXPAND)
            bg.Sizer.Add(canvas, 1, flag=wx.EXPAND)
        else:
            self.Sizer.Add(bg, flag=wx.ALIGN_CENTER)
            canvas_w = 240 * scale
            canvas.MinSize = (canvas_w, canvas_w * (74.6 / 67.4))
            bg.Sizer.Add(canvas, flag=wx.ALIGN_CENTER)
        label = wx.StaticText(bg,
                              -1,
                              x_label.replace("&", "&&"),
                              style=wx.ALIGN_CENTRE_HORIZONTAL)
        label.SetForegroundColour(FGCOLOUR)
        label.SetMaxFontSize(11)
        bg.Sizer.Add(label,
                     flag=wx.ALIGN_CENTER | wx.ALL & ~wx.TOP,
                     border=16 * scale)
        canvas.SetBackgroundColour(BGCOLOUR)
        canvas.SetEnableCenterLines(False)
        canvas.SetEnableDiagonals(False)
        canvas.SetEnableGrid(True)
        canvas.enableTicks = (True, True)
        canvas.tickPen = wx.Pen(GRIDCOLOUR, canvas._pointSize[0])
        canvas.SetEnablePointLabel(False)
        canvas.SetEnableTitle(True)
        canvas.SetForegroundColour(FGCOLOUR)
        canvas.SetGridColour(GRIDCOLOUR)
        canvas.canvas.BackgroundColour = BGCOLOUR
        if self.is_ccss:
            canvas.HandCursor = wx.StockCursor(wx.CURSOR_SIZING)
            canvas.SetCursor(canvas.HandCursor)
        else:
            canvas.canvas.Unbind(wx.EVT_LEFT_DCLICK)
            canvas.SetEnableDrag(False)
            canvas.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
            canvas.SetXSpec('none')
            canvas.SetYSpec('none')

        # CallAfter is needed under GTK as usual
        wx.CallAfter(self.draw_ccxx)

        if self.is_ccss:
            self.Bind(wx.EVT_KEY_DOWN, self.key_handler)
            for child in self.GetAllChildren():
                child.Bind(wx.EVT_KEY_DOWN, self.key_handler)
                child.Bind(wx.EVT_MOUSEWHEEL, self.OnWheel)

            self.toggle_btn.Bind(wx.EVT_BUTTON, self.toggle_draw)

            self.Bind(wx.EVT_SIZE, self.OnSize)
        else:
            bg.Sizer.Add((0, 16))
        self.Sizer.SetSizeHints(self)
        self.Sizer.Layout()
Exemple #29
0
    def __init__(self):
        SimpleTerminal.__init__(
            self,
            None,
            wx.ID_ANY,
            lang.getstr("scripting-client"),
            start_timer=False,
            pos=(getcfg("position.scripting.x"),
                 getcfg("position.scripting.y")),
            size=(getcfg("size.scripting.w"), getcfg("size.scripting.h")),
            consolestyle=wx.TE_CHARWRAP | wx.TE_MULTILINE | wx.TE_PROCESS_ENTER
            | wx.TE_RICH | wx.VSCROLL | wx.NO_BORDER,
            show=False,
            name="scriptingframe")
        self.SetIcons(
            config.get_icon_bundle([256, 48, 32, 16],
                                   appname + "-scripting-client"))
        self.console.SetForegroundColour("#EEEEEE")
        self.console.SetDefaultStyle(wx.TextAttr("#EEEEEE"))

        self.busy = False
        self.commands = []
        self.history = []
        self.historyfilename = os.path.join(
            confighome, config.appbasename + "-scripting-client.history")
        if os.path.isfile(self.historyfilename):
            try:
                with open(self.historyfilename) as historyfile:
                    for line in historyfile:
                        self.history.append(
                            safe_unicode(line, "UTF-8").rstrip("\r\n"))
            except EnvironmentError as exception:
                safe_print("Warning - couldn't read history file:", exception)
        # Always have empty selection at bottom
        self.history.append("")
        self.historypos = len(self.history) - 1

        self.overwrite = False

        # Determine which application we should connect to by default (if any)
        self.conn = None
        scripting_hosts = self.get_scripting_hosts()

        self.sizer.Layout()
        if sys.platform != "darwin":
            # Under Mac OS X, the transparency messes up the window shadow if
            # there is another window's border behind
            self.SetTransparent(240)

        self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Unbind(wx.EVT_CHAR_HOOK)
        self.console.Unbind(wx.EVT_KEY_DOWN, self.console)
        self.console.Bind(wx.EVT_KEY_DOWN, self.key_handler)
        self.console.Bind(wx.EVT_TEXT_COPY, self.copy_text_handler)
        self.console.Bind(wx.EVT_TEXT_PASTE, self.paste_text_handler)
        if sys.platform == "darwin":
            # Under Mac OS X, pasting text via the context menu isn't catched
            # by EVT_TEXT_PASTE. TODO: Implement custom context menu.
            self.console.Bind(wx.EVT_CONTEXT_MENU, lambda event: None)

        if scripting_hosts:
            self.add_text("> getscriptinghosts" + "\n")
            for host in scripting_hosts:
                self.add_text(host + "\n")
            ip_port = scripting_hosts[0].split()[0]
            self.add_text("> connect " + ip_port + "\n")
            self.connect_handler(ip_port)
Exemple #30
0
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 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))
def handle_error(error, parent=None, silent=False, tb=True):
    """ Log an error string and show an error dialog. """
    if isinstance(error, tuple):
        # We got a tuple. Assume (etype, value, tb)
        tbstr = "".join(traceback.format_exception(*error))
        error = error[1]
    else:
        tbstr = traceback.format_exc()
    if (tb and tbstr.strip() != "None" and isinstance(error, Exception)
            and (debug or not isinstance(error, EnvironmentError)
                 or not getattr(error, "filename", None))):
        # Print a traceback if in debug mode, for non environment errors, and
        # for environment errors not related to files
        errstr, tbstr = (safe_unicode(v) for v in (error, tbstr))
        msg = "\n\n".join((errstr, tbstr))
        if msg.startswith(errstr):
            safe_print(box(tbstr))
        else:
            safe_print(box(msg))
    else:
        msg = safe_unicode(error)
        safe_print(box(msg))
    if not silent:
        try:
            from wxaddons import wx
            if wx.VERSION < wx_recversion:
                msg += (
                    "\n\nWARNING: Your version of wxPython (%s) is outdated "
                    "and no longer supported. You should consider updating "
                    "to wxPython %s or newer." %
                    (wx.__version__, ".".join(str(n) for n in wx_recversion)))
            app = wx.GetApp()
            if app is None and parent is None:
                app = wx.App(redirect=False)
                # wxPython 3 bugfix: We also need a toplevel window
                frame = wx.Frame(None)
                parent = False
            else:
                frame = None
            if parent is None:
                parent = wx.GetActiveWindow()
            if parent:
                try:
                    parent.IsShownOnScreen()
                except:
                    # If the parent is still being constructed, we can't use it
                    parent = None
            icon = wx.ICON_INFORMATION
            if not isinstance(error, Info):
                if isinstance(error, Warning):
                    icon = wx.ICON_WARNING
                elif isinstance(error, Exception):
                    icon = wx.ICON_ERROR
            dlg = wx.MessageDialog(
                parent if parent not in (False, None)
                and parent.IsShownOnScreen() else None, msg, app.AppName,
                wx.OK | icon)
            if frame:
                # wxPython 3 bugfix: We need to use CallLater and MainLoop
                wx.CallLater(1, dlg.ShowModal)
                wx.CallLater(1, frame.Close)
                app.MainLoop()
            else:
                dlg.ShowModal()
                dlg.Destroy()
        except Exception as exception:
            safe_print("Warning: handle_error():", safe_unicode(exception))
Exemple #33
0
			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", 
def vrmlfile2x3dfile(vrmlpath=None,
                     x3dpath=None,
                     html=True,
                     embed=False,
                     view=False,
                     force=False,
                     cache=True,
                     worker=None,
                     gui=True):
    """ Convert VRML to HTML. Output is written to <vrmlfilename>.x3d.html
	unless you set x3dpath to desired output path, or False to be prompted
	for an output path. """
    while not vrmlpath or not os.path.isfile(vrmlpath):
        if not gui:
            if not vrmlpath or vrmlpath.startswith("--"):
                safe_print("No filename given.")
            else:
                safe_print("%r is not a file." % vrmlpath)
            return False
        if not wx.GetApp():
            app = BaseApp(0)
        defaultDir, defaultFile = config.get_verified_path("last_vrml_path")
        dlg = wx.FileDialog(None,
                            lang.getstr("file.select"),
                            defaultDir=defaultDir,
                            defaultFile=defaultFile,
                            wildcard=lang.getstr("filetype.vrml") +
                            "|*.vrml;*.vrml.gz;*.wrl.gz;*.wrl;*.wrz",
                            style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
        dlg.Center(wx.BOTH)
        result = dlg.ShowModal()
        vrmlpath = dlg.GetPath()
        dlg.Destroy()
        if result != wx.ID_OK:
            return
        config.setcfg("last_vrml_path", vrmlpath)
        config.writecfg(module="VRML-to-X3D-converter",
                        options=("last_vrml_path", ))
    filename, ext = os.path.splitext(vrmlpath)
    if x3dpath is None:
        x3dpath = filename + ".x3d"
    if x3dpath:
        dirname = os.path.dirname(x3dpath)
    while not x3dpath or not waccess(dirname, os.W_OK):
        if not gui:
            if not x3dpath:
                safe_print("No HTML output filename given.")
            else:
                safe_print("%r is not writable." % dirname)
            return False
        if not wx.GetApp():
            app = BaseApp(0)
        if x3dpath:
            defaultDir, defaultFile = os.path.split(x3dpath)
        else:
            defaultFile = os.path.basename(filename) + ".x3d"
        dlg = wx.FileDialog(None,
                            lang.getstr("error.access_denied.write", dirname),
                            defaultDir=defaultDir,
                            defaultFile=defaultFile,
                            wildcard=lang.getstr("filetype.x3d") + "|*.x3d",
                            style=wx.SAVE | wx.FD_OVERWRITE_PROMPT)
        dlg.Center(wx.BOTH)
        result = dlg.ShowModal()
        dlg.Destroy()
        if result != wx.ID_OK:
            return
        x3dpath = dlg.GetPath()
        dirname = os.path.dirname(x3dpath)
    vrmlpath, x3dpath = [safe_unicode(path) for path in (vrmlpath, x3dpath)]
    if sys.platform == "win32":
        vrmlpath = make_win32_compatible_long_path(vrmlpath)
        x3dpath = make_win32_compatible_long_path(x3dpath)
    if html:
        finalpath = x3dpath + ".html"
        if sys.platform == "win32":
            finalpath = make_win32_compatible_long_path(finalpath)
            x3dpath = finalpath[:-5]
    else:
        finalpath = x3dpath
    if worker:
        worker.clear_cmd_output()
        worker.start(
            lambda result: show_result_dialog(result,
                                              wx.GetApp().GetTopWindow())
            if isinstance(result, Exception
                          ) else result and view and launch_file(finalpath),
            x3dom.vrmlfile2x3dfile,
            wargs=(vrmlpath, x3dpath, html, embed, force, cache, worker),
            progress_title=lang.getstr("vrml_to_x3d_converter"),
            progress_start=1,
            resume=worker.progress_wnd
            and worker.progress_wnd.IsShownOnScreen(),
            fancy=False)
    else:
        result = x3dom.vrmlfile2x3dfile(vrmlpath, x3dpath, html, embed, force,
                                        cache, None)
        if not isinstance(result, Exception) and result:
            if view:
                launch_file(finalpath)
        else:
            return False
    return True
Exemple #35
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()
Exemple #36
0
def get_file_logger(name,
                    level=loglevel,
                    when="midnight",
                    backupCount=5,
                    logdir=None,
                    filename=None,
                    confighome=None):
    """ Return logger object.
	
	A TimedRotatingFileHandler or FileHandler (if when == "never") will be used.
	
	"""
    global _logdir
    if logdir is None:
        logdir = _logdir
    logger = logging.getLogger(name)
    if not filename:
        filename = name
    mode = "a"
    if confighome:
        # Use different logfile name (append number) for each additional
        # instance
        is_main_process = mp.current_process().name == "MainProcess"
        if os.path.basename(confighome).lower() == "dispcalgui":
            lockbasename = filename.replace(appname, "dispcalGUI")
        else:
            lockbasename = filename
        lockfilepath = os.path.join(confighome, lockbasename + ".lock")
        if os.path.isfile(lockfilepath):
            try:
                with open(lockfilepath, "r") as lockfile:
                    instances = len(lockfile.read().splitlines())
            except:
                pass
            else:
                if not is_main_process:
                    # Running as child from multiprocessing under Windows
                    instances -= 1
                if instances:
                    filenames = [filename]
                    filename += ".%i" % instances
                    filenames.append(filename)
                    if filenames[0].endswith("-apply-profiles"):
                        # Running the profile loader always sends a close
                        # request to an already running instance, so there
                        # will be at most two logfiles, and we want to use
                        # the one not currently in use.
                        mtimes = {}
                        for filename in filenames:
                            logfile = os.path.join(logdir, filename + ".log")
                            if not os.path.isfile(logfile):
                                mtimes[0] = filename
                                continue
                            try:
                                logstat = os.stat(logfile)
                            except Exception as exception:
                                safe_print(
                                    "Warning - os.stat('%s') failed: %s" %
                                    tuple(
                                        safe_unicode(s)
                                        for s in (logfile, exception)))
                            else:
                                mtimes[logstat.st_mtime] = filename
                        if mtimes:
                            filename = mtimes[sorted(mtimes.keys())[0]]
        if is_main_process:
            for lockfilepath in safe_glob(
                    os.path.join(confighome,
                                 lockbasename + ".mp-worker-*.lock")):
                try:
                    os.remove(lockfilepath)
                except:
                    pass
        else:
            # Running as child from multiprocessing under Windows
            lockbasename += ".mp-worker-"
            process_num = 1
            while os.path.isfile(
                    os.path.join(confighome,
                                 lockbasename + "%i.lock" % process_num)):
                process_num += 1
            lockfilepath = os.path.join(confighome,
                                        lockbasename + "%i.lock" % process_num)
            try:
                with open(lockfilepath, "w") as lockfile:
                    pass
            except:
                pass
            else:
                atexit.register(os.remove, lockfilepath)
            when = "never"
            filename += ".mp-worker-%i" % process_num
            mode = "w"
    logfile = os.path.join(logdir, filename + ".log")
    for handler in logger.handlers:
        if (isinstance(handler, logging.FileHandler)
                and handler.baseFilename == os.path.abspath(logfile)):
            return logger
    logger.propagate = 0
    logger.setLevel(level)
    if not os.path.exists(logdir):
        try:
            os.makedirs(logdir)
        except Exception as exception:
            safe_print(
                "Warning - log directory '%s' could not be created: %s" %
                tuple(safe_unicode(s) for s in (logdir, exception)))
    elif when != "never" and os.path.exists(logfile):
        try:
            logstat = os.stat(logfile)
        except Exception as exception:
            safe_print("Warning - os.stat('%s') failed: %s" %
                       tuple(safe_unicode(s) for s in (logfile, exception)))
        else:
            # rollover needed?
            t = logstat.st_mtime
            try:
                mtime = localtime(t)
            except ValueError as exception:
                # This can happen on Windows because localtime() is buggy on
                # that platform. See:
                # http://stackoverflow.com/questions/4434629/zipfile-module-in-python-runtime-problems
                # http://bugs.python.org/issue1760357
                # To overcome this problem, we ignore the real modification
                # date and force a rollover
                t = time() - 60 * 60 * 24
                mtime = localtime(t)
            # Deal with DST
            now = localtime()
            dstNow = now[-1]
            dstThen = mtime[-1]
            if dstNow != dstThen:
                if dstNow:
                    addend = 3600
                else:
                    addend = -3600
                mtime = localtime(t + addend)
            if now[:3] > mtime[:3]:
                # do rollover
                logbackup = logfile + strftime(".%Y-%m-%d", mtime)
                if os.path.exists(logbackup):
                    try:
                        os.remove(logbackup)
                    except Exception as exception:
                        safe_print("Warning - logfile backup '%s' could not "
                                   "be removed during rollover: %s" % tuple(
                                       safe_unicode(s)
                                       for s in (logbackup, exception)))
                try:
                    os.rename(logfile, logbackup)
                except Exception as exception:
                    safe_print(
                        "Warning - logfile '%s' could not be renamed "
                        "to '%s' during rollover: %s" % tuple(
                            safe_unicode(s)
                            for s in (logfile, os.path.basename(logbackup),
                                      exception)))
                # Adapted from Python 2.6's
                # logging.handlers.TimedRotatingFileHandler.getFilesToDelete
                extMatch = re.compile(r"^\d{4}-\d{2}-\d{2}$")
                baseName = os.path.basename(logfile)
                try:
                    fileNames = os.listdir(logdir)
                except Exception as exception:
                    safe_print(
                        "Warning - log directory '%s' listing failed "
                        "during rollover: %s" %
                        tuple(safe_unicode(s) for s in (logdir, exception)))
                else:
                    result = []
                    prefix = baseName + "."
                    plen = len(prefix)
                    for fileName in fileNames:
                        if fileName[:plen] == prefix:
                            suffix = fileName[plen:]
                            if extMatch.match(suffix):
                                result.append(os.path.join(logdir, fileName))
                    result.sort()
                    if len(result) > backupCount:
                        for logbackup in result[:len(result) - backupCount]:
                            try:
                                os.remove(logbackup)
                            except Exception as exception:
                                safe_print(
                                    "Warning - logfile backup '%s' "
                                    "could not be removed during "
                                    "rollover: %s" % tuple(
                                        safe_unicode(s)
                                        for s in (logbackup, exception)))
    if os.path.exists(logdir):
        try:
            if when != "never":
                filehandler = logging.handlers.TimedRotatingFileHandler(
                    logfile, when=when, backupCount=backupCount)
            else:
                filehandler = logging.FileHandler(logfile, mode)
            fileformatter = logging.Formatter("%(asctime)s %(message)s")
            filehandler.setFormatter(fileformatter)
            logger.addHandler(filehandler)
        except Exception as exception:
            safe_print("Warning - logging to file '%s' not possible: %s" %
                       tuple(safe_unicode(s) for s in (logfile, exception)))
    return logger