def testMove(self): """ Test for the move method. """ item_support.move("", "") self._repositoryMock.error = ItemError("") self.assertRaises(ItemSupportError, item_support.move, "", "") self._repositoryMock.error = None self._itemMock.methodNameResultMap = {"move": (None, ItemError(""))} self.assertRaises(ItemSupportError, item_support.move, "", "")
def testCopy(self): """ Test for the copy method. """ item_support.copy("", "") self._repositoryMock.error = ItemError("") self.assertRaises(ItemSupportError, item_support.copy, "", "") self._repositoryMock.error = None self._itemMock.methodNameResultMap = {"copy": (None, ItemError(""))} self.assertRaises(ItemSupportError, item_support.copy, "", "")
def checkDatamodelConsistency(self, parentDataType, childDataType, isRoot=False): """ Checks the data model consistency of both items. """ if self._configuration.isManagedRepository: if childDataType is None: raise ItemError("Data type is invalid.") if parentDataType is None and not isRoot: raise ItemError("Data type is invalid.") if not self._existsConnection(parentDataType, childDataType): raise ItemError("Cannot perform action because no relation between " \ + "both data types is defined by the underlying data model.")
def _checkPreConditions(self, sourceItem, properties): """ Sanity checks before the archive process starts. """ if not sourceItem.capabilities.canArchive: raise ItemError("The item '%s' cannot be archived." % sourceItem.path) missingPropertyIds = list() for property_ in properties: if not property_.propertyDefinition in self._repository.configuration.defaultArchivePropertyDefinitions: missingPropertyIds.append(property_.propertyDefinition.identifier) if len(missingPropertyIds) > 0: errorMessage = "The following properties are missing:" for propertyId in missingPropertyIds: errorMessage += "\n" + propertyId raise ItemError(errorMessage)
def _storeArchiveData(self, sourceCollection, archiveRoot): """ Collects data which has to be archived and stores it. """ importedLeafs = list() temporaryFilePath = self._determineTemporaryFilePath() try: # put everything in a temporary file cwr = self._repositoryManager.workingRepository archiveRepository = self._repositoryManager.connectRepository("arch:" + temporaryFilePath) try: importer = Importer(_STOP_TRAVERSAL_STATES, _STOP_PROCESSING_STATES) for item in sourceCollection.getChildren(): importer.performImport(item, archiveRepository.root, ignoreLinks=True) importedLeafs += importer.importedLeafs finally: self._repositoryManager.disconnectRepository(archiveRepository) self._repositoryManager.workingRepository = cwr # store it - when necessary if len(importedLeafs) > 0: try: archiveRoot.dataPersister.storeData(open(temporaryFilePath, "rb")) except (OSError, IOError): raise ItemError("Unable to access temporary created archive data.") finally: try: os.remove(temporaryFilePath) except OSError: _log.debug("Cannot remove temporary file '%s'" % temporaryFilePath) return importedLeafs
def _ensureReadableSystem(self): """ Make sure, self._archiveFileSystem contains a valid readable file system. If none is present, the corresponding ZIP file will be downloaded. """ if self._fileSystem is None: key = self._rootItem.path + str(self._index) if key in _temporaryFileMap: self._fileSystem = _temporaryFileMap[key][1] else: fd, path = mkstemp() fileHandle = os.fdopen(fd, "w+b") inStream = self._rootItem.dataPersister.retrieveData( self._index) try: block = inStream.read(_BLOCK_SIZE) while len(block) > 0: fileHandle.write(block) block = inStream.read(_BLOCK_SIZE) while len(block) > 0: fileHandle.write(block) block = inStream.read(_BLOCK_SIZE) fileHandle.close() except (OSError, IOError), error: reason = os.strerror(error.errno or 0) raise ItemError("Cannot retrieve archive.\nReason: '%s'" % reason) else: config = BaseConfiguration('arch:' + path) _log.debug("Downloaded %s to %s." % (self._rootItem.path, path)) self._fileSystem = FileSystem(config) _temporaryFileMap[key] = (path, self._fileSystem)
def testDelete(self): """ Test for the delete method. """ item_support.delete("") self._itemMock.error = ItemError("") self.assertRaises(ItemSupportError, item_support.delete, "")
def testCreateLink(self): """ Test for the createLink method. """ item_support.createLink("", "") self._itemMock.methodNameResultMap = {"create": (None, ItemError(""))} self.assertRaises(ItemSupportError, item_support.createLink, "", "")
def testRefresh(self): """ Test for the refresh method. """ item_support.refresh("") self._itemMock.error = ItemError("") self.assertRaises(ItemSupportError, item_support.refresh, "")
def _performFileActionWin32(self, item, command): """ Performs the given command on the specific file. """ # pylint: disable=E1101 # E1101: Pylint cannot resolve specific win32 modules. localContentPath, alreadyLocal = self._getContent(item) print localContentPath, alreadyLocal if not alreadyLocal and len( self._checkUntilClosedWorker) == self._MAX_WORKER_THREADS: errorMessage = "The maximum number (%i) of parallel opened editors " % self._MAX_WORKER_THREADS \ + "has been reached. Please close at least one external application." raise ItemError(errorMessage) fMask = 0 if not alreadyLocal: fMask = shellcon.SEE_MASK_NOCLOSEPROCESS try: result = shell.ShellExecuteEx(fMask, 0, command, localContentPath, "", "", 1) except pywintypes.error: return else: if not alreadyLocal: workerId = str(result["hProcess"]) worker = startNewQtThread( self._checkUntilClosed, self._createCheckUntilClosedCallback(workerId), result["hProcess"], command == self._OPEN_COMMAND, item, localContentPath) self._checkUntilClosedWorker[workerId] = worker
def testStoreData(self): """ Test for the storeData method. """ item_support.storeData("", "") self._itemMock.error = ItemError("") self.assertRaises(ItemSupportError, item_support.storeData, "", "")
def testRetrieveData(self): """ Test for the retrieveData method. """ item_support.retrieveData("") self._itemMock.error = ItemError("") self.assertRaises(ItemSupportError, item_support.retrieveData, "")
def create(self, properties): """ @see: L{ItemBase.create<datafinder.core.item.base.ItemBase.create>} """ if self._linkTarget is None: raise ItemError( "Cannot create link because the link target is missing.") else: ItemBase.create(self, properties) try: if not self.fileStorer.exists(): self.fileStorer.createLink(self._linkTarget.fileStorer) self._refreshProperties() except PersistenceError, error: raise ItemError("Unable to create leaf item.\nReason:'%s'" % error.message) else:
def testCreate(self): """ Test creation method of the archive data persister. """ self._persister.create() self._baseDataPersisterMock.error = ItemError("Already exists.") self.assertRaises(ItemError, self._persister.create)
def testCreateCollection(self): """ Test for the createCollection method. """ item_support.createCollection("", dict()) self._itemMock.methodNameResultMap = {"create": (None, ItemError(""))} self.assertRaises(ItemSupportError, item_support.createCollection, "", dict())
def testSearch(self): """ Test for the search method. """ self._itemMock.value = list() item_support.search("", "") self._itemMock.error = ItemError("") self.assertRaises(ItemSupportError, item_support.search, "", "")
def performImport(self, source, targetCollection, newSourceName=None, defaultProperties=None, copyData=True, ignoreLinks=False, determinePropertiesCallback=None): """ This method initiates the copy process and starts walking the source creating a new node in the destination tree for each item it passes. @param source: The item that should be imported. @type source: L{ItemBase<datafinder.core.item.base.ItemBase>} @param targetCollection: The collection that should afterwards contain the copy. @type targetCollection: L{ItemCollection<datafinder.core.item.collection.ItemCollection>} @param newSourceName: Optional new name of the source item. Default: C{None} @type newSourceName: C{unicode} @param defaultProperties: Optional list of properties which are set for every item. Default: C{None} @type defaultProperties: C{list} of L{Property<datafinder.core.item.property.Property>} @param copyData: Flag indicating whether data has to be copied or not. @type copyData: C{bool} @param ignoreLinks: Flag indicating the links are ignored during import. Default: C{False} @type ignoreLinks: C{bool} @param determinePropertiesCallback: Function determining properties used when importing a specific item. @type: determinePropertiesCallback: C{callable} using an item description as input and returns a dictionary describing the properties. @raise ItemError: Indicating errors during import. """ self._pwd = targetCollection self._deferredLinks = list() self._destinationRootPath = targetCollection.path self._itemFactory = targetCollection.itemFactory self._newSourceName = newSourceName self._defaultProperties = defaultProperties self._source = source self._copyData = copyData self.importedLeafs = list() self._ignoreLinks = ignoreLinks self._determinePropertiesCallback = determinePropertiesCallback self.walk(source) missingDefferedLinkPaths = list() for source, importName, destinationParent in self._deferredLinks: try: self._copyLink(source, importName, destinationParent) except ItemError: missingDefferedLinkPaths.append(source.path) if len(missingDefferedLinkPaths) > 0: errorMessage = "The following links could not be imported:" for linkPath in missingDefferedLinkPaths: errorMessage += "\n" + linkPath raise ItemError(errorMessage)
def _determineTemporaryFilePath(): """ Determines a temporary file path and returns it. """ try: tmpFile = NamedTemporaryFile() tmpFile.close() except (OSError, IOError): raise ItemError("Cannot determine temporary file name.") else: return tmpFile.name
def create(self): """ Creates the file resource on separated storage system under the path of the item. """ if not self._fileStorer.exists(): self._createParentCollection(self._fileStorer.parent) self._fileStorer.createResource() else: errorMessage = "The data persister '%s' does already exist." % ( self._fileStorer.identifier) raise ItemError(errorMessage)
def testWalk(self): """ Tests the walk method. """ self._repositoryMock.value = [ SimpleMock(path="/"), SimpleMock(path="/test") ] self.assertEquals(item_support.walk("/"), ["/", "/test"]) self._repositoryMock.error = ItemError("") self.assertRaises(ItemSupportError, item_support.walk, "")
def create(self): """ Initially creates the referenced file resource on the separated storage system. Additionally, sets the content identifier property in the item properties. This is required to identify the resource on the separated storage system. """ self._prepareAction() if self._fileStorer.exists(): raise ItemError("The unique identifier '%s' generated for item '%s' does already exist." \ % (self._fileStorer.name, self._item.path)) else: self._fileStorer.createResource() propertyDefinition = self._propertyRegistry.getPropertyDefinition( CONTENT_IDENTIFIER_ID) self._item.updateProperties( [Property(propertyDefinition, self._fileStorer.name)]) if not CONTENT_IDENTIFIER_ID in self._item.properties: raise ItemError("Unable to set the unique identifier property " \ + "to '%s' for item '%s'." % (self._fileStorer.name, self._item.path))
def create(self, path, parent=None, fileStorer=None): """ Returns an item for the given path. If it does not exist an error is raised. @param path: Path relative to the root item. E.g. "/a/b/c". @type path: C{unicode} @return: An item. @rtype: L{ItemBase<datafinder.core.item.base.ItemBase>} @raise ItemError: Raised when the item does not exist. """ try: if fileStorer is None \ and path not in self._itemCache: fileStorer = self._fileSystem.createFileStorer(path) elif fileStorer is not None: path = fileStorer.identifier if path in self._itemCache: item = self._itemCache[path] if not parent is None: item.parent = parent return item if path == "/": item = self._createItem(ItemRoot, fileStorer, None, parent) else: if fileStorer.isCollection: item = self._createItem(ItemCollection, fileStorer, None, parent) elif fileStorer.isLink: item = self._createItem(ItemLink, fileStorer, None, parent) elif fileStorer.isLeaf: item = self._createItem(ItemLeaf, fileStorer, None, parent) else: raise ItemError("No valid item representation found for '%s'" % path) except PersistenceError, error: raise ItemError("Problem accessing item '%s'. Reason: '%s'" % (path, error.message))
def _createItem(self, itemClass, fileStorer=None, name=None, parent=None): """ Creates the concrete item. """ item = itemClass(name, fileStorer) item.itemFactory = self if not parent is None: if parent.hasChild(item.name): raise ItemError("The item '%s' already has a child '%s'." % (parent.path, item.name)) item.parent = parent item._created = False if not parent is None: item._ignoreChecks = parent.ignoreChecks self._itemCache[item.path] = item return item
def create(self, properties): """ @see: L{ItemBase.create<datafinder.core.item.base.ItemBase.create>} """ ItemBase.create(self, properties) try: if not self.fileStorer.exists(): canStoreProperties = self.capabilities.canStoreProperties self.fileStorer.createResource() if canStoreProperties: self.updateProperties(properties) self.dataPersister.create() self._refreshProperties() except PersistenceError, error: raise ItemError("Unable to create leaf item.\nReason:'%s'" % error.message)
def create(self, properties): """ @see: L{ItemBase.create<datafinder.core.item.base.ItemBase.create>} """ ItemBase.create(self, properties) self.itemFactory.checkDatamodelConsistency(self.parent.dataType, self.dataType, self.parent.isRoot) try: if not self.fileStorer.exists(): canStoreProperties = self.capabilities.canStoreProperties self.fileStorer.createCollection() if canStoreProperties: self.updateProperties(properties) self.dataPersister.create() self._refreshProperties() except PersistenceError, error: raise ItemError("Unable to create collection item.\nReason:'%s'" % error.message)
def _performFileAction(self, item, command): """ Performs the given command on the specific file. """ print _isWin32 if _isWin32: self._performFileActionWin32(item, command) else: if self._OPEN_COMMAND: # Run a default viewer defaultViewer = os.environ.get( self._DF_DEFAULT_FILE_VIEWER_ENV, self._DF_DEFAULT_LINUX_VIEWER) localContentPath, _ = self._getContent(item) try: subprocess.Popen((defaultViewer, localContentPath)) except OSError, error: raise ItemError("Cannot open file. Reason: '%s'" % str(error)) else:
def getChildren(self): """ @see: L{ItemBase.getChildren<datafinder.core.item.base.ItemBase.getChildren>} """ if self._children is None: self._children = list() try: try: children = self.fileStorer.getChildren() except PersistenceError, error: self._childrenPopulated = True raise ItemError(error.args) else: for fileStorer in children: try: self._createItem(fileStorer) except ItemError: continue
def copy(self, item): """ Duplicates resource with the help of the data persister of the newly created target item. Updates the properties of the target item accordingly. """ self._prepareAction() uniqueName = _generateUniqueIdentifier(item.uri) targetFileStorer = self._baseFileStorer.getChild(uniqueName) self._fileStorer.copy(targetFileStorer) propertyDefinition = self._propertyRegistry.getPropertyDefinition( CONTENT_IDENTIFIER_ID) item.updateProperties([Property(propertyDefinition, uniqueName)]) item._dataPersister = None if not CONTENT_IDENTIFIER_ID in item.properties: raise ItemError("Unable to set the unique identifier property " \ + "to '%s' for item '%s'." % (uniqueName, item.path))
def move(self, sourceIndexes, targetParentIndex, newName=None): """ Moves the item referenced by C{sourceIndex} under the item referenced by C{targetParentIndex}. @param sourceIndex: List of indexes identifying the source items. @type sourceIndex: C{list} of L{QModelIndex<PyQt4.QtCore.QModelIndex>} @param targetParentIndex: Index identifying the new parent item of the source item. @type targetParentIndex: L{QModelIndex<PyQt4.QtCore.QModelIndex>} @param newName: Optional new of the moved item. @type newName: C{unicode} @raise ItemError: Indicating problems on moving. """ for sourceIndex in sourceIndexes: if sourceIndex.isValid(): sourceItem = self._parentModel.nodeFromIndex(sourceIndex) targetParentItem = self._parentModel.nodeFromIndex( targetParentIndex) if targetParentItem.path.startswith(sourceItem.path): postPath = targetParentItem.path[len(sourceItem.path):] if len(postPath) == 0 or postPath[0] == "/": raise ItemError( "Cannot move item in its own sub-structure.") targetName = self._repository.determineUniqueItemName( newName or sourceItem.name, targetParentItem) try: targetItem = self._createNewItem(targetName, targetParentItem, sourceItem.isCollection, sourceItem.linkTarget, sourceItem.isLink) sourceItem.move(targetItem) except ItemError, error: targetItem.invalidate() raise error else: del sourceItem
def _performPostArchivingActions(self, sourceItem, targetItem): """ Performs post archiving actions. """ if self._repository.configuration.isManagedRepository: properties = [self._repository.createProperty(ARCHIVE_ROOT_COLLECTION_ID, targetItem.path), self._repository.createProperty(ARCHIVE_PART_INDEX_ID, 0)] failedCopiedItems = list() importer = Importer(_STOP_TRAVERSAL_STATES, _STOP_PROCESSING_STATES) for sourceItem in sourceItem.getChildren(): try: importer.performImport(sourceItem, targetItem, defaultProperties=properties, copyData=False, ignoreLinks=True) except CoreError, error: failedCopiedItems.append((sourceItem, error.message)) if len(failedCopiedItems) > 0: errorMessage = "Problems occurred while performing post archiving action." \ + "The following items could not be copied:" for sourceItem, message in failedCopiedItems: errorMessage += "\n" + sourceItem.path + " Reason: " + message raise ItemError(errorMessage) else: targetItem.refresh()