syntactic sugar for filesystem access in Python

Bjorn Pettersen bjorn at roguewave.com
Wed Sep 27 02:18:46 CEST 2000


It's irresistably cute, so who cares if it's useful ;-)

-- bjorn

Kragen Sitaker wrote:
> 
> It is with some trepidation that I post this; I'm not sure it's
> useful.  It provides some very simple filesystem-access functionality
> in a very simple way, but it will throw exceptions at surprising times
> if the filesystem changes underneath it.
> 
> Still, it should be entertaining.
> 
> From kragen at kirk.dnaco.net Tue Sep 26 19:20:04 2000
> Date: Tue, 26 Sep 2000 19:14:21 -0400 (EDT)
> From: Kragen <kragen at kirk.dnaco.net>
> To: kragen-hacks at kragen.dnaco.net
> Subject: syntactic sugar for filesystem access in Python
> 
> Here's a sample session; source code follows:
> [kragen at kragen devel]$ python
> Python 1.5.2 (#1, Sep 17 1999, 20:15:36)  [GCC egcs-2.91.66 19990314/Linux (egcs- on linux-i386
> Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
> >>> import filesystem
> >>> fs = filesystem.Filesystem()
> >>> home = fs.home.kragen
> >>> nonexistent = fs.nonexistent_name
> Traceback (innermost last):
>   File "<stdin>", line 1, in ?
>   File "filesystem.py", line 21, in __getattr__
>     raise AttributeError, name
> AttributeError: nonexistent_name
> >>> fs.bin.cat("/home/kragen/imptest.py")
> class Bound:
>         def __import__(*args):
>                 print "importing ", args
> 0
> >>> imptest = str(home["imptest.py"])
> >>> print home["imptest.py"]
> class Bound:
>         def __import__(*args):
>                 print "importing ", args
> 
> >>> fs.bin.ls("-l", "/home/kragen/.ncftp")
> total 128
> -rw-------   1 kragen   kragen       3958 Jul 17 17:29 firewall
> -rw-------   1 kragen   kragen        870 Sep 25 00:11 history
> -rw-rw-r--   1 kragen   kragen       3093 Sep 25 00:11 log
> -rw-r--r--   1 kragen   kragen        415 Sep 20 13:22 prefs
> -rw-------   1 kragen   kragen       3261 Sep 25 00:11 trace
> -rw-------   1 kragen   kragen       3545 Jul 25 00:32 trace.002455
> -rw-------   1 kragen   kragen       4465 Jul 25 15:55 trace.004094
> -rw-------   1 kragen   kragen      12074 Jul 29 21:28 trace.004098
> -rw-------   1 kragen   kragen       5610 Jul 25 16:35 trace.004938
> -rw-------   1 kragen   kragen       3741 Aug  9 11:33 trace.010544
> -rw-------   1 kragen   kragen      31031 Aug  6 13:04 trace.013201
> -rw-------   1 kragen   kragen       8652 Aug  4 21:04 trace.013235
> -rw-------   1 kragen   kragen       4733 Aug  4 21:13 trace.013247
> -rw-------   1 kragen   kragen      10140 Aug  4 22:21 trace.013447
> -rw-------   1 kragen   kragen       1421 Sep 22 19:40 trace.019487
> -rw-rw-r--   1 kragen   kragen        143 Sep 25 00:11 v3init
> 0
> >>> home[".ncftp"][:]
> [Filesystem('/home/kragen/.ncftp/v3init'), Filesystem('/home/kragen/.ncftp/firewall'), Filesystem('/home/kragen/.ncftp/trace.002455'), Filesystem('/home/kragen/.ncftp/log'), Filesystem('/home/kragen/.ncftp/history'), Filesystem('/home/kragen/.ncftp/trace'), Filesystem('/home/kragen/.ncftp/prefs'), Filesystem('/home/kragen/.ncftp/trace.004094'), Filesystem('/home/kragen/.ncftp/trace.004938'), Filesystem('/home/kragen/.ncftp/trace.004098'), Filesystem('/home/kragen/.ncftp/trace.013201'), Filesystem('/home/kragen/.ncftp/trace.013235'), Filesystem('/home/kragen/.ncftp/trace.013247'), Filesystem('/home/kragen/.ncftp/trace.013447'), Filesystem('/home/kragen/.ncftp/trace.010544'), Filesystem('/home/kragen/.ncftp/trace.019487')]
> >>> home[".ncftp"][0]
> Filesystem('/home/kragen/.ncftp/v3init')
> >>> home[".ncftp"][1]
> Filesystem('/home/kragen/.ncftp/firewall')
> >>> del home["imptest.py"]
> >>> fs.bin.ls("/home/kragen/imptest.py")
> /bin/ls: /home/kragen/imptest.py: No such file or directory
> 256
> >>> imptest
> 'class Bound:\012        def __import__(*args):\012                print "importing ", args\012'
> >>> home["imptest.py"] = imptest
> >>> fs.bin.ls("/home/kragen/imptest.py")
> /home/kragen/imptest.py
> 0
> >>> len(str(home.core))
> 4808704
> >>> del home.core
> >>> home.core
> Traceback (innermost last):
>   File "<stdin>", line 1, in ?
>   File "filesystem.py", line 21, in __getattr__
>     raise AttributeError, name
> AttributeError: core
> >>> home.name()
> '/home/kragen'
> >>> home.dirname()
> '/home'
> >>> home.basename()
> 'kragen'
> >>>
> 
> Pretty cool, huh?  You can read and write files from the filesystem and
> run external programs more conveniently in Python than in the shell this
> way.  Here's the glue code that does the impedance matching between the
> filesystem and Python:
> 
> # Import the filesystem into your Python programs.  Inspired by some
> # comments by Mike Dierken I didn't completely understand at the time.
> 
> # I hereby disclaim any copyright interest in this work, my intent in
> # so doing being to thereby put it in the public domain.
> # Kragen Sitaker <kragen at pobox.com>, 2000-09-26
> 
> # There are some correctness problems with this code, having largely to do
> # with things changing out from under you: the current working directory,
> # These are not issues unique to Python, but they aren't there with normal
> # Python code that doesn't expect to deal with a filesystem.
> 
> import os, os.path, types, string
> 
> class Filesystem:
>     def __init__(self, pathname='/'):
>         self.__dict__["pathname"] = pathname
>     def __getattr__(self, name):
>         pathname = os.path.join(self.pathname, name)
>         if not os.path.exists(pathname):
>             raise AttributeError, name
>         return Filesystem(pathname)
>     def __len__(self):
>         return len(os.listdir(self.pathname))
>     def __getslice__(self, start, end):
>         return map ((lambda x, self=self: self.__getattr__(x)),
>                     os.listdir(self.pathname))
>     def __getitem__(self, key):
>         if not os.path.isdir(self.pathname):
>             raise TypeError, "not a directory"
>         if type(key) is types.IntType:
>             return self.__getattr__(os.listdir(self.pathname)[key])
>         else:
>             return self.__getattr__(key)
>     def __delattr__(self, key):
>         pathname = os.path.join(self.pathname, key)
>         if os.path.isdir(pathname):
>             os.rmdir(pathname)
>         elif os.path.exists(pathname):
>             os.remove(pathname)
>         else:
>             # the equivalent to this for ordinary Python objects is not
>             # correct English, so I deviate for correctness
>             raise AttributeError, "delete nonexistent file"
>     def __delitem__(self, name):
>         # sorry, we don't support deletion by numeric index :)
>         return self.__delattr__(name)
>     def __str__(self):
>         fh = open(self.pathname, 'r')
>         str = fh.read()
>         fh.close()
>         return str
>     # XXX this is inexact; What if
>     # Filesystem isn't defined in the namespace where someone tries to
>     # eval this?
>     def __repr__(self):
>         return 'Filesystem(%s)' % repr(self.pathname)
>     def name(self):
>         return self.pathname
>     def dirname(self):
>         return os.path.split(self.pathname)[0]
>     def basename(self):
>         return os.path.split(self.pathname)[1]
>     def __call__(self, *args):  # this could be improved!
>         nargs = list(args)
>         nargs.insert(0, self.name())
>         return os.system(string.join(nargs))
>     def __setattr__(self, name, value): # we unfortunately only support strings
>         fh = open(os.path.join(self.pathname, name), 'w')
>         fh.write(value)
>         fh.close()
>     def __setitem__(self, name, value):
>         return self.__setattr__(name, value)
> 
> --
> <kragen at pobox.com>       Kragen Sitaker     <http://www.pobox.com/~kragen/>
> Perilous to all of us are the devices of an art deeper than we ourselves
> possess.
>                 -- Gandalf the Grey [J.R.R. Tolkien, "Lord of the Rings"]
> --
> http://www.python.org/mailman/listinfo/python-list




More information about the Python-list mailing list