batchmp 1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- batchmp/__init__.py +0 -0
- batchmp/cli/__init__.py +0 -0
- batchmp/cli/base/__init__.py +0 -0
- batchmp/cli/base/bmp_dispatch.py +60 -0
- batchmp/cli/base/bmp_options.py +349 -0
- batchmp/cli/base/vchk.py +47 -0
- batchmp/cli/bmfp/__init__.py +0 -0
- batchmp/cli/bmfp/bmfp_dispatch.py +120 -0
- batchmp/cli/bmfp/bmfp_options.py +442 -0
- batchmp/cli/renamer/__init__.py +0 -0
- batchmp/cli/renamer/renamer_dispatch.py +135 -0
- batchmp/cli/renamer/renamer_options.py +355 -0
- batchmp/cli/tagger/__init__.py +0 -0
- batchmp/cli/tagger/tagger_dispatch.py +143 -0
- batchmp/cli/tagger/tagger_options.py +338 -0
- batchmp/commons/__init__.py +0 -0
- batchmp/commons/chainedhandler.py +102 -0
- batchmp/commons/descriptors.py +173 -0
- batchmp/commons/progressbar.py +154 -0
- batchmp/commons/taskprocessor.py +149 -0
- batchmp/commons/utils.py +194 -0
- batchmp/ffmptools/__init__.py +0 -0
- batchmp/ffmptools/ffcommands/__init__.py +0 -0
- batchmp/ffmptools/ffcommands/cmdopt.py +115 -0
- batchmp/ffmptools/ffcommands/convert.py +130 -0
- batchmp/ffmptools/ffcommands/cuesplit.py +223 -0
- batchmp/ffmptools/ffcommands/denoise.py +173 -0
- batchmp/ffmptools/ffcommands/fragment.py +121 -0
- batchmp/ffmptools/ffcommands/normalize_peak.py +135 -0
- batchmp/ffmptools/ffcommands/segment.py +157 -0
- batchmp/ffmptools/ffcommands/silencesplit.py +159 -0
- batchmp/ffmptools/ffrunner.py +189 -0
- batchmp/ffmptools/ffutils.py +300 -0
- batchmp/ffmptools/processors/__init__.py +0 -0
- batchmp/ffmptools/processors/basefp.py +92 -0
- batchmp/ffmptools/processors/ffentry.py +81 -0
- batchmp/ffmptools/utils/__init__.py +0 -0
- batchmp/ffmptools/utils/cueparse.py +227 -0
- batchmp/ffmptools/utils/cuesheet.py +239 -0
- batchmp/fstools/__init__.py +0 -0
- batchmp/fstools/builders/__init__.py +0 -0
- batchmp/fstools/builders/fsb.py +221 -0
- batchmp/fstools/builders/fsentry.py +60 -0
- batchmp/fstools/builders/fsprms.py +372 -0
- batchmp/fstools/dirtools.py +549 -0
- batchmp/fstools/fsutils.py +272 -0
- batchmp/fstools/rename.py +390 -0
- batchmp/fstools/walker.py +79 -0
- batchmp/tags/__init__.py +0 -0
- batchmp/tags/handlers/__init__.py +0 -0
- batchmp/tags/handlers/basehandler.py +99 -0
- batchmp/tags/handlers/ffmphandler.py +75 -0
- batchmp/tags/handlers/ffmphandlers/__init__.py +0 -0
- batchmp/tags/handlers/ffmphandlers/base.py +243 -0
- batchmp/tags/handlers/mtghandler.py +56 -0
- batchmp/tags/handlers/pmhandler.py +36 -0
- batchmp/tags/handlers/tagsholder.py +264 -0
- batchmp/tags/output/__init__.py +0 -0
- batchmp/tags/output/formatters.py +218 -0
- batchmp/tags/processors/__init__.py +0 -0
- batchmp/tags/processors/basetp.py +266 -0
- batchmp-1.4.dist-info/METADATA +422 -0
- batchmp-1.4.dist-info/RECORD +68 -0
- batchmp-1.4.dist-info/WHEEL +5 -0
- batchmp-1.4.dist-info/entry_points.txt +5 -0
- batchmp-1.4.dist-info/licenses/LICENSE +11 -0
- batchmp-1.4.dist-info/top_level.txt +1 -0
- batchmp-1.4.dist-info/zip-safe +1 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# coding=utf8
|
|
2
|
+
## Copyright (c) 2014 Arseniy Kuznetsov
|
|
3
|
+
##
|
|
4
|
+
## This program is free software; you can redistribute it and/or
|
|
5
|
+
## modify it under the terms of the GNU General Public License
|
|
6
|
+
## as published by the Free Software Foundation; either version 2
|
|
7
|
+
## of the License, or (at your option) any later version.
|
|
8
|
+
##
|
|
9
|
+
## This program is distributed in the hope that it will be useful,
|
|
10
|
+
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
## GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
from enum import IntEnum
|
|
16
|
+
|
|
17
|
+
class FSEntry:
|
|
18
|
+
''' File System entry representation
|
|
19
|
+
'''
|
|
20
|
+
def __init__(self, type, basename, realpath, indent,
|
|
21
|
+
isEnclosingEntry = False, isEnclosingFilesContainterEntry = False,
|
|
22
|
+
isScopeSwitchingEntry = False):
|
|
23
|
+
self.type = type
|
|
24
|
+
self.basename = basename
|
|
25
|
+
self.realpath = realpath
|
|
26
|
+
self.indent = indent
|
|
27
|
+
self.isEnclosingEntry = isEnclosingEntry
|
|
28
|
+
self.isEnclosingFilesContainterEntry = isEnclosingFilesContainterEntry
|
|
29
|
+
self.scopeSwitchingEntry = isScopeSwitchingEntry
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class FSEntryType(IntEnum):
|
|
33
|
+
ROOT = 0x00000
|
|
34
|
+
DIR = 0x00001
|
|
35
|
+
FILE = 0x00002
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class FSMediaEntryType(IntEnum):
|
|
39
|
+
IMAGE = 0x00010
|
|
40
|
+
AUDIO = 0x00011
|
|
41
|
+
VIDEO = 0x00012
|
|
42
|
+
NONMEDIA = 0x00013
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class FSMediaEntryGroupType(IntEnum):
|
|
46
|
+
MEDIA = 0x00100
|
|
47
|
+
PLAYABLE = 0x00101
|
|
48
|
+
NONPLAYABLE = 0x00102
|
|
49
|
+
ANY = 0x00103
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class FSEntryDefaults:
|
|
53
|
+
DEFAULT_NESTED_INDENT = ' '
|
|
54
|
+
DEFAULT_INCLUDE = '*'
|
|
55
|
+
DEFAULT_EXCLUDE = '.*' #exclude hidden files
|
|
56
|
+
DEFAULT_SORT = 'na'
|
|
57
|
+
DEFAULT_FILE_TYPE = 'any'
|
|
58
|
+
DEFAULT_MEDIA_TYPE = 'playable'
|
|
59
|
+
|
|
60
|
+
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# coding=utf8
|
|
2
|
+
## Copyright (c) 2014 Arseniy Kuznetsov
|
|
3
|
+
##
|
|
4
|
+
## This program is free software; you can redistribute it and/or
|
|
5
|
+
## modify it under the terms of the GNU General Public License
|
|
6
|
+
## as published by the Free Software Foundation; either version 2
|
|
7
|
+
## of the License, or (at your option) any later version.
|
|
8
|
+
##
|
|
9
|
+
## This program is distributed in the hope that it will be useful,
|
|
10
|
+
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
## GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
import os, sys, fnmatch, collections, pygtrie, heapq
|
|
16
|
+
from enum import IntEnum
|
|
17
|
+
from abc import ABCMeta, abstractmethod
|
|
18
|
+
from batchmp.fstools.fsutils import FSH
|
|
19
|
+
from batchmp.ffmptools.ffutils import FFH
|
|
20
|
+
from batchmp.fstools.builders.fsentry import FSEntryDefaults, FSMediaEntryType, FSMediaEntryGroupType
|
|
21
|
+
from batchmp.commons.descriptors import (
|
|
22
|
+
PropertyDescriptor,
|
|
23
|
+
LazyFunctionPropertyDescriptor,
|
|
24
|
+
LazyClassPropertyDescriptor,
|
|
25
|
+
FunctionPropertyDescriptor,
|
|
26
|
+
BooleanPropertyDescriptor)
|
|
27
|
+
|
|
28
|
+
# FSEntry Attributes with default values
|
|
29
|
+
class FSEntryDefaultValueDescriptor(LazyFunctionPropertyDescriptor):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
# FSEntry Attributes with default values
|
|
33
|
+
class FSEntryRuntimeAttributeDescriptor(PropertyDescriptor):
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class FSEntryFilteredFilesValueDescriptor(FSEntryRuntimeAttributeDescriptor):
|
|
38
|
+
''' Files property descriptor
|
|
39
|
+
'''
|
|
40
|
+
def __set__(self, instance, value):
|
|
41
|
+
if isinstance(instance, FSEntryParamsBase):
|
|
42
|
+
# filtering
|
|
43
|
+
if instance.filter_files:
|
|
44
|
+
fnames = [fname for fname in value if instance.passed_filters(fname)]
|
|
45
|
+
else:
|
|
46
|
+
fnames = [fname for fname in value]
|
|
47
|
+
|
|
48
|
+
# file types
|
|
49
|
+
if instance.file_type != FSMediaEntryGroupType.ANY:
|
|
50
|
+
fnames = [fname for fname in fnames if instance.is_of_required_type(os.path.join(instance.rpath, fname))]
|
|
51
|
+
|
|
52
|
+
# sorting
|
|
53
|
+
if instance.by_size:
|
|
54
|
+
sort_key = lambda fname: os.path.getsize(os.path.join(instance.rpath, fname))
|
|
55
|
+
else:
|
|
56
|
+
sort_key = lambda fname: fname.lower()
|
|
57
|
+
fnames.sort(key = sort_key, reverse = instance.descending)
|
|
58
|
+
# set value
|
|
59
|
+
super().__set__(instance, fnames)
|
|
60
|
+
else:
|
|
61
|
+
raise TypeError("Not a FSEntryParamsBase Type: {}".format(instance.__class__))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
DNames = collections.namedtuple('DNames', ['passed', 'enclosing'])
|
|
65
|
+
class FSEntryFilteredDirsValueDescriptor(FSEntryRuntimeAttributeDescriptor):
|
|
66
|
+
''' Directories property descriptor
|
|
67
|
+
'''
|
|
68
|
+
def __set__(self, instance, value):
|
|
69
|
+
if isinstance(instance, FSEntryParamsBase):
|
|
70
|
+
passed_dnames, enclosing_dnames = [], []
|
|
71
|
+
# filtering
|
|
72
|
+
if instance.filter_dirs:
|
|
73
|
+
for dname in value:
|
|
74
|
+
if instance.file_type == FSMediaEntryGroupType.ANY and instance.passed_filters(dname):
|
|
75
|
+
passed_dnames.append(dname)
|
|
76
|
+
elif instance.scan_for_enclosing_directories:
|
|
77
|
+
en_dname = os.path.join(instance.rpath, dname)
|
|
78
|
+
if instance._enclosing_dnames.has_node(en_dname):
|
|
79
|
+
enclosing_dnames.append(dname)
|
|
80
|
+
else:
|
|
81
|
+
passed_dnames = [dname for dname in value]
|
|
82
|
+
# sorting
|
|
83
|
+
if instance.by_size:
|
|
84
|
+
dirs_sort_key = lambda dname: FSH.dir_size(os.path.join(instance.rpath, dname))
|
|
85
|
+
else:
|
|
86
|
+
dirs_sort_key = lambda dname: dname.lower()
|
|
87
|
+
passed_dnames.sort(key = dirs_sort_key, reverse = instance.descending)
|
|
88
|
+
enclosing_dnames.sort(key = dirs_sort_key, reverse = instance.descending)
|
|
89
|
+
super().__set__(instance, DNames(passed_dnames, enclosing_dnames))
|
|
90
|
+
else:
|
|
91
|
+
raise TypeError("Not a FSEntryParamsBase Type: {}".format(instance.__class__))
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class FSEntryRPathDescriptor(FSEntryRuntimeAttributeDescriptor):
|
|
96
|
+
''' RPath property descriptor
|
|
97
|
+
'''
|
|
98
|
+
def __set__(self, instance, value):
|
|
99
|
+
if isinstance(instance, FSEntryParamsBase):
|
|
100
|
+
super().__set__(instance, FSH.full_path(value))
|
|
101
|
+
else:
|
|
102
|
+
raise TypeError("Not a FSEntryParamsBase Type: {}".format(instance.__class__))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class FSEntryFileTypeDescriptor(PropertyDescriptor):
|
|
106
|
+
''' RPath property descriptor
|
|
107
|
+
'''
|
|
108
|
+
def __set__(self, instance, value):
|
|
109
|
+
if isinstance(instance, FSEntryParamsBase):
|
|
110
|
+
file_types_map = {
|
|
111
|
+
'image': FSMediaEntryType.IMAGE,
|
|
112
|
+
'video': FSMediaEntryType.VIDEO,
|
|
113
|
+
'audio': FSMediaEntryType.AUDIO,
|
|
114
|
+
'nonmedia': FSMediaEntryType.NONMEDIA,
|
|
115
|
+
'playable': FSMediaEntryGroupType.PLAYABLE,
|
|
116
|
+
'nonplayable': FSMediaEntryGroupType.NONPLAYABLE,
|
|
117
|
+
'media': FSMediaEntryGroupType.MEDIA,
|
|
118
|
+
'any': FSMediaEntryGroupType.ANY
|
|
119
|
+
}
|
|
120
|
+
super().__set__(instance, file_types_map.get(value, FSMediaEntryGroupType.ANY))
|
|
121
|
+
else:
|
|
122
|
+
raise TypeError("Not a FSEntryParamsBase Type: {}".format(instance.__class__))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class FSEntryParamsBase():
|
|
127
|
+
''' Base Entry attributes
|
|
128
|
+
'''
|
|
129
|
+
src_dir = PropertyDescriptor()
|
|
130
|
+
|
|
131
|
+
start_level = PropertyDescriptor()
|
|
132
|
+
end_level = PropertyDescriptor()
|
|
133
|
+
|
|
134
|
+
filter_dirs = BooleanPropertyDescriptor()
|
|
135
|
+
filter_files = BooleanPropertyDescriptor()
|
|
136
|
+
show_size = BooleanPropertyDescriptor()
|
|
137
|
+
|
|
138
|
+
include = PropertyDescriptor()
|
|
139
|
+
exclude = PropertyDescriptor()
|
|
140
|
+
nested_indent = PropertyDescriptor()
|
|
141
|
+
sort = PropertyDescriptor()
|
|
142
|
+
file_type = FSEntryFileTypeDescriptor()
|
|
143
|
+
media_scan = BooleanPropertyDescriptor()
|
|
144
|
+
|
|
145
|
+
fs_entry_builder = LazyClassPropertyDescriptor('batchmp.fstools.builders.fsb.FSEntryBuilderBase')
|
|
146
|
+
'''Runtime attrbutes
|
|
147
|
+
'''
|
|
148
|
+
rpath = FSEntryRPathDescriptor()
|
|
149
|
+
fnames = FSEntryFilteredFilesValueDescriptor()
|
|
150
|
+
dnames = FSEntryFilteredDirsValueDescriptor()
|
|
151
|
+
|
|
152
|
+
def __init__(self, args = {}):
|
|
153
|
+
self.src_dir = args.get('dir')
|
|
154
|
+
self.start_level = args.get('start_level', 0)
|
|
155
|
+
self.end_level = args.get('end_level', sys.maxsize)
|
|
156
|
+
self.nested_indent = args.get('nested_indent', FSEntryDefaults.DEFAULT_NESTED_INDENT)
|
|
157
|
+
self.include = args.get('include', FSEntryDefaults.DEFAULT_INCLUDE)
|
|
158
|
+
self.exclude = args.get('exclude', FSEntryDefaults.DEFAULT_EXCLUDE)
|
|
159
|
+
self.file_type = args.get('file_type', FSEntryDefaults.DEFAULT_FILE_TYPE)
|
|
160
|
+
self.sort = args.get('sort', FSEntryDefaults.DEFAULT_SORT)
|
|
161
|
+
self.filter_dirs = not args.get('all_dirs', False)
|
|
162
|
+
self.filter_files = not args.get('all_files', False)
|
|
163
|
+
self.show_size = args.get('show_size', False)
|
|
164
|
+
self.fast_scan = not args.get('media_scan', False)
|
|
165
|
+
|
|
166
|
+
#self._media_extensions_cache = set()
|
|
167
|
+
|
|
168
|
+
# enclosing directores
|
|
169
|
+
self._enclosing_dnames = pygtrie.StringTrie(separator=os.path.sep)
|
|
170
|
+
self._enclosing_files_containters = set()
|
|
171
|
+
if self.scan_for_enclosing_directories:
|
|
172
|
+
for rpath, dirs, files in os.walk(self.src_dir):
|
|
173
|
+
if FSH.level_from_root(self.src_dir, rpath) < self.end_level:
|
|
174
|
+
marked_enclosing = False
|
|
175
|
+
for dir_name in dirs:
|
|
176
|
+
if self.file_type == FSMediaEntryGroupType.ANY and self.passed_filters(dir_name):
|
|
177
|
+
self._enclosing_dnames[rpath] = rpath
|
|
178
|
+
marked_enclosing = True
|
|
179
|
+
break # no need to check this root further
|
|
180
|
+
for file_name in files:
|
|
181
|
+
if self.passed_filters(file_name) and self.is_of_required_type(os.path.join(rpath,file_name)):
|
|
182
|
+
if not marked_enclosing:
|
|
183
|
+
self._enclosing_dnames[rpath] = rpath
|
|
184
|
+
self._enclosing_files_containters.add(rpath)
|
|
185
|
+
break # no need to check this root further
|
|
186
|
+
#print(self.file_type)
|
|
187
|
+
#print('Enclosing: {}'.format(self._enclosing_dnames))
|
|
188
|
+
#print('Enclosing File Containers: {}'.format(self._enclosing_files_containters))
|
|
189
|
+
|
|
190
|
+
# Current level
|
|
191
|
+
@property
|
|
192
|
+
def current_level(self):
|
|
193
|
+
return FSH.level_from_root(self.src_dir, self.rpath)
|
|
194
|
+
|
|
195
|
+
# Sorting
|
|
196
|
+
@property
|
|
197
|
+
def descending(self):
|
|
198
|
+
return True if self.sort.endswith('d') else False
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def by_size(self):
|
|
202
|
+
return True if self.sort.startswith('s') else False
|
|
203
|
+
|
|
204
|
+
# Filtering
|
|
205
|
+
@property
|
|
206
|
+
def passed_filters(self):
|
|
207
|
+
def include_match(fsname):
|
|
208
|
+
for include_pattern in self.include.split(';'):
|
|
209
|
+
if fnmatch.fnmatch(fsname, include_pattern):
|
|
210
|
+
return True
|
|
211
|
+
return False
|
|
212
|
+
|
|
213
|
+
def exclude_match(fsname):
|
|
214
|
+
for exclude_pattern in self.exclude.split(';'):
|
|
215
|
+
if fnmatch.fnmatch(fsname, exclude_pattern):
|
|
216
|
+
return True
|
|
217
|
+
return False
|
|
218
|
+
|
|
219
|
+
return lambda fs_name: include_match(fs_name) and (not exclude_match(fs_name))
|
|
220
|
+
|
|
221
|
+
def is_of_entry_type(self, media_type):
|
|
222
|
+
return {
|
|
223
|
+
FSMediaEntryGroupType.ANY: True,
|
|
224
|
+
FSMediaEntryType.IMAGE: media_type == FSMediaEntryType.IMAGE,
|
|
225
|
+
FSMediaEntryType.VIDEO: media_type == FSMediaEntryType.VIDEO,
|
|
226
|
+
FSMediaEntryType.AUDIO: media_type == FSMediaEntryType.AUDIO,
|
|
227
|
+
FSMediaEntryGroupType.PLAYABLE: media_type in (FSMediaEntryType.VIDEO, FSMediaEntryType.AUDIO),
|
|
228
|
+
FSMediaEntryGroupType.NONPLAYABLE: media_type not in (FSMediaEntryType.VIDEO, FSMediaEntryType.AUDIO),
|
|
229
|
+
FSMediaEntryGroupType.MEDIA: media_type in (FSMediaEntryType.IMAGE, FSMediaEntryType.VIDEO, FSMediaEntryType.AUDIO),
|
|
230
|
+
FSMediaEntryType.NONMEDIA: media_type not in (FSMediaEntryType.IMAGE, FSMediaEntryType.VIDEO, FSMediaEntryType.AUDIO)
|
|
231
|
+
}[self.file_type]
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def is_of_required_type(self, fpath):
|
|
235
|
+
media_type = FFH.media_type(fpath = fpath, fast_scan = self.fast_scan)
|
|
236
|
+
return self.is_of_entry_type(media_type)
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def scan_for_enclosing_directories(self):
|
|
240
|
+
return self. filter_dirs and (self.file_type != FSMediaEntryGroupType.ANY or self.include != FSEntryDefaults.DEFAULT_INCLUDE) and self.end_level > 0
|
|
241
|
+
|
|
242
|
+
@property
|
|
243
|
+
def skip_iteration(self):
|
|
244
|
+
return True if (self.current_level < self.start_level) or (self.current_level > self.end_level) else False
|
|
245
|
+
|
|
246
|
+
@property
|
|
247
|
+
def end_iteration(self):
|
|
248
|
+
return True if self.current_level > self.end_level else False
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def current_indent(self):
|
|
252
|
+
return '{0}{1}'.format(self.nested_indent * (self.current_level), '|-> ' if not (self.isEnclosingEntry) else '|.. ')
|
|
253
|
+
|
|
254
|
+
@property
|
|
255
|
+
def siblings_indent(self):
|
|
256
|
+
return '{0}{1}'.format(self.nested_indent * (self.current_level + 1), '|- ')
|
|
257
|
+
|
|
258
|
+
@property
|
|
259
|
+
def merged_dnames(self):
|
|
260
|
+
return list(heapq.merge(self.dnames.passed, self.dnames.enclosing, reverse = self.descending))
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def isEnclosingEntry(self):
|
|
264
|
+
return self._enclosing_dnames.has_node(self.rpath) and not self.isMatchingDirEntry
|
|
265
|
+
|
|
266
|
+
@property
|
|
267
|
+
def isMatchingDirEntry(self):
|
|
268
|
+
dir_name = os.path.basename(self.rpath)
|
|
269
|
+
return self.file_type == FSMediaEntryGroupType.ANY and self.passed_filters(dir_name)
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def isEnclosingFilesContainterEntry(self):
|
|
273
|
+
return self.rpath in self._enclosing_files_containters
|
|
274
|
+
|
|
275
|
+
@property
|
|
276
|
+
def args(self):
|
|
277
|
+
return self._args
|
|
278
|
+
|
|
279
|
+
@classmethod
|
|
280
|
+
def writable_fields(cls):
|
|
281
|
+
''' generates names of all writable tag fields
|
|
282
|
+
'''
|
|
283
|
+
for c in cls.__mro__:
|
|
284
|
+
for field, descr in vars(c).items():
|
|
285
|
+
if isinstance(descr, LazyClassPropertyDescriptor):
|
|
286
|
+
continue
|
|
287
|
+
if isinstance(descr, BooleanPropertyDescriptor):
|
|
288
|
+
yield field
|
|
289
|
+
elif isinstance(descr, PropertyDescriptor):
|
|
290
|
+
yield field
|
|
291
|
+
|
|
292
|
+
@classmethod
|
|
293
|
+
def runtime_attributes(cls):
|
|
294
|
+
''' generates names of all runtime fields
|
|
295
|
+
'''
|
|
296
|
+
for c in cls.__mro__:
|
|
297
|
+
for field, descr in vars(c).items():
|
|
298
|
+
if isinstance(descr, FSEntryRuntimeAttributeDescriptor):
|
|
299
|
+
yield field
|
|
300
|
+
|
|
301
|
+
# Copy attributes from another entry
|
|
302
|
+
def copy_params(self, fs_entry_params):
|
|
303
|
+
self._enclosing_dnames = fs_entry_params._enclosing_dnames
|
|
304
|
+
self._enclosing_files_containters = fs_entry_params._enclosing_files_containters
|
|
305
|
+
for field in self.writable_fields():
|
|
306
|
+
value = getattr(fs_entry_params, field)
|
|
307
|
+
if value is not None:
|
|
308
|
+
setattr(self, field, value)
|
|
309
|
+
|
|
310
|
+
def reset_runtime(self):
|
|
311
|
+
for field in self.runtime_attributes():
|
|
312
|
+
setattr(self, field, [])
|
|
313
|
+
|
|
314
|
+
def __str__(self):
|
|
315
|
+
return ('Entry of type: {}\n'.format(self.__class__.__name__) + \
|
|
316
|
+
'\n '.join('{}: {}'.format(key, value) for key, value in vars(self).items()))
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
class FSEntryParamsExt(FSEntryParamsBase):
|
|
321
|
+
display_current = BooleanPropertyDescriptor()
|
|
322
|
+
include_dirs = BooleanPropertyDescriptor()
|
|
323
|
+
include_files = BooleanPropertyDescriptor()
|
|
324
|
+
quiet = BooleanPropertyDescriptor()
|
|
325
|
+
|
|
326
|
+
def __init__(self, args = {}):
|
|
327
|
+
super().__init__(args)
|
|
328
|
+
self.display_current = args.get('display_current', False)
|
|
329
|
+
self.include_dirs = args.get('include_dirs', False)
|
|
330
|
+
self.include_files = not args.get('exclude_files', False)
|
|
331
|
+
self.quiet = args.get('quiet', False)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
class FSEntryParamsFlatten(FSEntryParamsExt):
|
|
335
|
+
''' Flatten Entry attributes
|
|
336
|
+
'''
|
|
337
|
+
fs_entry_builder = LazyClassPropertyDescriptor('batchmp.fstools.builders.fsb.FSEntryBuilderFlatten')
|
|
338
|
+
|
|
339
|
+
target_level = PropertyDescriptor()
|
|
340
|
+
remove_folders = BooleanPropertyDescriptor()
|
|
341
|
+
remove_non_empty_folders = BooleanPropertyDescriptor()
|
|
342
|
+
unique_fnames = FunctionPropertyDescriptor()
|
|
343
|
+
non_empty_folders_mgs = PropertyDescriptor
|
|
344
|
+
|
|
345
|
+
def __init__(self, args = {}):
|
|
346
|
+
super().__init__(args)
|
|
347
|
+
self.remove_folders = False if args.get('discard_flattened') == 'le' else True
|
|
348
|
+
self.remove_non_empty_folders = True if args.get('discard_flattened') == 'da' else False
|
|
349
|
+
self.unique_fnames = args.get('unique_fnames', FSH.unique_fnames)
|
|
350
|
+
|
|
351
|
+
self.non_empty_folders_mgs = 'Use --discard-flattened parameter to remove non empty folders'
|
|
352
|
+
|
|
353
|
+
self.target_level = args.get('target_level', 0)
|
|
354
|
+
if self.end_level < self.target_level:
|
|
355
|
+
self.end_level = self.target_level
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
class FSEntryParamsOrganize(FSEntryParamsExt):
|
|
360
|
+
''' Organize Entry attributes
|
|
361
|
+
'''
|
|
362
|
+
fs_entry_builder = LazyClassPropertyDescriptor('batchmp.fstools.builders.fsb.FSEntryBuilderOrganizeWorker')
|
|
363
|
+
|
|
364
|
+
by = PropertyDescriptor()
|
|
365
|
+
date_format = PropertyDescriptor()
|
|
366
|
+
target_dir = PropertyDescriptor()
|
|
367
|
+
|
|
368
|
+
def __init__(self, args = {}):
|
|
369
|
+
super().__init__(args)
|
|
370
|
+
self.by = args.get('by')
|
|
371
|
+
self.date_format = args.get('date_format')
|
|
372
|
+
self.target_dir = args.get('target_dir')
|