Пример #1
0
    def testGetFilesByOrderedTypes(self):
        if os.name == 'posix':
            configFilePathName = '/storage/emulated/0/Android/data/ru.iiec.pydroid3/files/trans_file_cloud/test/transfiles.ini'
        else:
            configFilePathName = 'D:\\Development\\Python\\trans_file_cloud\\test\\transfiles.ini'

        cm = ConfigManager(configFilePathName)
        fl = FileLister(cm)
        cloudFileLst = [
            'aa_current.jpg', 'constants_2.py', 'current_state_21.jpg',
            'current_state_22.jpg', 'doc_21.docx', 'doc_22.docx',
            'filelister_2.py', 'filemover_2.py', 'README_2.md',
            'testfilelister_2.py', 'testfilemover_2.py'
        ]

        orderedFileTypeWildchardExprLst, fileTypeDic = fl.getFilesByOrderedTypes(
            'transFileCloudTestProject', cloudFileLst=cloudFileLst)

        self.assertEqual([
            'aa*.jpg', '*Solemne*.mp3', 'test*.py', '*.mp3', '*.jpg', '*.docx',
            '*.py', '*.md'
        ], orderedFileTypeWildchardExprLst)

        if os.name == 'posix':
            self.assertEqual(
                {
                    '*.jpg':
                    ('/images',
                     ['current_state_21.jpg', 'current_state_22.jpg']),
                    '*.docx': ('/doc', ['doc_21.docx', 'doc_22.docx']),
                    '*.md': ('', ['README_2.md']),
                    '*.mp3': ('/mp3', []),
                    'test*.py':
                    ('/test', ['testfilelister_2.py', 'testfilemover_2.py']),
                    '*.py':
                    ('',
                     ['constants_2.py', 'filelister_2.py', 'filemover_2.py']),
                    '*Solemne*.mp3': ('/mp3/solemne', []),
                    'aa*.jpg': ('/images/aa', ['aa_current.jpg'])
                }, fileTypeDic)
        else:
            self.assertEqual(
                {
                    '*.jpg':
                    ('\\images',
                     ['current_state_21.jpg', 'current_state_22.jpg']),
                    '*.docx': ('\\doc', ['doc_21.docx', 'doc_22.docx']),
                    '*.md': ('', ['README_2.md']),
                    '*.mp3': ('\\mp3', []),
                    'test*.py':
                    ('\\test', ['testfilelister_2.py', 'testfilemover_2.py']),
                    '*.py':
                    ('',
                     ['constants_2.py', 'filelister_2.py', 'filemover_2.py']),
                    '*Solemne*.mp3': ('\\mp3\\solemne', []),
                    'aa*.jpg': ('\\images\\aa', ['aa_current.jpg'])
                }, fileTypeDic)
    def testMoveFilesToLocalDirs(self):
        if os.name == 'posix':
            downloadDir = '/storage/emulated/0/Android/data/ru.iiec.pydroid3/files/trans_file_cloud/test/testproject_1/fromdir'
            downloadDirSaved = '/storage/emulated/0/Android/data/ru.iiec.pydroid3/files/trans_file_cloud/test/testproject_1/fromdir_saved'
            projectDir = '/storage/emulated/0/Android/data/ru.iiec.pydroid3/files/trans_file_cloud/test/testproject_1/projectdir'
            projectDirEmpty = '/storage/emulated/0/Android/data/ru.iiec.pydroid3/files/trans_file_cloud/test/testproject_1/projectdir_empty'

            TEST_SUB_DIR = '/test'
            IMG_SUB_DIR = '/images'
            DOC_SUB_DIR = '/doc'
        else:
            # Windows
            downloadDir = 'D:\\Development\\Python\\trans_file_cloud\\test\\testproject_1\\fromdir'
            downloadDirSaved = 'D:\\Development\\Python\\trans_file_cloud\\test\\testproject_1\\fromdir_saved'
            projectDir = 'D:\\Development\\Python\\trans_file_cloud\\test\\testproject_1\\projectdir'
            projectDirEmpty = 'D:\\Development\\Python\\trans_file_cloud\\test\\testproject_1\\projectdir_empty'

            TEST_SUB_DIR = '/test'
            IMG_SUB_DIR = '/images'
            DOC_SUB_DIR = '/doc'

        configManager = ConfigManager(CONFIG_FILE_PATH_NAME)

        # deleting downloadDir (dir and content)
        if os.path.exists(downloadDir):
            shutil.rmtree(downloadDir)

        # restoring downloadDir from its saved version
        shutil.copytree(downloadDirSaved, downloadDir)

        # deleting projectDir
        if os.path.exists(projectDir):
            shutil.rmtree(projectDir)

        # restoring a directory structure only project dir (no files) from its saved empty version
        shutil.copytree(projectDirEmpty, projectDir)

        # ensuring downloadDir contains the required files

        fl = FileLister(configManager)
        projectName = 'transFileCloudTestProject'
        cloudFileLst = [
            'constants_1.py', 'current_state_11.jpg', 'current_state_12.jpg',
            'doc_11.docx', 'doc_12.docx', 'filelister_1.py', 'filemover_1.py',
            'README_1.md', 'testfilelister_1.py', 'testfilemover_1.py'
        ]
        _, fileTypeDic = fl.getFilesByOrderedTypes(projectName,
                                                   cloudFileLst=cloudFileLst)

        self.assertEqual(
            sorted(['filelister_1.py', 'filemover_1.py', 'constants_1.py']),
            fileTypeDic['*.py'][1])
        self.assertEqual(sorted(['testfilelister_1.py', 'testfilemover_1.py']),
                         fileTypeDic['test*.py'][1])
        self.assertEqual(
            sorted(['current_state_12.jpg', 'current_state_11.jpg']),
            fileTypeDic['*.jpg'][1])
        self.assertEqual(sorted(['doc_12.docx', 'doc_11.docx']),
                         fileTypeDic['*.docx'][1])
        self.assertEqual(sorted(['README_1.md']), fileTypeDic['*.md'][1])

        fm = FileMover(configManager, projectName)
        fm.projectDir = projectDir

        # capturing stdout into StringIO to avoid outputing in terminal
        # window while unit testing

        stdout = sys.stdout
        outputCapturingString = StringIO()
        sys.stdout = outputCapturingString

        fm.moveFilesToLocalDirs(cloudFileLst)

        sys.stdout = stdout

        if os.name == 'posix':
            self.assertEqual([
                'moving test/testproject_1/fromdir/testfilelister_1.py to '
                'testproject_1/projectdir/test/testfilelister_1.py',
                'moving test/testproject_1/fromdir/testfilemover_1.py to '
                'testproject_1/projectdir/test/testfilemover_1.py',
                'moving test/testproject_1/fromdir/current_state_11.jpg to '
                'testproject_1/projectdir/images/current_state_11.jpg',
                'moving test/testproject_1/fromdir/current_state_12.jpg to '
                'testproject_1/projectdir/images/current_state_12.jpg',
                'moving test/testproject_1/fromdir/doc_11.docx to '
                'testproject_1/projectdir/doc/doc_11.docx',
                'moving test/testproject_1/fromdir/doc_12.docx to '
                'testproject_1/projectdir/doc/doc_12.docx',
                'moving test/testproject_1/fromdir/constants_1.py to '
                'test/testproject_1/projectdir/constants_1.py',
                'moving test/testproject_1/fromdir/filelister_1.py to '
                'test/testproject_1/projectdir/filelister_1.py',
                'moving test/testproject_1/fromdir/filemover_1.py to '
                'test/testproject_1/projectdir/filemover_1.py',
                'moving test/testproject_1/fromdir/README_1.md to '
                'test/testproject_1/projectdir/README_1.md', ''
            ],
                             outputCapturingString.getvalue().split('\n'))
        else:
            self.assertEqual([
                'moving test\\testproject_1\\fromdir\\testfilelister_1.py to '
                'testproject_1\\projectdir\\test\\testfilelister_1.py',
                'moving test\\testproject_1\\fromdir\\testfilemover_1.py to '
                'testproject_1\\projectdir\\test\\testfilemover_1.py',
                'moving test\\testproject_1\\fromdir\\current_state_11.jpg to '
                'testproject_1\\projectdir\\images\\current_state_11.jpg',
                'moving test\\testproject_1\\fromdir\\current_state_12.jpg to '
                'testproject_1\\projectdir\\images\\current_state_12.jpg',
                'moving test\\testproject_1\\fromdir\\doc_11.docx to '
                'testproject_1\\projectdir\\doc\\doc_11.docx',
                'moving test\\testproject_1\\fromdir\\doc_12.docx to '
                'testproject_1\\projectdir\\doc\\doc_12.docx',
                'moving test\\testproject_1\\fromdir\\constants_1.py to '
                'test\\testproject_1\\projectdir\\constants_1.py',
                'moving test\\testproject_1\\fromdir\\filelister_1.py to '
                'test\\testproject_1\\projectdir\\filelister_1.py',
                'moving test\\testproject_1\\fromdir\\filemover_1.py to '
                'test\\testproject_1\\projectdir\\filemover_1.py',
                'moving test\\testproject_1\\fromdir\\README_1.md to '
                'test\\testproject_1\\projectdir\\README_1.md', ''
            ],
                             outputCapturingString.getvalue().split('\n'))

        # verifying project dir
        fileNameLst = [
            x.split(sep)[-1] for x in glob.glob(projectDir + sep + '*.*')
        ]
        self.assertEqual(
            sorted([
                'filelister_1.py', 'filemover_1.py', 'constants_1.py',
                'README_1.md'
            ]), sorted(fileNameLst))

        # verifying project test sub dir
        fileNameLst = [
            x.split(sep)[-1]
            for x in glob.glob(projectDir + TEST_SUB_DIR + sep + '*.*')
        ]
        self.assertEqual(sorted(['testfilelister_1.py', 'testfilemover_1.py']),
                         sorted(fileNameLst))

        # verifying project images sub dir
        fileNameLst = [
            x.split(sep)[-1]
            for x in glob.glob(projectDir + IMG_SUB_DIR + sep + '*.*')
        ]
        self.assertEqual(
            sorted(['current_state_12.jpg', 'current_state_11.jpg']),
            sorted(fileNameLst))

        # verifying project doc sub dir
        fileNameLst = [
            x.split(sep)[-1]
            for x in glob.glob(projectDir + DOC_SUB_DIR + sep + '*.*')
        ]
        self.assertEqual(sorted(['doc_12.docx', 'doc_11.docx']),
                         sorted(fileNameLst))

        # testing that download no longer contains the files defined in cloudFileLst
        fileNameLst = [
            x.split(sep)[-1] for x in glob.glob(downloadDir + sep + '*.*')
        ]
        self.assertEqual(
            sorted([
                'constants_1.mp3',
                'Nikolay Rimsky-Korsakov - Отче наш   Notre Père   Our Father - Cep.mp3'
            ]), sorted(fileNameLst))
