[elbe-devel] [PATCH 5/5] filesystem: Add dodctests

Torben Hohn torben.hohn at linutronix.de
Mon May 25 15:24:30 CEST 2020


On Mon, May 18, 2020 at 10:10:00AM -0400, Olivier Dion wrote:
> Most of the tests are trivial and ensure that that all code paths are
> executed and proper exceptions are thrown.
> 
> Some test are less easier to do.  For example disk_usage(), which
> would requires to assume the size of small directories on a
> system.
> 
> Also, to avoid clashing between files of different tests, each file
> created are prefix with the method tested.
> 
> Signed-off-by: Olivier Dion <dion at linutronix.de>
> ---
>  elbepack/filesystem.py | 172 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 172 insertions(+)
> 
> diff --git a/elbepack/filesystem.py b/elbepack/filesystem.py
> index 99c5a013..09baf5ee 100644
> --- a/elbepack/filesystem.py
> +++ b/elbepack/filesystem.py
> @@ -56,6 +56,11 @@ class Filesystem(object):
>      # pylint: disable=too-many-public-methods
>  
>      def __init__(self, path, clean=False):
> +        """
> +        >>> os.path.isdir(this.path)
> +        True
> +        """
> +
>          self.path = os.path.abspath(path)
>  
>          if clean:
> @@ -63,39 +68,149 @@ class Filesystem(object):
>              os.makedirs(self.path)
>  
>      def fname(self, path):
> +        """
> +        >>> this.fname('/fname')
> +        '/tmp/elbe-doctests/fname'
> +        """

mmm... i see, but this does not allow 2 elbe tests to run on the same
machine at once.

you can use 

>>> this.fname('/fname') == os.path.join(this.path, '/fname')
True

and it seems like there are not so many occasions, where you rely on
/tmp/elbe-doctests


>          if path.startswith('/'):
>              path = path[1:]
>          return os.path.join(self.path, path)
>  
>      def open(self, path, mode="r"):
> +        """
> +        >>> this.open("open") # doctest: +ELLIPSIS
> +        Traceback (most recent call last):
> +        ...
> +        FileNotFoundError: [Errno 2] ...
> +
> +        >>> this.open("open", mode="w") # doctest: +ELLIPSIS
> +        <_io.TextIOWrapper ...>
> +
> +        >>> _.close()
> +        """
>          return open(self.fname(path), mode)
>  
>      def open_gz(self, path, mode="r"):
> +        """
> +        >>> this.open_gz("open_gz") # doctest: +ELLIPSIS
> +        Traceback (most recent call last):
> +        ...
> +        FileNotFoundError: [Errno 2] ...
> +
> +        >>> this.open_gz("open_gz", mode="w") # doctest: +ELLIPSIS
> +        <gzip _io.BufferedWriter ...>
> +
> +        >>> _.close()
> +        """
>          return gzip.open(self.fname(path), mode)
>  
>      def isdir(self, path):
> +        """
> +        >>> this.isdir("isdir")
> +        False
> +
> +        >>> os.makedirs(this.fname("isdir"))
> +        >>> this.isdir("isdir")
> +        True
> +        """
>          return os.path.isdir(self.fname(path))
>  
>      def islink(self, path):
> +        """
> +        >>> this.islink("islink")
> +        False
> +
> +        >>> os.symlink("target", this.fname("islink"))
> +        >>> this.islink("islink")
> +        True
> +        """
>          return os.path.islink(self.fname(path))
>  
>      def isfile(self, path):
> +        """
> +        >>> this.isfile("isfile")
> +        False
> +
> +        >>> open(this.fname("isfile"), mode="w").close()
> +        >>> this.isfile("isfile")
> +        True
> +        """
>          return os.path.isfile(self.fname(path))
>  
>      def exists(self, path):
> +        """
> +        >>> this.exists("exists")
> +        False
> +
> +        >>> os.symlink("broken", this.fname("exixsts-broken-link"))
> +        >>> this.exists("exists-broken-link")
> +        False
> +
> +        >>> open(this.fname("exists"), mode="w").close()
> +        >>> this.exists("exists")
> +        True
> +        """
>          return os.path.exists(self.fname(path))
>  
>      def lexists(self, path):
> +        """
> +        >>> this.lexists("lexists")
> +        False
> +
> +        >>> os.symlink("target", this.fname("lexists"))
> +        >>> os.path.lexists(this.fname("lexists"))
> +        True
> +        """
>          return os.path.lexists(self.fname(path))
>  
>      def mkdir(self, path):
> +        """
> +        >>> os.path.isdir(this.fname("mkdir"))
> +        False
> +        >>> this.mkdir("mkdir")
> +        >>> os.path.isdir(this.fname("mkdir"))
> +        True
> +        """
>          os.makedirs(self.realpath(path))
>  
>      def readlink(self, path):
> +        """
> +        >>> this.symlink("target", "readlink")
> +        >>> this.readlink("readlink")
> +        'target'
> +        """
>          return os.readlink(self.fname(path))
>  
>      def realpath(self, path):
> +        """
> +        >>> this.realpath(".")
> +        '/tmp/elbe-doctests'
> +
> +        >>> this.realpath("..")
> +        '/tmp/elbe-doctests'
> +
> +        >>> this.realpath("/realpath")
> +        '/tmp/elbe-doctests/realpath'
>  
> +        >>> this.symlink("/target", "realpath-abs-symlink")
> +        >>> this.realpath("realpath-abs-symlink")
> +        '/tmp/elbe-doctests/target'
> +
> +        >>> this.symlink("target", "/realpath-symlink")
> +        >>> this.realpath("realpath-symlink")
> +        '/tmp/elbe-doctests/target'
> +
> +        >>> this.symlink(".././realpath-symlink", "realpath-multi-symlink")
> +        >>> this.realpath("realpath-multi-symlink")
> +        '/tmp/elbe-doctests/target'
> +
> +        >>> this.symlink("realpath-loop-A", "realpath-loop-B")
> +        >>> this.symlink("realpath-loop-B", "realpath-loop-A")
> +        >>> this.realpath("realpath-loop-A")
> +        '/tmp/elbe-doctests/realpath-loop-A'
> +        >>> this.realpath("realpath-loop-B")
> +        '/tmp/elbe-doctests/realpath-loop-B'
> +        """

