def updateDict(self, propDict): """ このオブジェクトのpropertyをdictで更新する。 dictのキーはASCII文字列でなければならない。 更新されたpropertyのdictを返す。 """ filePath = os.path.abspath( os.path.normpath(self._getPropertyFilePath())) #全てのkeyがASCII文字列であるかチェック。 for key in propDict.keys(): if not isinstance(key, basestring): msg = 'Bug found. Tried to update a property file %s with non-string key "%s".' % ( filePath, repr(key)) logging.error(msg) raise MyException(msg) #propertyファイル更新。 with FileLock(filePath): #propertyファイルのリードとライトをアトミックに行う。 currentDict = self.__updateDict(propDict) #キャッシュ更新。 self.__cache.set(filePath, currentDict) return currentDict
def __getDictWithoutInheritance(self, filePath): """ Propertyファイルリード。キャッシュは使わない。 """ if not os.path.exists(filePath): return {} #読み込みに失敗すればself.__readTimeLimitの時間だけ再トライを続ける。 startTime = datetime.datetime.now() while (datetime.datetime.now() - startTime < self.__readTimeLimit): #JSONフォーマットでdictを読み込むので正常なファイルでは{と}のペアが対応しており、他プロセス(他ユーザー)の書き込み途中に読み込んだ場合特殊な場合を除いて例外を送出する。 #他プロセス(他ユーザー)によるライト途中の読み込みはJSON読み込みの失敗で検知できるものとし、ファイルロックやロックファイル有無の確認は行わない。 try: with open(filePath, 'r') as f: propertyDict = json.load(f) break #読み込み成功。 except: if not os.path.exists(filePath): #読み込もうとしている最中に他プロセス(ユーザー)によってファイルが削除された。 return {} import traceback exc = traceback.format_exc() #ロギング用にtraceback表示の記録。 time.sleep(self.__READ_INTERVAL) else: #読み込み失敗。 msg = 'Failed reading property file ' + repr(filePath) logging.error(msg) logging.error(exc) raise MyException(msg) return propertyDict
def getWithoutInheritance(self, key, default=None): """ 継承を含めないpropertyのkeyをとってvalueを返す。 keyに対するvalueがなければdefaultを返す。 何度も呼ぶ場合は都度ファイルアクセスが発生しないようgetDictWithoutInheritance()を用いること。 """ filePath = os.path.abspath( os.path.normpath(self._getPropertyFilePath())) if not isinstance(key, basestring): msg = 'Bug found. Tried to get a property with non-string key "%s" from file %s' % ( repr(key), repr(filePath)) logging.error(msg) raise MyException(msg) return self.getDictWithoutInheritance().get(key, default)
def __enter__(self): startTime = datetime.datetime.now() while (True): try: os.mkdir(self._lockFilePath) return except: if datetime.datetime.now() - startTime > self._timeLimit: msg = 'Could not lock file ' + repr(self._filePath) logging.error(msg) import traceback logging.error(traceback.format_exc()) raise MyException(msg) time.sleep(self._SLEEP_SEC)
def get(self, pluginName): """ プラグインを取得する。既に読み込まれていれば再ロードせずキャッシュされたものを返す。 """ #ロードするプラグインファイルの特定。 pluginFilePath = self._getPluginFilePath(pluginName) if not pluginFilePath: #プラグインファイルがない。デフォルトプラグインが指定されていればそれを使う。 if (self.__defaultPluginName): pluginName = self.__defaultPluginName pluginFilePath = self._getPluginFilePath(pluginName) if not pluginFilePath: msg = 'Plugin ' + repr(pluginName) + ' not found.' logging.error(msg) import traceback logging.error(traceback.format_exc()) userMessage.showError(msg) raise MyException(msg) #キャッシュを探す。 plugin = self.__loadedPluginCache.get(pluginName) if plugin: return plugin #ロード。 try: if pluginFilePath.endswith('py'): plugin = imp.load_source(pluginName, pluginFilePath) else: plugin = imp.load_compiled(pluginName, pluginFilePath) except: msg = 'Failed reading plugin file ' + repr(pluginFilePath) + ' .' logging.error(msg) import traceback logging.error(traceback.format_exc()) userMessage.showError(msg) raise self.__loadedPluginCache[plugin] = plugin return plugin
def remove(self, key): """ このオブジェクトのkeyで指定されたpropertyを削除する。存在しなければ何もしない。 キーはASCII文字列でなければならない。 更新されたpropertyのdictを返す。 """ filePath = os.path.abspath( os.path.normpath(self._getPropertyFilePath())) if not isinstance(key, basestring): msg = 'Bug found. Tried to remove a property from file %s with non-string key "%s".' % ( filePath, repr(key)) logging.error(msg) raise MyException(msg) #propertyファイル更新。 with FileLock(filePath): #propertyファイルのリードとライトをアトミックに行う。 currentDict = self.__remove(key, filePath) #キャッシュ更新。 self.__cache.set(filePath, currentDict) return currentDict