Antoine Pitrou avatar Antoine Pitrou committed 59b1cff

Add mkdir()

Comments (0)

Files changed (3)

    the symbolic link's information rather than its target's.
 
 
+.. method:: Path.mkdir(mode=0o777, parents=False)
+
+   Create a new directory at this given path.  If *mode* is given, it is
+   combined with the process' ``umask`` value to determine the file mode
+   and access flags.  If the path already exists, :exc:`OSError` is raised.
+
+   If *parents* is True, any missing parents of this path are created
+   as needed.  If *parents* is False (the default), a missing parent raises
+   :exc:`OSError`.
+
+
 .. method:: Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)
 
    Open the file pointed to by the path, like the built-in :func:`open`
 
    Create a file at this given path.  If *mode* is given, it is combined
    with the process' ``umask`` value to determine the file mode and access
-   flags.  If the file already exists, the function is a no-op if *exist_ok*
+   flags.  If the file already exists, the function succeeds if *exist_ok*
    is true, otherwise :exc:`OSError` is raised.
 
 
 
 # We need all of these
 _at_functions = [
-    'fchmodat', 'fdlistdir', 'fstatat', 'openat', 'readlinkat', 'renameat',
-    'symlinkat', 'unlinkat',
+    'fchmodat', 'fdlistdir', 'fstatat', 'mkdirat', 'openat', 'readlinkat',
+    'renameat', 'symlinkat', 'unlinkat',
     ]
 supports_openat = all(hasattr(os, fn) for fn in _at_functions)
 
         def lchmod(self, pathobj, mode):
             return self.chmod(pathobj, mode, _AT_SYMLINK_NOFOLLOW)
 
+        mkdir = _wrap_atfunc(os.mkdirat)
+
         unlink = _wrap_atfunc(os.unlinkat)
 
         def rmdir(self, pathobj):
         def lchmod(self, pathobj, mode):
             raise NotImplementedError("lchmod() not available on this system")
 
+    mkdir = _wrap_strfunc(os.mkdir)
+
     unlink = _wrap_strfunc(os.unlink)
 
     rmdir = _wrap_strfunc(os.rmdir)
         """
         Create this file with the given access mode, if it doesn't exist.
         """
+        if self._closed:
+            self._raise_closed()
         flags = os.O_CREAT
         if not exist_ok:
             flags |= os.O_EXCL
         fd = self.raw_open(flags, mode)
         os.close(fd)
 
+    def mkdir(self, mode=0o777, parents=False):
+        if self._closed:
+            self._raise_closed()
+        if not parents:
+            self._accessor.mkdir(self, mode)
+        else:
+            try:
+                self._accessor.mkdir(self, mode)
+            except OSError as e:
+                if e.errno != ENOENT:
+                    raise
+                self.parent().mkdir(mode, True)
+                self._accessor.mkdir(self, mode)
+
     def chmod(self, mode):
         """
         Change the permissions of the path, like os.chmod().
 class _BasePathTest(unittest.TestCase):
     """Tests for the FS-accessing functionalities of the Path classes."""
 
+    using_openat = False
+
     def setUp(self):
         os.mkdir(BASE)
         self.addCleanup(support.rmtree, BASE)
         p.touch(mode=0o700, exist_ok=False)
         self.assertTrue(p.exists())
         self.assertRaises(OSError, p.touch, exist_ok=False)
+        # XXX better test `mode` arg
+
+    def test_mkdir(self):
+        P = self.cls(BASE)
+        p = P['newdirA']
+        self.assertFalse(p.exists())
+        p.mkdir()
+        self.assertTrue(p.exists())
+        self.assertTrue(p.is_dir())
+        with self.assertRaises(OSError) as cm:
+            p.mkdir()
+        self.assertEqual(cm.exception.errno, errno.EEXIST)
+        # XXX test `mode` arg
+
+    def test_mkdir_parents(self):
+        # Creating a chain of directories
+        p = self.cls(BASE, 'newdirB', 'newdirC')
+        self.assertFalse(p.exists())
+        with self.assertRaises(OSError) as cm:
+            p.mkdir()
+        self.assertEqual(cm.exception.errno, errno.ENOENT)
+        p.mkdir(parents=True)
+        self.assertTrue(p.exists())
+        self.assertTrue(p.is_dir())
+        with self.assertRaises(OSError) as cm:
+            p.mkdir(parents=True)
+        self.assertEqual(cm.exception.errno, errno.EEXIST)
+        # XXX test `mode` arg
 
     @with_symlinks
     def test_symlink_to(self):
         pathlib.PosixPath(*args, use_openat=True, **kwargs)
     )
 
+    using_openat = True
+
     def _check_symlink_loop(self, *args):
         # with openat(), ELOOP is returned as soon as you try to construct
         # the path
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.