[issue13033] Add shutil.chowntree

2011-12-25 Thread Tigger Level-5

Tigger Level-5 a.wild.tig...@gmail.com added the comment:

Hi Éric,

Apologies for the late response, attached is the patch. Let me know if
I need any changes or anything else.

Best,
Tigger

On Sat, Nov 5, 2011 at 11:01 AM, Éric Araujo rep...@bugs.python.org wrote:

 Éric Araujo mer...@netwok.org added the comment:

 Tigger: Could you provide a patch for Python 3.3? (more info at 
 http://docs.python.org/devguide/)

 --

 ___
 Python tracker rep...@bugs.python.org
 http://bugs.python.org/issue13033
 ___

--
keywords: +patch
Added file: http://bugs.python.org/file24091/chowntree.patch

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue13033
___diff -r 2b47f0146639 Doc/library/shutil.rst
--- a/Doc/library/shutil.rstSun Sep 25 17:36:31 2011 +0200
+++ b/Doc/library/shutil.rstMon Sep 26 17:18:43 2011 -0500
@@ -196,6 +196,33 @@
 
.. versionadded:: 3.3
 
+.. function:: chowntree(path, user=None, group=None, followlinks=False)
+
+   Change owner *user* and/or *group* of the given *path* and all contents 
recursively.
+
+   *user* can be a system user name or a uid; the same applies to *group*. At
+   least one argument is required.
+
+   See also :func:`os.chown` and :func:`os.walk`, the underlying functions.
+
+   By default, :func:`walk` will not walk down into symbolic links that 
resolve to
+   directories. Set *followlinks* to ``True`` to visit directories pointed to 
by
+   symlinks, on systems that support them.
+
+   .. note::
+
+  Be aware that setting *followlinks* to ``True`` can lead to infinite 
recursion if a
+  link points to a parent directory of itself. This is due to the fact 
that the underlying
+  function :func:`os.walk` does not keep track of
+  the directories it visited already.
+
+   .. note::
+
+  If there is an error with the underlying :func:`os.walk` method, then 
any files whose
+  ownership was successfully changed will be reverted back to the original 
ownership.
+
+   Availability: Unix.
+
 
 .. exception:: Error
 
diff -r 2b47f0146639 Lib/shutil.py
--- a/Lib/shutil.py Sun Sep 25 17:36:31 2011 +0200
+++ b/Lib/shutil.py Mon Sep 26 17:18:43 2011 -0500
@@ -822,3 +822,57 @@
 raise LookupError(no such group: {!r}.format(group))
 
 os.chown(path, _user, _group)
+
+
+def chowntree(path, user=None, group=None, followlinks=False):
+Change owner user and group of the given path and all contents 
recursively.
+
+user and group can be the uid/gid or the user/group names, and in that 
case,
+they are converted to their respective uid/gid. followlinks tells us 
whether we should
+follow symlinks. This may lead to infinite recursion if links loop back.
+
+The dictionary _modified_items, will keep track of the old ownership 
details,
+with keys being the full path, and values being tuples where the first 
element is
+the uid and the second element is the gid. This way if there are any 
errors that
+arise, we can undo any ownership changes to the old state.
+
+
+
+if user is None and group is None:
+raise ValueError(user and/or group must be set)
+
+_user = user
+_group = group
+
+# -1 means don't change it
+if user is None:
+_user = -1
+# user can either be an int (the uid) or a string (the system username)
+elif isinstance(user, str):
+_user = _get_uid(user)
+if _user is None:
+raise LookupError(no such user: {!r}.format(user))
+
+if group is None:
+_group = -1
+elif not isinstance(group, int):
+_group = _get_gid(group)
+if _group is None:
+raise LookupError(no such group: {!r}.format(group))
+
+
+_modified_items = dict()
+def _listdir_errorhandler(oserror):
+for path, stat in _modified_items.items():
+os.chown(path, stat.st_uid, stat.st_gid)
+raise oserror
+
+if(os.path.isdir(path)):
+for root, dirs, files in os.walk(path, onerror = 
_listdir_errorhandler, followlinks = followlinks):
+for item in (files + dirs):
+_full_file_path = os.path.join(root, item)
+
+stat_info = os.stat(_full_file_path)
+os.chown(_full_file_path, _user, _group)
+_modified_items[_full_file_path] = (stat_info.st_uid, 
stat_info.st_gid)
+
+os.chown(path, _user, _group)
diff -r 2b47f0146639 Lib/test/test_shutil.py
--- a/Lib/test/test_shutil.py   Sun Sep 25 17:36:31 2011 +0200
+++ b/Lib/test/test_shutil.py   Mon Sep 26 17:18:43 2011 -0500
@@ -770,6 +770,50 @@
 check_chown(filename, uid, gid)
 shutil.chown(dirname, user, group)
 check_chown(dirname, uid, gid)
+
+
+@unittest.skipUnless(UID_GID_SUPPORT, Requires grp and pwd support)
+@unittest.skipUnless(hasattr(os, 'chown

[issue13033] Add shutil.chowntree

2011-09-24 Thread Tigger Level-5

Tigger Level-5 a.wild.tig...@gmail.com added the comment:

First time posting, how about something like this. Just added a os.walk method 
to do the chown recursively.

--
nosy: +Tigger.Level-5
Added file: http://bugs.python.org/file23240/temp.py

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue13033
___
___
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com