summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwillmcgugan@gmail.com <willmcgugan@gmail.com@67cdc799-7952-0410-af00-57a81ceafa0f>2015-02-03 10:51:53 +0000
committerwillmcgugan@gmail.com <willmcgugan@gmail.com@67cdc799-7952-0410-af00-57a81ceafa0f>2015-02-03 10:51:53 +0000
commit1f3ed9f956c9f9eca3a4f19e5e6ad8bbd2368c32 (patch)
treef2ebfdca476196e53de68a8c16e10918984dce24
parenta61d85e3e97f4c8ef2c733416ec1e59de71ed2ff (diff)
downloadpyfilesystem-1f3ed9f956c9f9eca3a4f19e5e6ad8bbd2368c32.tar.gz
adde utils.copydir_progress method
git-svn-id: http://pyfilesystem.googlecode.com/svn/trunk@911 67cdc799-7952-0410-af00-57a81ceafa0f
-rw-r--r--CHANGES.txt3
-rw-r--r--fs/memoryfs.py2
-rw-r--r--fs/utils.py50
3 files changed, 53 insertions, 2 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index df34fd7..dab45a1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -89,7 +89,8 @@
* Added archivefs to fs.contrib, contributed by btimby
* Added some polish to fstree command and unicode box lines rather than ascii art
-0.5:
+0.5.1:
* Fixed a hang bug in readline
+ * Added copydir_progress to fs.utils
diff --git a/fs/memoryfs.py b/fs/memoryfs.py
index 9a87db3..cde0096 100644
--- a/fs/memoryfs.py
+++ b/fs/memoryfs.py
@@ -542,7 +542,7 @@ class MemoryFS(FS):
@synchronize
def _on_close_memory_file(self, open_file, path):
dir_entry = self._get_dir_entry(path)
- if dir_entry is not None:
+ if dir_entry is not None and open_file in dir_entry.open_files:
dir_entry.open_files.remove(open_file)
diff --git a/fs/utils.py b/fs/utils.py
index e0ab693..8fd6254 100644
--- a/fs/utils.py
+++ b/fs/utils.py
@@ -258,6 +258,56 @@ def copydir(fs1, fs2, create_destination=True, ignore_errors=False, chunk_size=6
chunk_size=chunk_size)
+def copydir_progress(progress_callback, fs1, fs2, create_destination=True, ignore_errors=False, chunk_size=64*1024):
+ """
+ Copies the contents of a directory from one fs to another, with a callback function to display progress.
+
+ `progress_callback` should be a function with two parameters; `step` and `num_steps`.
+
+ `num_steps` is the number of steps in the copy process, and `step` is the current step. `num_steps` may be None if the number
+ of steps is still being calculated.
+
+ """
+ if isinstance(fs1, tuple):
+ fs1, dir1 = fs1
+ fs1 = fs1.opendir(dir1)
+ if isinstance(fs2, tuple):
+ fs2, dir2 = fs2
+ if create_destination:
+ fs2.makedir(dir2, allow_recreate=True, recursive=True)
+ fs2 = fs2.opendir(dir2)
+
+ def do_callback(step, num_steps):
+ try:
+ progress_callback(step, num_steps)
+ except:
+ pass
+
+ do_callback(0, None)
+
+ file_count = 0
+ copy_paths = []
+ for dir_path, file_paths in fs1.walk():
+ copy_paths.append((dir_path, file_paths))
+ file_count += len(file_paths)
+ do_callback(0, file_count)
+
+ step = 0
+ for i, (dir_path, file_paths) in enumerate(copy_paths):
+ try:
+ fs2.makedir(dir_path, allow_recreate=True)
+ for path in file_paths:
+ copy_path = pathjoin(dir_path, path)
+ with fs1.open(copy_path, 'rb') as src_file:
+ fs2.setcontents(copy_path, src_file, chunk_size=chunk_size)
+ step += 1
+ except:
+ if ignore_errors:
+ continue
+ raise
+ do_callback(step, file_count)
+
+
def remove_all(fs, path):
"""Remove everything in a directory. Returns True if successful.