Compare commits

...

5 commits

4 changed files with 56 additions and 16 deletions

View file

@ -362,6 +362,22 @@ class Path:
items = [self.with_child(c, _case_correct=self._case_correct) for c in children] items = [self.with_child(c, _case_correct=self._case_correct) for c in children]
return items return items
def glob_many(self, patterns):
'''
Given many glob patterns, yield the results as a single generator.
Saves you from having to write the nested loop.
'''
for pattern in patterns:
yield from self.glob(pattern)
def glob_many_directories(self, patterns):
for pattern in patterns:
yield from self.glob_directories(pattern)
def glob_many_files(self, patterns):
for pattern in patterns:
yield from self.glob_files(pattern)
@property @property
def is_directory(self): def is_directory(self):
return os.path.isdir(self) return os.path.isdir(self)

View file

@ -129,7 +129,7 @@ class Bar1(Progress):
if width is WIDTH_AUTO: if width is WIDTH_AUTO:
self.width = shutil.get_terminal_size().columns - 2 self.width = shutil.get_terminal_size().columns - 2
self.width = min(80, self.width) self.width = min(120, self.width)
else: else:
self.width = width self.width = width

View file

@ -81,6 +81,7 @@ def copy_directory(
file_progressbar=None, file_progressbar=None,
files_per_second=None, files_per_second=None,
hash_class=None, hash_class=None,
lock_files=True,
overwrite=OVERWRITE_OLD, overwrite=OVERWRITE_OLD,
precalcsize=False, precalcsize=False,
skip_symlinks=True, skip_symlinks=True,
@ -160,6 +161,9 @@ def copy_directory(
hash_class: hash_class:
Passed into each `copy_file` as `hash_class`. Passed into each `copy_file` as `hash_class`.
lock_files:
Passed into each `copy_file` as `lock_files`.
overwrite: overwrite:
Passed into each `copy_file` as `overwrite`. Passed into each `copy_file` as `overwrite`.
@ -304,6 +308,7 @@ def copy_directory(
chunk_size=chunk_size, chunk_size=chunk_size,
dry_run=dry_run, dry_run=dry_run,
hash_class=hash_class, hash_class=hash_class,
lock_files=lock_files,
overwrite=overwrite, overwrite=overwrite,
progressbar=file_progressbar, progressbar=file_progressbar,
verify_hash=verify_hash, verify_hash=verify_hash,
@ -345,6 +350,7 @@ def copy_file(
destination_new_root=None, destination_new_root=None,
dry_run=False, dry_run=False,
hash_class=None, hash_class=None,
lock_files=True,
overwrite=OVERWRITE_OLD, overwrite=OVERWRITE_OLD,
progressbar=None, progressbar=None,
verify_hash=False, verify_hash=False,
@ -400,6 +406,11 @@ def copy_file(
needing overwrite, this won't be set, so be prepared to handle None. needing overwrite, this won't be set, so be prepared to handle None.
If None, the hash will not be calculated. If None, the hash will not be calculated.
lock_files:
If True, attempt to lock the source file and destination file while we
are copying it, to prevent corruption. Only works if portalocker is
installed.
overwrite: overwrite:
This option decides what to do when the destination file already exists. This option decides what to do when the destination file already exists.
If OVERWRITE_ALL, the file will be overwritten. If OVERWRITE_ALL, the file will be overwritten.
@ -484,8 +495,22 @@ def copy_file(
def handlehelper(path, mode): def handlehelper(path, mode):
try: try:
handle = path.open(mode) if lock_files and portalocker is not None:
return handle log.loud(f'Locking {path.absolute_path}.')
lock = portalocker.Lock(
path.absolute_path,
mode=mode,
flags=portalocker.LockFlags.EXCLUSIVE | portalocker.LockFlags.NON_BLOCKING,
timeout=10,
)
handle = lock.acquire()
return (handle, lock)
else:
lock = None
handle = path.open(mode)
return (handle, lock)
except portalocker.exceptions.LockException:
raise
except PermissionError as exception: except PermissionError as exception:
if callback_permission_denied is not None: if callback_permission_denied is not None:
callback_permission_denied(exception) callback_permission_denied(exception)
@ -495,19 +520,20 @@ def copy_file(
log.loud('Copying file %s', source.absolute_path) log.loud('Copying file %s', source.absolute_path)
log.loud('Opening source handle.') log.loud('Opening source handle.')
source_handle = handlehelper(source, 'rb') (source_handle, source_lock) = handlehelper(source, 'rb')
if source_handle is None: if source_handle is None:
return results return results
if portalocker is not None:
log.loud('Locking source file.')
portalocker.lock(source_handle, portalocker.LockFlags.EXCLUSIVE)
log.loud('Opening dest handle.') log.loud('Opening dest handle.')
destination_handle = handlehelper(destination, 'wb') if destination.is_file:
os.chmod(destination.absolute_path, 0o777)
(destination_handle, destination_lock) = handlehelper(destination, 'wb')
if destination_handle is None: if destination_handle is None:
if source_lock:
source_lock.release()
source_handle.close() source_handle.close()
return results return results
os.utime(destination.absolute_path, (315600000, 315600000))
if hash_class is not None: if hash_class is not None:
results.hash = hash_class() results.hash = hash_class()
@ -550,8 +576,11 @@ def copy_file(
chunk_time = time.perf_counter() - chunk_start chunk_time = time.perf_counter() - chunk_start
chunk_size = dynamic_chunk_sizer(chunk_size, chunk_time, IDEAL_CHUNK_TIME) chunk_size = dynamic_chunk_sizer(chunk_size, chunk_time, IDEAL_CHUNK_TIME)
if portalocker is not None: if source_lock is not None:
portalocker.unlock(source_handle) source_lock.release()
if destination_lock is not None:
destination_lock.release()
progressbar.done() progressbar.done()

View file

@ -5,11 +5,6 @@ def getpid(process_name):
pids = [] pids = []
target = process_name.lower() target = process_name.lower()
for process in psutil.process_iter(): for process in psutil.process_iter():
# print(dir(process))
try:
print(process.cmdline())
except:
pass
if process.name().lower() == target: if process.name().lower() == target:
pids.append(process.pid) pids.append(process.pid)
return pids return pids