def ok(self, event=None): if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged or self.modelClassesChanged or self.disclosureSystemTypesChanged or self.hostSystemFeaturesChanged: # may require reloading UI affectedItems = "" if self.uiClassMethodsChanged: affectedItems += _("menus of the user interface") if self.modelClassesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("model objects of the processor") if self.disclosureSystemTypesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("disclosure system types") if self.hostSystemFeaturesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("host system features") if messagebox.askyesno(_("User interface plug-in change"), _("A change in plug-in class methods may have affected {0}. " "Please restart Arelle to due to these changes. \n\n" "Should Arelle restart itself now " "(if there are any unsaved changes they would be lost!)?" ).format(affectedItems), parent=self): self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True])) self.close()
def get_test_data(args): """ Produces a list of Pytest Params that can be fed into a parameterized pytest function :param args: The args to be parsed by arelle in order to correctly produce the desired result set :type args: list of strings :return: A list of PyTest Params that can be used to run a parameterized pytest function :rtype: list of ::class:: `~pytest.param` """ cntlr = parseAndRun(args) results = [] model_document = cntlr.modelManager.modelXbrl.modelDocument if model_document is not None: if model_document.type == ModelDocument.Type.TESTCASESINDEX: for tc in sorted(model_document.referencesDocument.keys(), key=lambda doc: doc.uri): uri_dir_parts = os.path.dirname(tc.uri).split('/') test_case_dir = '/'.join(uri_dir_parts[-2:]) if hasattr(tc, "testcaseVariations"): for mv in tc.testcaseVariations: param = pytest.param( { 'status': mv.status, 'expected': mv.expected, 'actual': mv.actual }, id='{}/{}'.format(test_case_dir, str(mv.id or mv.name))) results.append(param) cntlr.modelManager.close() PackageManager.close() PluginManager.close() return results
def ok(self, event=None): if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged or self.modelClassesChanged or self.disclosureSystemTypesChanged: # may require reloading UI affectedItems = "" if self.uiClassMethodsChanged: affectedItems += _("menus of the user interface") if self.modelClassesChanged: if self.uiClassMethodsChanged: affectedItems += _(" and ") affectedItems += _("model objects of the processor") if (self.uiClassMethodsChanged or self.modelClassesChanged): affectedItems += _(" and ") if self.disclosureSystemTypesChanged: if (self.uiClassMethodsChanged or self.modelClassesChanged): affectedItems += _(" and ") affectedItems += _("disclosure system types") if messagebox.askyesno(_("User interface plug-in change"), _("A change in plug-in class methods may have affected {0}. " "Please restart Arelle to due to these changes. \n\n" "Should Arelle restart itself now " "(if there are any unsaved changes they would be lost!)?" ).format(affectedItems), parent=self): self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True])) self.close()
def close(self, saveConfig=False): """.. method:: close(saveConfig=False) Close controller and its logger, optionally saaving the user preferences configuration :param saveConfig: save the user preferences configuration""" PluginManager.save(self) if saveConfig: self.saveConfig() if self.logger is not None: self.logHandler.close()
def ok(self, event=None): if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged: # may require reloading UI messagebox.showwarning(_("User interface plug-in change"), _("A change in plug-in class methods may have affected the menus " "of the user interface. It may be necessary to restart Arelle to " "access the menu entries or the changes to their plug-in methods."), parent=self) self.close()
def ok(self, event=None): # check for orphaned classes (for which there is no longer a corresponding module) _moduleNames = self.pluginConfig.get("modules", {}).keys() _orphanedClassNames = set() for className, moduleList in self.pluginConfig.get("classes", {}).items(): for _moduleName in moduleList.copy(): if _moduleName not in _moduleNames: # it's orphaned moduleList.remove(_moduleName) self.pluginConfigChanged = True if not moduleList: # now orphaned _orphanedClassNames.add(className) self.pluginConfigChanged = True for _orphanedClassName in _orphanedClassNames: del self.pluginConfig["classes"][_orphanedClassName] if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged or self.modelClassesChanged or self.customTransformsChanged or self.disclosureSystemTypesChanged or self.hostSystemFeaturesChanged: # may require reloading UI affectedItems = "" if self.uiClassMethodsChanged: affectedItems += _("menus of the user interface") if self.modelClassesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("model objects of the processor") if self.customTransformsChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("custom transforms") if self.disclosureSystemTypesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("disclosure system types") if self.hostSystemFeaturesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("host system features") if messagebox.askyesno( _("User interface plug-in change"), _("A change in plug-in class methods may have affected {0}. " "Please restart Arelle to due to these changes. \n\n" "Should Arelle restart itself now " "(if there are any unsaved changes they would be lost!)?" ).format(affectedItems), parent=self): self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True])) self.close()
def close(self, saveConfig=False): """Closes the controller and its logger, optionally saving the user preferences configuration :param saveConfig: save the user preferences configuration :type saveConfig: bool """ PluginManager.save(self) if saveConfig: self.saveConfig() if self.logger is not None: try: self.logHandler.close() except Exception: # fails on some earlier pythons (3.1) pass
def ok(self, event=None): if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged: # may require reloading UI if messagebox.askyesno(_("User interface plug-in change"), _("A change in plug-in class methods may have affected the menus " "of the user interface. It may be necessary to restart Arelle to " "access the menu entries or the changes to their plug-in methods. \n\n" "Should Arelle restart with changed user interface language, " "(if there are any unsaved changes they would be lost!)?"), parent=self): self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True])) self.close()
def test_plugin_manager_reset(): """ Test that modulePluginInfos and pluginMethodsForClasses are cleared when close is called, pluginConfig remains unchanged """ cntlr = Mock(pluginDir='some_dir') PluginManager.init(cntlr, loadPluginConfig=False) assert len(PluginManager.modulePluginInfos) == 0 assert len(PluginManager.pluginMethodsForClasses) == 0 PluginManager.modulePluginInfos['module'] = 'plugin_info' PluginManager.pluginMethodsForClasses['class'] = 'plugin_method' PluginManager.reset() assert len(PluginManager.pluginConfig) == 2 assert len(PluginManager.modulePluginInfos) == 0 assert len(PluginManager.pluginMethodsForClasses) == 0 assert PluginManager._cntlr == cntlr
def ok(self, event=None): # check for orphaned classes (for which there is no longer a corresponding module) _moduleNames = self.pluginConfig.get("modules", {}).keys() _orphanedClassNames = set() for className, moduleList in self.pluginConfig.get("classes", {}).items(): for _moduleName in moduleList.copy(): if _moduleName not in _moduleNames: # it's orphaned moduleList.remove(_moduleName) self.pluginConfigChanged = True if not moduleList: # now orphaned _orphanedClassNames.add(className) self.pluginConfigChanged = True for _orphanedClassName in _orphanedClassNames: del self.pluginConfig["classes"][_orphanedClassName] if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged or self.modelClassesChanged or self.customTransformsChanged or self.disclosureSystemTypesChanged or self.hostSystemFeaturesChanged: # may require reloading UI affectedItems = "" if self.uiClassMethodsChanged: affectedItems += _("menus of the user interface") if self.modelClassesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("model objects of the processor") if self.customTransformsChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("custom transforms") if self.disclosureSystemTypesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("disclosure system types") if self.hostSystemFeaturesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("host system features") if messagebox.askyesno(_("User interface plug-in change"), _("A change in plug-in class methods may have affected {0}. " "Please restart Arelle to due to these changes. \n\n" "Should Arelle restart itself now " "(if there are any unsaved changes they would be lost!)?" ).format(affectedItems), parent=self): self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True])) self.close()
def selectChoices(dir, indent=""): dirHasEntries = False for f in sorted(os.listdir(dir), key=sortOrder): if f not in (".", "..", "__pycache__", "__init__.py"): fPath = os.path.join(dir, f) fPkgInit = os.path.join(fPath, "__init__.py") dirInsertPoint = len(choices) moduleInfo = None if ((os.path.isdir(fPath) and os.path.exists(fPkgInit)) or ((os.path.isfile(fPath) and f.endswith(".py")))): moduleInfo = PluginManager.moduleModuleInfo(fPath) if moduleInfo: choices.append(( indent + f, "name: {}\ndescription: {}\nversion: {}\nlicense: {}" .format(moduleInfo["name"], moduleInfo.get("description"), moduleInfo.get("version"), moduleInfo.get("license")), fPath, moduleInfo["name"], moduleInfo.get("version"), moduleInfo.get("description"), moduleInfo.get("license"))) dirHasEntries = True if os.path.isdir(fPath) and f not in ("DQC_US_Rules", ): if selectChoices(fPath, indent=indent + " ") and not moduleInfo: choices.insert(dirInsertPoint, (indent + f, None, None, None, None, None, None)) return dirHasEntries
def selectLocally(self): choices = [] # list of tuple of (file name, description) def sortOrder(key): return {"EdgarRenderer": "1", "validate": "2", "xbrlDB": "3"}.get(key, "4") + key.lower() def selectChoices(dir, indent=""): dirHasEntries = False for f in sorted(os.listdir(dir), key=sortOrder): if f not in (".", "..", "__pycache__", "__init__.py"): fPath = os.path.join(dir, f) fPkgInit = os.path.join(fPath, "__init__.py") dirInsertPoint = len(choices) moduleInfo = None if ((os.path.isdir(fPath) and os.path.exists(fPkgInit)) or ((os.path.isfile(fPath) and f.endswith(".py")))): moduleInfo = PluginManager.moduleModuleInfo(fPath) if moduleInfo: choices.append((indent + f, "name: {}\ndescription: {}\n version {}".format( moduleInfo["name"], moduleInfo["description"], moduleInfo.get("version")), fPath, moduleInfo["name"], moduleInfo.get("version"), moduleInfo["description"])) dirHasEntries = True if os.path.isdir(fPath) and f not in ("DQC_US_Rules",): if selectChoices(fPath, indent=indent + " ") and not moduleInfo: choices.insert(dirInsertPoint, (indent + f,None,None,None,None,None)) return dirHasEntries selectChoices(self.cntlr.pluginDir) selectedPath = DialogOpenArchive.selectPlugin(self, choices) if selectedPath: moduleInfo = PluginManager.moduleModuleInfo(selectedPath) self.loadFoundModuleInfo(moduleInfo, selectedPath)
def test_plugin_manager_init_first_pass(): """ Test that pluginConfig is correctly setup during init on fresh pass """ cntlr = Mock(pluginDir='some_dir') PluginManager.init(cntlr, loadPluginConfig=False) assert len(PluginManager.pluginConfig) == 2 assert 'modules' in PluginManager.pluginConfig assert isinstance(PluginManager.pluginConfig.get('modules'), dict) assert len(PluginManager.pluginConfig.get('modules')) == 0 assert 'classes' in PluginManager.pluginConfig assert isinstance(PluginManager.pluginConfig.get('classes'), dict) assert len(PluginManager.pluginConfig.get('classes')) == 0 assert len(PluginManager.modulePluginInfos) == 0 assert len(PluginManager.pluginMethodsForClasses) == 0 assert PluginManager._cntlr == cntlr
def moduleReload(self): if self.selectedModule in self.pluginConfig["modules"]: url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL") if url: moduleInfo = PluginManager.moduleModuleInfo(url, reload=True) if moduleInfo: self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo.get("name")), clearAfter=5000)
def backgroundCheckForUpdates(cntlr): cntlr.showStatus(_("Checking for updates to plug-ins")) # clear web loading status modulesWithNewerFileDates = PluginManager.modulesWithNewerFileDates() if modulesWithNewerFileDates: cntlr.showStatus(_("Updates are available for these plug-ins: {0}") .format(', '.join(modulesWithNewerFileDates)), clearAfter=5000) else: cntlr.showStatus(_("No updates found for plug-ins."), clearAfter=5000) time.sleep(0.1) # Mac locks up without this, may be needed for empty ui queue? cntlr.uiThreadQueue.put((DialogPluginManager, [cntlr, modulesWithNewerFileDates]))
def findLocally(self): filename = self.cntlr.uiFileDialog("open", owner=self, title=_("Choose plug-in module file"), initialdir=self.cntlr.config.setdefault("pluginOpenDir","."), filetypes=[(_("Python files"), "*.py")], defaultextension=".py") if filename: self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename) moduleInfo = PluginManager.moduleModuleInfo(filename) self.loadFoundModuleInfo(moduleInfo, filename)
def moduleReload(self): if self.selectedModule in self.pluginConfig["modules"]: url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL") if url: moduleInfo = PluginManager.moduleModuleInfo(url, reload=True) if moduleInfo: self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo.get("name")), clearAfter=5000) else: messagebox.showwarning(_("Module error"), _("File or module cannot be reloaded: \n\n{0}") .format(url), parent=self)
def findLocally(self): initialdir = self.cntlr.pluginDir # default plugin directory if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory initialdir = self.cntlr.config.setdefault("pluginOpenDir", initialdir) filename = self.cntlr.uiFileDialog("open", parent=self, title=_("Choose plug-in module file"), initialdir=initialdir, filetypes=[(_("Python files"), "*.py")], defaultextension=".py") if filename: # check if a package is selected (any file in a directory containing an __init__.py if (os.path.isdir(os.path.dirname(filename)) and os.path.isfile(os.path.join(os.path.dirname(filename), "__init__.py"))): filename = os.path.dirname(filename) # refer to the package instead self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename) moduleInfo = PluginManager.moduleModuleInfo(filename) self.loadFoundModuleInfo(moduleInfo, filename)
def findLocally(self): initialdir = self.cntlr.pluginDir # default plugin directory if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory initialdir = self.cntlr.config.setdefault("pluginOpenDir", initialdir) filename = self.cntlr.uiFileDialog("open", parent=self, title=_("Choose plug-in module file"), initialdir=initialdir, filetypes=[(_("Python files"), "*.py")], defaultextension=".py") if filename: # check if a package is selected (any file in a directory containing an __init__.py #if (os.path.basename(filename) == "__init__.py" and os.path.isdir(os.path.dirname(filename)) and # os.path.isfile(filename)): # filename = os.path.dirname(filename) # refer to the package instead self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename) moduleInfo = PluginManager.moduleModuleInfo(filename) self.loadFoundModuleInfo(moduleInfo, filename)
def selectChoices(dir, indent=""): dirHasEntries = False for f in sorted(os.listdir(dir), key=sortOrder): if f not in (".", "..", "__pycache__", "__init__.py"): fPath = os.path.join(dir, f) fPkgInit = os.path.join(fPath, "__init__.py") dirInsertPoint = len(choices) moduleInfo = None if ((os.path.isdir(fPath) and os.path.exists(fPkgInit)) or ((os.path.isfile(fPath) and f.endswith(".py")))): moduleInfo = PluginManager.moduleModuleInfo(fPath) if moduleInfo: choices.append((indent + f, "name: {}\ndescription: {}\n version {}".format( moduleInfo["name"], moduleInfo["description"], moduleInfo.get("version")), fPath, moduleInfo["name"], moduleInfo.get("version"), moduleInfo["description"])) dirHasEntries = True if os.path.isdir(fPath) and f not in ("DQC_US_Rules",): if selectChoices(fPath, indent=indent + " ") and not moduleInfo: choices.insert(dirInsertPoint, (indent + f,None,None,None,None,None)) return dirHasEntries
help="URL to ixbrlviewer.js", default="ixbrlviewer.js") parser.add_argument("--out", "-o", help="File or directory to write output to", default="viewer.html") parser.add_argument('files', metavar='FILES', nargs='+', help='Files to process') args = parser.parse_args() cntlr = CntlrCreateViewer() cntlr.startLogging(logFileName='logToPrint', logFormat="[%(messageCode)s] %(message)s - %(file)s", logLevel="DEBUG", logRefObjectProperties=True, logToBuffer=True) cntlr.modelManager.validateInferDecimals = True cntlr.modelManager.validateCalcLB = True cntlr.modelManager.formulaOptions = FormulaOptions() PluginManager.addPluginModule("transforms/SEC") PluginManager.addPluginModule("inlineXbrlDocumentSet") cntlr.modelManager.loadCustomTransforms() if args.package_dir: cntlr.loadPackagesFromDir(args.package_dir) for f in args.files: cntlr.createViewer(f, outPath=args.out, scriptUrl=args.viewer_url)
parser = argparse.ArgumentParser(description="Create iXBRL Viewer instances") parser.add_argument("--package-dir", "-p", help="Path to directory containing taxonomy packages") parser.add_argument("--viewer-url", "-u", help="URL to ixbrlviewer.js", default="ixbrlviewer.js") parser.add_argument("--out", "-o", help="File or directory to write output to", default="viewer.html") parser.add_argument('files', metavar='FILES', nargs='+', help='Files to process') args = parser.parse_args() cntlr = CntlrCreateViewer() cntlr.startLogging(logFileName='logToPrint', logFormat="[%(messageCode)s] %(message)s - %(file)s", logLevel="DEBUG", logRefObjectProperties=True, logToBuffer=False) PluginManager.addPluginModule("inlineXbrlDocumentSet") if args.package_dir: cntlr.loadPackagesFromDir(args.package_dir) for f in args.files: cntlr.createViewer(f, outPath=args.out, scriptUrl=args.viewer_url)
def findOnWeb(self): url = DialogURL.askURL(self) if url: # url is the in-cache or local file moduleInfo = PluginManager.moduleModuleInfo(url) self.cntlr.showStatus("") # clear web loading status self.loadFoundModuleInfo(moduleInfo, url)
def __init__(self, hasGui=False, logFileName=None, logFileMode=None, logFileEncoding=None, logFormat=None): self.hasWin32gui = False self.hasGui = hasGui self.hasFileSystem = True # no file system on Google App Engine servers self.isGAE = False self.systemWordSize = int(round(math.log(sys.maxsize, 2)) + 1) # e.g., 32 or 64 self.moduleDir = os.path.dirname(__file__) # for python 3.2 remove __pycache__ if self.moduleDir.endswith("__pycache__"): self.moduleDir = os.path.dirname(self.moduleDir) if self.moduleDir.endswith("python32.zip/arelle"): ''' distZipFile = os.path.dirname(self.moduleDir) d = os.path.join(self.userAppDir, "arelle") self.configDir = os.path.join(d, "config") self.imagesDir = os.path.join(d, "images") import zipfile distZip = zipfile.ZipFile(distZipFile, mode="r") distNames = distZip.namelist() distZip.extractall(path=self.userAppDir, members=[f for f in distNames if "/config/" in f or "/images/" in f] ) distZip.close() ''' resources = os.path.dirname(os.path.dirname(os.path.dirname(self.moduleDir))) self.configDir = os.path.join(resources, "config") self.imagesDir = os.path.join(resources, "images") self.localeDir = os.path.join(resources, "locale") self.pluginDir = os.path.join(resources, "plugin") elif self.moduleDir.endswith("library.zip\\arelle") or self.moduleDir.endswith("library.zip/arelle"): # cx_Freexe resources = os.path.dirname(os.path.dirname(self.moduleDir)) self.configDir = os.path.join(resources, "config") self.imagesDir = os.path.join(resources, "images") self.localeDir = os.path.join(resources, "locale") self.pluginDir = os.path.join(resources, "plugin") else: self.configDir = os.path.join(self.moduleDir, "config") self.imagesDir = os.path.join(self.moduleDir, "images") self.localeDir = os.path.join(self.moduleDir, "locale") self.pluginDir = os.path.join(self.moduleDir, "plugin") serverSoftware = os.getenv("SERVER_SOFTWARE", "") if serverSoftware.startswith("Google App Engine/") or serverSoftware.startswith("Development/"): self.hasFileSystem = False # no file system, userAppDir does not exist self.isGAE = True configHomeDir = None # look for path configDir/CONFIG_HOME in argv and environment parameters for i, arg in enumerate(sys.argv): # check if config specified in a argv if arg.startswith("--xdgConfigHome="): configHomeDir = arg[16:] break elif arg == "--xdgConfigHome" and i + 1 < len(sys.argv): configHomeDir = sys.argv[i + 1] break if not configHomeDir: # not in argv, may be an environment parameter configHomeDir = os.getenv('XDG_CONFIG_HOME') if not configHomeDir: # look for path configDir/CONFIG_HOME configHomeDirFile = os.path.join(self.configDir, "XDG_CONFIG_HOME") if os.path.exists(configHomeDirFile): try: with io.open(configHomeDirFile, 'rt', encoding='utf-8') as f: configHomeDir = f.read().strip() if configHomeDir and not os.path.isabs(configHomeDir): configHomeDir = os.path.abspath(configHomeDir) # make into a full path if relative except EnvironmentError: configHomeDir = None if self.hasFileSystem and configHomeDir and os.path.exists(configHomeDir): # check if a cache exists in this directory (e.g. from XPE or other tool) impliedAppDir = os.path.join(configHomeDir, "arelle") if os.path.exists(impliedAppDir): self.userAppDir = impliedAppDir elif os.path.exists(os.path.join(configHomeDir, "cache")): self.userAppDir = configHomeDir # use the XDG_CONFIG_HOME because cache is already a subdirectory else: self.userAppDir = impliedAppDir if sys.platform == "darwin": self.isMac = True self.isMSW = False if self.hasFileSystem and not configHomeDir: self.userAppDir = os.path.expanduser("~") + "/Library/Application Support/Arelle" # note that cache is in ~/Library/Caches/Arelle self.contextMenuClick = "<Button-2>" self.hasClipboard = hasGui # clipboard always only if Gui (not command line mode) self.updateURL = "http://arelle.org/downloads/8" elif sys.platform.startswith("win"): self.isMac = False self.isMSW = True if self.hasFileSystem and not configHomeDir: tempDir = tempfile.gettempdir() if tempDir.endswith('local\\temp'): impliedAppDir = tempDir[:-10] + 'local' else: impliedAppDir = tempDir self.userAppDir = os.path.join( impliedAppDir, "Arelle") if hasGui: try: import win32clipboard self.hasClipboard = True except ImportError: self.hasClipboard = False try: import win32gui self.hasWin32gui = True # active state for open file dialogs except ImportError: pass else: self.hasClipboard = False self.contextMenuClick = "<Button-3>" if "64 bit" in sys.version: self.updateURL = "http://arelle.org/downloads/9" else: # 32 bit self.updateURL = "http://arelle.org/downloads/10" else: # Unix/Linux self.isMac = False self.isMSW = False if self.hasFileSystem and not configHomeDir: self.userAppDir = os.path.join( os.path.expanduser("~/.config"), "arelle") if hasGui: try: import gtk self.hasClipboard = True except ImportError: self.hasClipboard = False else: self.hasClipboard = False self.contextMenuClick = "<Button-3>" try: from arelle import webserver self.hasWebServer = True except ImportError: self.hasWebServer = False # assert that app dir must exist self.config = None if self.hasFileSystem: if not os.path.exists(self.userAppDir): os.makedirs(self.userAppDir) # load config if it exists self.configJsonFile = self.userAppDir + os.sep + "config.json" if os.path.exists(self.configJsonFile): try: with io.open(self.configJsonFile, 'rt', encoding='utf-8') as f: self.config = json.load(f) except Exception as ex: self.config = None # restart with a new config if not self.config: self.config = { 'fileHistory': [], 'windowGeometry': "{0}x{1}+{2}+{3}".format(800, 500, 200, 100), } # start language translation for domain self.setUiLanguage(self.config.get("userInterfaceLangOverride",None), fallbackToDefault=True) from arelle.WebCache import WebCache self.webCache = WebCache(self, self.config.get("proxySettings")) self.modelManager = ModelManager.initialize(self) # start plug in server (requres web cache initialized, but not logger) PluginManager.init(self) # start taxonomy package server (requres web cache initialized, but not logger) PackageManager.init(self) self.startLogging(logFileName, logFileMode, logFileEncoding, logFormat) # Cntlr.Init after logging started for pluginMethod in PluginManager.pluginClassMethods("Cntlr.Init"): pluginMethod(self)
def run(self, options, sourceZipStream=None): """Process command line arguments or web service request, such as to load and validate an XBRL document, or start web server. When a web server has been requested, this method may be called multiple times, once for each web service (REST) request that requires processing. Otherwise (when called for a command line request) this method is called only once for the command line arguments request. :param options: OptionParser options from parse_args of main argv arguments (when called from command line) or corresponding arguments from web service (REST) request. :type options: optparse.Values """ if options.showOptions: # debug options for optName, optValue in sorted(options.__dict__.items(), key=lambda optItem: optItem[0]): self.addToLog("Option {0}={1}".format(optName, optValue), messageCode="info") self.addToLog("sys.argv {0}".format(sys.argv), messageCode="info") if options.uiLang: # set current UI Lang (but not config setting) self.setUiLanguage(options.uiLang) if options.proxy: if options.proxy != "show": proxySettings = proxyTuple(options.proxy) self.webCache.resetProxies(proxySettings) self.config["proxySettings"] = proxySettings self.saveConfig() self.addToLog(_("Proxy configuration has been set."), messageCode="info") useOsProxy, urlAddr, urlPort, user, password = self.config.get("proxySettings", proxyTuple("none")) if useOsProxy: self.addToLog(_("Proxy configured to use {0}.").format( _('Microsoft Windows Internet Settings') if sys.platform.startswith("win") else (_('Mac OS X System Configuration') if sys.platform in ("darwin", "macos") else _('environment variables'))), messageCode="info") elif urlAddr: self.addToLog(_("Proxy setting: http://{0}{1}{2}{3}{4}").format( user if user else "", ":****" if password else "", "@" if (user or password) else "", urlAddr, ":{0}".format(urlPort) if urlPort else ""), messageCode="info") else: self.addToLog(_("Proxy is disabled."), messageCode="info") if options.plugins: from arelle import PluginManager resetPlugins = False savePluginChanges = True showPluginModules = False for pluginCmd in options.plugins.split('|'): cmd = pluginCmd.strip() if cmd == "show": showPluginModules = True elif cmd == "temp": savePluginChanges = False elif cmd.startswith("+"): moduleInfo = PluginManager.addPluginModule(cmd[1:]) if moduleInfo: self.addToLog(_("Addition of plug-in {0} successful.").format(moduleInfo.get("name")), messageCode="info", file=moduleInfo.get("moduleURL")) resetPlugins = True else: self.addToLog(_("Unable to load plug-in."), messageCode="info", file=cmd[1:]) elif cmd.startswith("~"): if PluginManager.reloadPluginModule(cmd[1:]): self.addToLog(_("Reload of plug-in successful."), messageCode="info", file=cmd[1:]) resetPlugins = True else: self.addToLog(_("Unable to reload plug-in."), messageCode="info", file=cmd[1:]) elif cmd.startswith("-"): if PluginManager.removePluginModule(cmd[1:]): self.addToLog(_("Deletion of plug-in successful."), messageCode="info", file=cmd[1:]) resetPlugins = True else: self.addToLog(_("Unable to delete plug-in."), messageCode="info", file=cmd[1:]) else: # assume it is a module or package savePluginChanges = False moduleInfo = PluginManager.addPluginModule(cmd) if moduleInfo: self.addToLog(_("Activation of plug-in {0} successful.").format(moduleInfo.get("name")), messageCode="info", file=moduleInfo.get("moduleURL")) resetPlugins = True else: self.addToLog(_("Unable to load {0} as a plug-in or {0} is not recognized as a command. ").format(cmd), messageCode="info", file=cmd) if resetPlugins: PluginManager.reset() if savePluginChanges: PluginManager.save(self) if showPluginModules: self.addToLog(_("Plug-in modules:"), messageCode="info") for i, moduleItem in enumerate(sorted(PluginManager.pluginConfig.get("modules", {}).items())): moduleInfo = moduleItem[1] self.addToLog(_("Plug-in: {0}; author: {1}; version: {2}; status: {3}; date: {4}; description: {5}; license {6}.").format( moduleItem[0], moduleInfo.get("author"), moduleInfo.get("version"), moduleInfo.get("status"), moduleInfo.get("fileDate"), moduleInfo.get("description"), moduleInfo.get("license")), messageCode="info", file=moduleInfo.get("moduleURL")) # run utility command line options that don't depend on entrypoint Files hasUtilityPlugin = False for pluginXbrlMethod in pluginClassMethods("CntlrCmdLine.Utility.Run"): hasUtilityPlugin = True pluginXbrlMethod(self, options) # if no entrypointFile is applicable, quit now if options.proxy or options.plugins or hasUtilityPlugin: if not options.entrypointFile: return True # success self.username = options.username self.password = options.password self.entrypointFile = options.entrypointFile if self.entrypointFile: filesource = FileSource.openFileSource(self.entrypointFile, self, sourceZipStream) else: filesource = None if options.validateEFM: if options.disclosureSystemName: self.addToLog(_("both --efm and --disclosureSystem validation are requested, proceeding with --efm only"), messageCode="info", file=self.entrypointFile) self.modelManager.validateDisclosureSystem = True self.modelManager.disclosureSystem.select("efm") elif options.disclosureSystemName: self.modelManager.validateDisclosureSystem = True self.modelManager.disclosureSystem.select(options.disclosureSystemName) elif options.validateHMRC: self.modelManager.validateDisclosureSystem = True self.modelManager.disclosureSystem.select("hmrc") else: self.modelManager.disclosureSystem.select(None) # just load ordinary mappings self.modelManager.validateDisclosureSystem = False if options.utrUrl: # override disclosureSystem utrUrl self.modelManager.disclosureSystem.utrUrl = options.utrUrl # can be set now because the utr is first loaded at validation time # disclosure system sets logging filters, override disclosure filters, if specified by command line if options.logLevelFilter: self.setLogLevelFilter(options.logLevelFilter) if options.logCodeFilter: self.setLogCodeFilter(options.logCodeFilter) if options.calcDecimals: if options.calcPrecision: self.addToLog(_("both --calcDecimals and --calcPrecision validation are requested, proceeding with --calcDecimals only"), messageCode="info", file=self.entrypointFile) self.modelManager.validateInferDecimals = True self.modelManager.validateCalcLB = True elif options.calcPrecision: self.modelManager.validateInferDecimals = False self.modelManager.validateCalcLB = True if options.utrValidate: self.modelManager.validateUtr = True if options.infosetValidate: self.modelManager.validateInfoset = True if options.abortOnMajorError: self.modelManager.abortOnMajorError = True if options.collectProfileStats: self.modelManager.collectProfileStats = True if options.internetConnectivity == "offline": self.webCache.workOffline = True elif options.internetConnectivity == "online": self.webCache.workOffline = False if options.internetTimeout is not None: self.webCache.timeout = (options.internetTimeout or None) # use None if zero specified to disable timeout fo = FormulaOptions() if options.parameters: parameterSeparator = (options.parameterSeparator or ',') fo.parameterValues = dict(((qname(key, noPrefixIsNoNamespace=True),(None,value)) for param in options.parameters.split(parameterSeparator) for key,sep,value in (param.partition('='),) ) ) if options.formulaParamExprResult: fo.traceParameterExpressionResult = True if options.formulaParamInputValue: fo.traceParameterInputValue = True if options.formulaCallExprSource: fo.traceCallExpressionSource = True if options.formulaCallExprCode: fo.traceCallExpressionCode = True if options.formulaCallExprEval: fo.traceCallExpressionEvaluation = True if options.formulaCallExprResult: fo.traceCallExpressionResult = True if options.formulaVarSetExprEval: fo.traceVariableSetExpressionEvaluation = True if options.formulaVarSetExprResult: fo.traceVariableSetExpressionResult = True if options.formulaAsserResultCounts: fo.traceAssertionResultCounts = True if options.formulaFormulaRules: fo.traceFormulaRules = True if options.formulaVarsOrder: fo.traceVariablesOrder = True if options.formulaVarExpressionSource: fo.traceVariableExpressionSource = True if options.formulaVarExpressionCode: fo.traceVariableExpressionCode = True if options.formulaVarExpressionEvaluation: fo.traceVariableExpressionEvaluation = True if options.formulaVarExpressionResult: fo.traceVariableExpressionResult = True if options.timeVariableSetEvaluation: fo.timeVariableSetEvaluation = True if options.formulaVarFilterWinnowing: fo.traceVariableFilterWinnowing = True if options.formulaVarFiltersResult: fo.traceVariableFiltersResult = True if options.formulaVarFiltersResult: fo.traceVariableFiltersResult = True self.modelManager.formulaOptions = fo timeNow = XmlUtil.dateunionValue(datetime.datetime.now()) firstStartedAt = startedAt = time.time() modelDiffReport = None success = True modelXbrl = None try: if filesource: modelXbrl = self.modelManager.load(filesource, _("views loading")) except ModelDocument.LoadingException: pass except Exception as err: self.addToLog(_("[Exception] Failed to complete request: \n{0} \n{1}").format( err, traceback.format_tb(sys.exc_info()[2]))) success = False # loading errors, don't attempt to utilize loaded DTS if modelXbrl and modelXbrl.modelDocument: loadTime = time.time() - startedAt modelXbrl.profileStat(_("load"), loadTime) self.addToLog(format_string(self.modelManager.locale, _("loaded in %.2f secs at %s"), (loadTime, timeNow)), messageCode="info", file=self.entrypointFile) if options.importFiles: for importFile in options.importFiles.split("|"): fileName = importFile.strip() if sourceZipStream is not None and not (fileName.startswith('http://') or os.path.isabs(fileName)): fileName = os.path.dirname(modelXbrl.uri) + os.sep + fileName # make relative to sourceZipStream ModelDocument.load(modelXbrl, fileName) loadTime = time.time() - startedAt self.addToLog(format_string(self.modelManager.locale, _("import in %.2f secs at %s"), (loadTime, timeNow)), messageCode="info", file=importFile) modelXbrl.profileStat(_("import"), loadTime) if modelXbrl.errors: success = False # loading errors, don't attempt to utilize loaded DTS if modelXbrl.modelDocument.type in ModelDocument.Type.TESTCASETYPES: for pluginXbrlMethod in pluginClassMethods("Testcases.Start"): pluginXbrlMethod(self, options, modelXbrl) else: # not a test case, probably instance or DTS for pluginXbrlMethod in pluginClassMethods("CntlrCmdLine.Xbrl.Loaded"): pluginXbrlMethod(self, options, modelXbrl) else: success = False if success and options.diffFile and options.versReportFile: try: diffFilesource = FileSource.FileSource(options.diffFile,self) startedAt = time.time() modelXbrl2 = self.modelManager.load(diffFilesource, _("views loading")) if modelXbrl2.errors: if not options.keepOpen: modelXbrl2.close() success = False else: loadTime = time.time() - startedAt modelXbrl.profileStat(_("load"), loadTime) self.addToLog(format_string(self.modelManager.locale, _("diff comparison DTS loaded in %.2f secs"), loadTime), messageCode="info", file=self.entrypointFile) startedAt = time.time() modelDiffReport = self.modelManager.compareDTSes(options.versReportFile) diffTime = time.time() - startedAt modelXbrl.profileStat(_("diff"), diffTime) self.addToLog(format_string(self.modelManager.locale, _("compared in %.2f secs"), diffTime), messageCode="info", file=self.entrypointFile) except ModelDocument.LoadingException: success = False except Exception as err: success = False self.addToLog(_("[Exception] Failed to doad diff file: \n{0} \n{1}").format( err, traceback.format_tb(sys.exc_info()[2]))) if success: try: modelXbrl = self.modelManager.modelXbrl hasFormulae = modelXbrl.hasFormulae if options.validate: startedAt = time.time() if options.formulaAction: # don't automatically run formulas modelXbrl.hasFormulae = False self.modelManager.validate() if options.formulaAction: # restore setting modelXbrl.hasFormulae = hasFormulae self.addToLog(format_string(self.modelManager.locale, _("validated in %.2f secs"), time.time() - startedAt), messageCode="info", file=self.entrypointFile) if options.formulaAction in ("validate", "run"): # do nothing here if "none" from arelle import ValidateXbrlDimensions, ValidateFormula startedAt = time.time() if not options.validate: ValidateXbrlDimensions.loadDimensionDefaults(modelXbrl) # setup fresh parameters from formula optoins modelXbrl.parameters = fo.typedParameters() ValidateFormula.validate(modelXbrl, compileOnly=(options.formulaAction != "run")) self.addToLog(format_string(self.modelManager.locale, _("formula validation and execution in %.2f secs") if options.formulaAction == "run" else _("formula validation only in %.2f secs"), time.time() - startedAt), messageCode="info", file=self.entrypointFile) if options.testReport: ViewFileTests.viewTests(self.modelManager.modelXbrl, options.testReport, options.testReportCols) if options.rssReport: ViewFileRssFeed.viewRssFeed(self.modelManager.modelXbrl, options.rssReport, options.rssReportCols) if options.DTSFile: ViewFileDTS.viewDTS(modelXbrl, options.DTSFile) if options.factsFile: ViewFileFactList.viewFacts(modelXbrl, options.factsFile, labelrole=options.labelRole, lang=options.labelLang, cols=options.factListCols) if options.factTableFile: ViewFileFactTable.viewFacts(modelXbrl, options.factTableFile, labelrole=options.labelRole, lang=options.labelLang) if options.conceptsFile: ViewFileConcepts.viewConcepts(modelXbrl, options.conceptsFile, labelrole=options.labelRole, lang=options.labelLang) if options.preFile: ViewFileRelationshipSet.viewRelationshipSet(modelXbrl, options.preFile, "Presentation Linkbase", "http://www.xbrl.org/2003/arcrole/parent-child", labelrole=options.labelRole, lang=options.labelLang) if options.calFile: ViewFileRelationshipSet.viewRelationshipSet(modelXbrl, options.calFile, "Calculation Linkbase", "http://www.xbrl.org/2003/arcrole/summation-item", labelrole=options.labelRole, lang=options.labelLang) if options.dimFile: ViewFileRelationshipSet.viewRelationshipSet(modelXbrl, options.dimFile, "Dimensions", "XBRL-dimensions", labelrole=options.labelRole, lang=options.labelLang) if options.formulaeFile: ViewFileFormulae.viewFormulae(modelXbrl, options.formulaeFile, "Formulae", lang=options.labelLang) if options.viewArcrole and options.viewFile: ViewFileRelationshipSet.viewRelationshipSet(modelXbrl, options.viewFile, os.path.basename(options.viewArcrole), options.viewArcrole, labelrole=options.labelRole, lang=options.labelLang) for pluginXbrlMethod in pluginClassMethods("CntlrCmdLine.Xbrl.Run"): pluginXbrlMethod(self, options, modelXbrl) except (IOError, EnvironmentError) as err: self.addToLog(_("[IOError] Failed to save output:\n {0}").format(err)) success = False except Exception as err: self.addToLog(_("[Exception] Failed to complete request: \n{0} \n{1}").format( err, traceback.format_tb(sys.exc_info()[2]))) success = False if modelXbrl: modelXbrl.profileStat(_("total"), time.time() - firstStartedAt) if options.collectProfileStats and modelXbrl: modelXbrl.logProfileStats() if not options.keepOpen: if modelDiffReport: self.modelManager.close(modelDiffReport) elif modelXbrl: self.modelManager.close(modelXbrl) self.username = self.password = None #dereference password return success
def __init__(self, logFileName=None, logFileMode=None, logFileEncoding=None, logFormat=None): self.hasWin32gui = False self.hasGui = False if sys.platform == "darwin": self.isMac = True self.isMSW = False self.userAppDir = os.path.expanduser("~") + "/Library/Application Support/Arelle" self.contextMenuClick = "<Button-2>" self.hasClipboard = True self.updateURL = "http://arelle.org/downloads/8" elif sys.platform.startswith("win"): self.isMac = False self.isMSW = True tempDir = tempfile.gettempdir() if tempDir.endswith('local\\temp'): self.userAppDir = tempDir[:-10] + 'local\\Arelle' else: self.userAppDir = tempDir + os.sep + 'arelle' try: import win32clipboard self.hasClipboard = True except ImportError: self.hasClipboard = False try: import win32gui self.hasWin32gui = True # active state for open file dialogs except ImportError: pass self.contextMenuClick = "<Button-3>" if "64 bit" in sys.version: self.updateURL = "http://arelle.org/downloads/9" else: # 32 bit self.updateURL = "http://arelle.org/downloads/10" else: # Unix/Linux self.isMac = False self.isMSW = False self.userAppDir = os.path.join( os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")), "arelle") try: import gtk self.hasClipboard = True except ImportError: self.hasClipboard = False self.contextMenuClick = "<Button-3>" self.moduleDir = os.path.dirname(__file__) # for python 3.2 remove __pycache__ if self.moduleDir.endswith("__pycache__"): self.moduleDir = os.path.dirname(self.moduleDir) if self.moduleDir.endswith("python32.zip/arelle"): ''' distZipFile = os.path.dirname(self.moduleDir) d = os.path.join(self.userAppDir, "arelle") self.configDir = os.path.join(d, "config") self.imagesDir = os.path.join(d, "images") import zipfile distZip = zipfile.ZipFile(distZipFile, mode="r") distNames = distZip.namelist() distZip.extractall(path=self.userAppDir, members=[f for f in distNames if "/config/" in f or "/images/" in f] ) distZip.close() ''' resources = os.path.dirname(os.path.dirname(os.path.dirname(self.moduleDir))) self.configDir = os.path.join(resources, "config") self.imagesDir = os.path.join(resources, "images") self.localeDir = os.path.join(resources, "locale") elif self.moduleDir.endswith("library.zip\\arelle") or self.moduleDir.endswith("library.zip/arelle"): # cx_Freexe resources = os.path.dirname(os.path.dirname(self.moduleDir)) self.configDir = os.path.join(resources, "config") self.imagesDir = os.path.join(resources, "images") self.localeDir = os.path.join(resources, "locale") else: self.configDir = os.path.join(self.moduleDir, "config") self.imagesDir = os.path.join(self.moduleDir, "images") self.localeDir = os.path.join(self.moduleDir, "locale") try: from arelle import webserver self.hasWebServer = True except ImportError: self.hasWebServer = False # assert that app dir must exist if not os.path.exists(self.userAppDir): os.makedirs(self.userAppDir) # load config if it exists self.configJsonFile = self.userAppDir + os.sep + "config.json" self.config = None if os.path.exists(self.configJsonFile): try: with io.open(self.configJsonFile, 'rt', encoding='utf-8') as f: self.config = json.load(f) except Exception as ex: self.config = None # restart with a new config if not self.config: self.config = { 'fileHistory': [], 'windowGeometry': "{0}x{1}+{2}+{3}".format(800, 500, 200, 100), } # start language translation for domain try: gettext.translation("arelle", self.localeDir, getLanguageCodes(self.config.get("userInterfaceLangOverride",None))).install() except Exception as msg: gettext.install("arelle", self.localeDir) from arelle.WebCache import WebCache self.webCache = WebCache(self, self.config.get("proxySettings")) self.modelManager = ModelManager.initialize(self) # start plug in server (requres web cache initialized PluginManager.init(self) self.startLogging(logFileName, logFileMode, logFileEncoding, logFormat)
def __init__(self, logFileName=None, logFileMode=None, logFileEncoding=None, logFormat=None): self.hasWin32gui = False self.hasGui = False if sys.platform == "darwin": self.isMac = True self.isMSW = False self.userAppDir = os.path.expanduser("~") + "/Library/Application Support/Arelle" self.contextMenuClick = "<Button-2>" self.hasClipboard = True self.updateURL = "http://arelle.org/downloads/8" elif sys.platform.startswith("win"): self.isMac = False self.isMSW = True tempDir = tempfile.gettempdir() if tempDir.endswith('local\\temp'): impliedAppDir = tempDir[:-10] + 'local' else: impliedAppDir = tempDir self.userAppDir = os.path.join( os.getenv('XDG_CONFIG_HOME', impliedAppDir), "Arelle") try: import win32clipboard self.hasClipboard = True except ImportError: self.hasClipboard = False try: import win32gui self.hasWin32gui = True # active state for open file dialogs except ImportError: pass self.contextMenuClick = "<Button-3>" if "64 bit" in sys.version: self.updateURL = "http://arelle.org/downloads/9" else: # 32 bit self.updateURL = "http://arelle.org/downloads/10" else: # Unix/Linux self.isMac = False self.isMSW = False self.userAppDir = os.path.join( os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")), "arelle") try: import gtk self.hasClipboard = True except ImportError: self.hasClipboard = False self.contextMenuClick = "<Button-3>" self.moduleDir = os.path.dirname(__file__) # for python 3.2 remove __pycache__ if self.moduleDir.endswith("__pycache__"): self.moduleDir = os.path.dirname(self.moduleDir) if self.moduleDir.endswith("python32.zip/arelle"): ''' distZipFile = os.path.dirname(self.moduleDir) d = os.path.join(self.userAppDir, "arelle") self.configDir = os.path.join(d, "config") self.imagesDir = os.path.join(d, "images") import zipfile distZip = zipfile.ZipFile(distZipFile, mode="r") distNames = distZip.namelist() distZip.extractall(path=self.userAppDir, members=[f for f in distNames if "/config/" in f or "/images/" in f] ) distZip.close() ''' resources = os.path.dirname(os.path.dirname(os.path.dirname(self.moduleDir))) self.configDir = os.path.join(resources, "config") self.imagesDir = os.path.join(resources, "images") self.localeDir = os.path.join(resources, "locale") elif self.moduleDir.endswith("library.zip\\arelle") or self.moduleDir.endswith("library.zip/arelle"): # cx_Freexe resources = os.path.dirname(os.path.dirname(self.moduleDir)) self.configDir = os.path.join(resources, "config") self.imagesDir = os.path.join(resources, "images") self.localeDir = os.path.join(resources, "locale") else: self.configDir = os.path.join(self.moduleDir, "config") self.imagesDir = os.path.join(self.moduleDir, "images") self.localeDir = os.path.join(self.moduleDir, "locale") try: from arelle import webserver self.hasWebServer = True except ImportError: self.hasWebServer = False # assert that app dir must exist if not os.path.exists(self.userAppDir): os.makedirs(self.userAppDir) # load config if it exists self.configJsonFile = self.userAppDir + os.sep + "config.json" self.config = None if os.path.exists(self.configJsonFile): try: with io.open(self.configJsonFile, 'rt', encoding='utf-8') as f: self.config = json.load(f) except Exception as ex: self.config = None # restart with a new config if not self.config: self.config = { 'fileHistory': [], 'windowGeometry': "{0}x{1}+{2}+{3}".format(800, 500, 200, 100), } # start language translation for domain self.setUiLanguage(self.config.get("userInterfaceLangOverride",None), fallbackToDefault=True) from arelle.WebCache import WebCache self.webCache = WebCache(self, self.config.get("proxySettings")) self.modelManager = ModelManager.initialize(self) # start plug in server (requres web cache initialized PluginManager.init(self) self.startLogging(logFileName, logFileMode, logFileEncoding, logFormat)
def __init__(self, hasGui=False, logFileName=None, logFileMode=None, logFileEncoding=None, logFormat=None): self.hasWin32gui = False self.hasGui = hasGui self.hasFileSystem = True # no file system on Google App Engine servers self.moduleDir = os.path.dirname(__file__) # for python 3.2 remove __pycache__ if self.moduleDir.endswith("__pycache__"): self.moduleDir = os.path.dirname(self.moduleDir) if self.moduleDir.endswith("python32.zip/arelle"): ''' distZipFile = os.path.dirname(self.moduleDir) d = os.path.join(self.userAppDir, "arelle") self.configDir = os.path.join(d, "config") self.imagesDir = os.path.join(d, "images") import zipfile distZip = zipfile.ZipFile(distZipFile, mode="r") distNames = distZip.namelist() distZip.extractall(path=self.userAppDir, members=[f for f in distNames if "/config/" in f or "/images/" in f] ) distZip.close() ''' resources = os.path.dirname( os.path.dirname(os.path.dirname(self.moduleDir))) self.configDir = os.path.join(resources, "config") self.imagesDir = os.path.join(resources, "images") self.localeDir = os.path.join(resources, "locale") self.pluginDir = os.path.join(resources, "plugin") elif self.moduleDir.endswith( "library.zip\\arelle") or self.moduleDir.endswith( "library.zip/arelle"): # cx_Freexe resources = os.path.dirname(os.path.dirname(self.moduleDir)) self.configDir = os.path.join(resources, "config") self.imagesDir = os.path.join(resources, "images") self.localeDir = os.path.join(resources, "locale") self.pluginDir = os.path.join(resources, "plugin") else: self.configDir = os.path.join(self.moduleDir, "config") self.imagesDir = os.path.join(self.moduleDir, "images") self.localeDir = os.path.join(self.moduleDir, "locale") self.pluginDir = os.path.join(self.moduleDir, "plugin") configHomeDir = os.getenv('XDG_CONFIG_HOME') if not configHomeDir: # look for path configDir/CONFIG_HOME configHomeDirFile = os.path.join(self.configDir, "XDG_CONFIG_HOME") if os.path.exists(configHomeDirFile): try: with io.open(configHomeDirFile, 'rt', encoding='utf-8') as f: configHomeDir = f.read().strip() if configHomeDir and not os.path.isabs(configHomeDir): configHomeDir = os.path.abspath( configHomeDir) # make into a full path if relative except EnvironmentError: configHomeDir = None if configHomeDir and os.path.exists(configHomeDir): # check if a cache exists in this directory (e.g. from XPE or other tool) impliedAppDir = os.path.join(configHomeDir, "arelle") if os.path.exists(impliedAppDir): self.userAppDir = impliedAppDir elif os.path.exists(os.path.join(configHomeDir, "cache")): self.userAppDir = configHomeDir # use the XDG_CONFIG_HOME because cache is already a subdirectory else: self.userAppDir = impliedAppDir if sys.platform == "darwin": self.isMac = True self.isMSW = False self.isGAE = False if not configHomeDir: self.userAppDir = os.path.expanduser( "~") + "/Library/Application Support/Arelle" # note that cache is in ~/Library/Caches/Arelle self.contextMenuClick = "<Button-2>" self.hasClipboard = hasGui # clipboard always only if Gui (not command line mode) self.updateURL = "http://arelle.org/downloads/8" elif sys.platform.startswith("win"): self.isMac = False self.isMSW = True self.isGAE = False if not configHomeDir: tempDir = tempfile.gettempdir() if tempDir.endswith('local\\temp'): impliedAppDir = tempDir[:-10] + 'local' else: impliedAppDir = tempDir self.userAppDir = os.path.join(impliedAppDir, "Arelle") if hasGui: try: import win32clipboard self.hasClipboard = True except ImportError: self.hasClipboard = False try: import win32gui self.hasWin32gui = True # active state for open file dialogs except ImportError: pass else: self.hasClipboard = False self.contextMenuClick = "<Button-3>" if "64 bit" in sys.version: self.updateURL = "http://arelle.org/downloads/9" else: # 32 bit self.updateURL = "http://arelle.org/downloads/10" else: # Unix/Linux self.isMac = False self.isMSW = False serverSoftware = os.getenv("SERVER_SOFTWARE", "") if serverSoftware.startswith( "Google App Engine/") or serverSoftware.startswith( "Development/"): self.hasFileSystem = False # no file system, userAppDir does not exist self.isGAE = True elif not configHomeDir: self.userAppDir = os.path.join(os.path.expanduser("~/.config"), "arelle") self.isGAE = False if hasGui: try: import gtk self.hasClipboard = True except ImportError: self.hasClipboard = False else: self.hasClipboard = False self.contextMenuClick = "<Button-3>" try: from arelle import webserver self.hasWebServer = True except ImportError: self.hasWebServer = False # assert that app dir must exist self.config = None if self.hasFileSystem: if not os.path.exists(self.userAppDir): os.makedirs(self.userAppDir) # load config if it exists self.configJsonFile = self.userAppDir + os.sep + "config.json" if os.path.exists(self.configJsonFile): try: with io.open(self.configJsonFile, 'rt', encoding='utf-8') as f: self.config = json.load(f) except Exception as ex: self.config = None # restart with a new config if not self.config: self.config = { 'fileHistory': [], 'windowGeometry': "{0}x{1}+{2}+{3}".format(800, 500, 200, 100), } # start language translation for domain self.setUiLanguage(self.config.get("userInterfaceLangOverride", None), fallbackToDefault=True) from arelle.WebCache import WebCache self.webCache = WebCache(self, self.config.get("proxySettings")) self.modelManager = ModelManager.initialize(self) # start plug in server (requres web cache initialized, but not logger) PluginManager.init(self) self.startLogging(logFileName, logFileMode, logFileEncoding, logFormat) # Cntlr.Init after logging started for pluginMethod in PluginManager.pluginClassMethods("Cntlr.Init"): pluginMethod(self)
def __init__(self, hasGui=False, logFileName=None, logFileMode=None, logFileEncoding=None, logFormat=None): self.hasWin32gui = False self.hasGui = hasGui self.hasFileSystem = True # no file system on Google App Engine servers self.isGAE = False self.isCGI = False self.systemWordSize = int(round(math.log(sys.maxsize, 2)) + 1) # e.g., 32 or 64 _resourcesDir = resourcesDir() self.configDir = os.path.join(_resourcesDir, "config") self.imagesDir = os.path.join(_resourcesDir, "images") self.localeDir = os.path.join(_resourcesDir, "locale") self.pluginDir = os.path.join(_resourcesDir, "plugin") _mplDir = os.path.join(_resourcesDir, "mpl-data") if os.path.exists( _mplDir ): # set matplotlibdata for cx_Freeze with local directory os.environ["MATPLOTLIBDATA"] = _mplDir serverSoftware = os.getenv("SERVER_SOFTWARE", "") if serverSoftware.startswith( "Google App Engine/") or serverSoftware.startswith( "Development/"): self.hasFileSystem = False # no file system, userAppDir does not exist self.isGAE = True else: gatewayInterface = os.getenv("GATEWAY_INTERFACE", "") if gatewayInterface.startswith("CGI/"): self.isCGI = True configHomeDir = None # look for path configDir/CONFIG_HOME in argv and environment parameters for i, arg in enumerate( sys.argv): # check if config specified in a argv if arg.startswith("--xdgConfigHome="): configHomeDir = arg[16:] break elif arg == "--xdgConfigHome" and i + 1 < len(sys.argv): configHomeDir = sys.argv[i + 1] break if not configHomeDir: # not in argv, may be an environment parameter configHomeDir = os.getenv('XDG_CONFIG_HOME') if not configHomeDir: # look for path configDir/CONFIG_HOME configHomeDirFile = os.path.join(self.configDir, "XDG_CONFIG_HOME") if os.path.exists(configHomeDirFile): try: with io.open(configHomeDirFile, 'rt', encoding='utf-8') as f: configHomeDir = f.read().strip() if configHomeDir and not os.path.isabs(configHomeDir): configHomeDir = os.path.abspath( configHomeDir) # make into a full path if relative except EnvironmentError: configHomeDir = None if self.hasFileSystem and configHomeDir and os.path.exists( configHomeDir): # check if a cache exists in this directory (e.g. from XPE or other tool) impliedAppDir = os.path.join(configHomeDir, "arelle") if os.path.exists(impliedAppDir): self.userAppDir = impliedAppDir elif os.path.exists(os.path.join(configHomeDir, "cache")): self.userAppDir = configHomeDir # use the XDG_CONFIG_HOME because cache is already a subdirectory else: self.userAppDir = impliedAppDir if sys.platform == "darwin": self.isMac = True self.isMSW = False if self.hasFileSystem and not configHomeDir: self.userAppDir = os.path.expanduser( "~") + "/Library/Application Support/Arelle" # note that cache is in ~/Library/Caches/Arelle self.contextMenuClick = "<Button-2>" self.hasClipboard = hasGui # clipboard always only if Gui (not command line mode) self.updateURL = "http://arelle.org/downloads/8" elif sys.platform.startswith("win"): self.isMac = False self.isMSW = True if self.hasFileSystem and not configHomeDir: tempDir = tempfile.gettempdir() if tempDir.lower().endswith('local\\temp'): impliedAppDir = tempDir[:-10] + 'local' else: impliedAppDir = tempDir self.userAppDir = os.path.join(impliedAppDir, "Arelle") if hasGui: try: import win32clipboard self.hasClipboard = True except ImportError: self.hasClipboard = False try: import win32gui self.hasWin32gui = True # active state for open file dialogs except ImportError: pass else: self.hasClipboard = False self.contextMenuClick = "<Button-3>" if "64 bit" in sys.version: self.updateURL = "http://arelle.org/downloads/9" else: # 32 bit self.updateURL = "http://arelle.org/downloads/10" else: # Unix/Linux self.isMac = False self.isMSW = False if self.hasFileSystem and not configHomeDir: self.userAppDir = os.path.join(os.path.expanduser("~/.config"), "arelle") if hasGui: try: import gtk self.hasClipboard = True except ImportError: self.hasClipboard = False else: self.hasClipboard = False self.contextMenuClick = "<Button-3>" try: from arelle import webserver self.hasWebServer = True except ImportError: self.hasWebServer = False # assert that app dir must exist self.config = None if self.hasFileSystem: if not os.path.exists(self.userAppDir): os.makedirs(self.userAppDir) # load config if it exists self.configJsonFile = self.userAppDir + os.sep + "config.json" if os.path.exists(self.configJsonFile): try: with io.open(self.configJsonFile, 'rt', encoding='utf-8') as f: self.config = json.load(f) except Exception as ex: self.config = None # restart with a new config if not self.config: self.config = { 'fileHistory': [], 'windowGeometry': "{0}x{1}+{2}+{3}".format(800, 500, 200, 100), } # start language translation for domain self.setUiLanguage(self.config.get("userInterfaceLangOverride", None), fallbackToDefault=True) from arelle.WebCache import WebCache self.webCache = WebCache(self, self.config.get("proxySettings")) # start plug in server (requres web cache initialized, but not logger) PluginManager.init(self, loadPluginConfig=hasGui) # requires plug ins initialized self.modelManager = ModelManager.initialize(self) # start taxonomy package server (requres web cache initialized, but not logger) PackageManager.init(self, loadPackagesConfig=hasGui) self.startLogging(logFileName, logFileMode, logFileEncoding, logFormat) # Cntlr.Init after logging started for pluginMethod in PluginManager.pluginClassMethods("Cntlr.Init"): pluginMethod(self)