ok... so here you also need to use the 

>>> this.realpath("realpath-loop-B") == this.fname('/realpath-loop-B')
True 

and then it will be fine.


>          path = path.split(os.sep)
>          path.reverse()
>          following = []
> @@ -142,6 +257,23 @@ class Filesystem(object):
>          return os.sep.join(real_path)
>  
>      def symlink(self, src, path, allow_exists=False):
> +        """
> +        >>> this.symlink("target", "symlink-link")
> +        >>> os.readlink(this.fname("symlink-link"))
> +        'target'
> +
> +        >>> this.symlink("target", "symlink-link") # doctest: +ELLIPSIS
> +        Traceback (most recent call last):
> +        ...
> +        FileExistsError: [Errno 17] ...
> +
> +        >>> os.readlink(this.fname("not-a-link")) # doctest: +ELLIPSIS
> +        Traceback (most recent call last):
> +        ...
> +        FileNotFoundError: [Errno 2] ...
> +
> +        >>> this.symlink("target", "symlink-link", allow_exists=True)
> +        """
>          try:
>              os.symlink(src, self.fname(path))
>          except OSError as e:
> @@ -173,6 +305,20 @@ class Filesystem(object):
>          return content
>  
>      def remove(self, path, noerr=False):
> +        """
> +        >>> this.remove("remove") # doctest: +ELLIPSIS
> +        Traceback (most recent call last):
> +        ...
> +        FileNotFoundError: [Errno 2] ...
> +
> +        >>> this.remove("remove", noerr=True)
> +
> +        >>> open(this.fname("remove"), "w").close()
> +        >>> this.remove("remove")
> +
> +        >>> this.lexists("remove")
> +        False
> +        """
>          try:
>              return os.remove(self.fname(path))
>          except BaseException:
> @@ -180,6 +326,14 @@ class Filesystem(object):
>                  raise
>  
>      def rmtree(self, path):
> +        """
> +        >>> this.mkdir("/rmtree/rmtree")
> +        >>> this.rmtree("/rmtree")
> +        >>> this.lexists("/rmtree/rmtree")
> +        False
> +        >>> this.lexists("/rmtree")
> +        False
> +        """
>          shutil.rmtree(self.fname(path))
>  
>      def listdir(self, path='', ignore=None, skiplinks=False):
> @@ -239,6 +393,24 @@ class Filesystem(object):
>                  - already exists, silently complete
>                  - regular file in the way, raise an exception
>                  - parent directory(ies) does not exist, make them as well
> +
> +        --
> +        >>> this.mkdir_p("mkdir_p/foo/bar")
> +        >>> this.isdir("mkdir_p")
> +        True
> +
> +        >>> this.isdir("mkdir_p/foo")
> +        True
> +
> +        >>> this.isdir("mkdir_p/foo/bar")
> +        True
> +
> +        >>> open(this.fname("mkdir_p/foo/bar/baz"), "w").close()
> +
> +        >>> this.mkdir_p("mkdir_p/foo/bar/baz") # doctest: +ELLIPSIS
> +        Traceback (most recent call last):
> +        ...
> +        OSError: a file with the same name as the desired dir, ...
>          """
>          if self.isdir(newdir):
>              pass
> -- 
> 2.26.2
> 
> 
> _______________________________________________
> elbe-devel mailing list
> elbe-devel at linutronix.de
> https://lists.linutronix.de/mailman/listinfo/elbe-devel

-- 
Torben Hohn
Linutronix GmbH | Bahnhofstrasse 3 | D-88690 Uhldingen-Mühlhofen
Phone: +49 7556 25 999 18; Fax.: +49 7556 25 999 99

Hinweise zum Datenschutz finden Sie hier (Informations on data privacy 
can be found here): https://linutronix.de/kontakt/Datenschutz.php

Linutronix GmbH | Firmensitz (Registered Office): Uhldingen-Mühlhofen | 
Registergericht (Registration Court): Amtsgericht Freiburg i.Br., HRB700 
806 | Geschäftsführer (Managing Directors): Heinz Egger, Thomas Gleixner



More information about the elbe-devel mailing list