class FileMover:
	"""
	This class manages the physical moving of the files from the local
	download dir to the correct target dirs which depend on the file type or
	name pattern as defined in the local configuration file.
	"""
	def __init__(self, configManager, projectName):
		"""
		FileMover constructor.
		
		@param configManager: ConfigManager giving access to the local configuration
							  file data
		@param projectName: project name as defined in the local configuration
							file
		"""
		self.projectName = projectName
		self.downloadDir = configManager.downloadPath
		self.projectDir = configManager.getProjectLocalDir(projectName)
		self.fileNameLister = FileLister(configManager)

	def moveFilesToLocalDirs(self, cloudFileLst):
		"""
		This method performs the physical moving of the files from the local
		download dir to the correct target dirs which depend on the file type or
		name pattern as defined in the local configuration file.
		
		It uses a FileLister instance to obtain the required information for 
		transferring the files at their right destination.
		
		Here are an example of the two data structures returned by FileLister 
		and used by FileMover to transfer files in the adequate order at their 
		local destination:
			
		orderedFileTypeWildchardExprLst and fileTypeDic examples:
				
		['test*.py', 'aa*.jpg', '*.jpg', '*.docx', '*.py', '*.rd'], orderedFileTypeWildchardExprLst)

		{'*.jpg': ('/images', ['current_state_21.jpg', 'current_state_22.jpg']), 
		'*.docx': ('/doc', ['doc_21.docx', 'doc_22.docx']),
		'*.rd': ('/', ['README_2.rd']),
		'aa*.jpg': ('/images/aa', ['aa_current.jpg']),
		'test*.py': ('/test', ['testfilelister_2.py', 'testfilemover_2.py']),
		'*.py': ('/', ['constants_2.py', 'filelister_2.py', 'filemover_2.py'])}, fileTypeDic)

		@param cloudFileLst: list of files downloaded from the cloud to the download dir which
							 must be moved to their destination dir
		"""
		orderedFileTypeWildchardExprLst, fileTypeDic = self.fileNameLister.getFilesByOrderedTypes(self.projectName, cloudFileLst=cloudFileLst)

		try:
			for fileTypeWildchardExpr in orderedFileTypeWildchardExprLst:
				fileTypeEntryTuple = fileTypeDic[fileTypeWildchardExpr]
				destinationDir = self.projectDir + fileTypeEntryTuple[0]
				fileToMoveNameLst = fileTypeEntryTuple[1]

				for fileToMoveName in fileToMoveNameLst:
					fromFilePath = self.downloadDir + sep + fileToMoveName
					toFilePath = destinationDir + sep + fileToMoveName
					shutil.move(fromFilePath, toFilePath)
					fromFilePathShortened = self.shortenFileNamePath(fromFilePath)
					toFilePathShortened = self.shortenFileNamePath(toFilePath)
					print('moving {} to {}'.format(fromFilePathShortened, toFilePathShortened))
		except FileNotFoundError as e:
			pathElemLst = e.filename.split(sep)
			pathOnly = sep.join(pathElemLst[:-1])
			print('Destination dir {} does not exist. Program stopped.'.format(pathOnly))

	def shortenFileNamePath(self, completeFilePathName):
		"""
		This method shortens the full path file name string to make it more
		readable by the user. Here, the completeFilePathName is a fuLl file path
		name. In order to display a more readable file list, only the last 4 file
		pathName elements are kept.
		
		@param completeFilePathName: fuLl file path name
		"""
		filePathNameElementLst = completeFilePathName.split(sep)
		
		return sep.join(filePathNameElementLst[-4:])