syntactic sugar for filesystem access in Python
Kragen Sitaker
kragen at dnaco.net
Tue Sep 26 19:19:59 EDT 2000
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"]
More information about the Python-list
mailing list