[Zope-CVS] CVS: Products/AdaptableStorage/gateway_fs - FSConnection.py:1.6.2.1
Christian Zagrodnick
cz@gocept.com
Mon, 13 Jan 2003 14:28:26 -0500
Update of /cvs-repository/Products/AdaptableStorage/gateway_fs
In directory cvs.zope.org:/tmp/cvs-serv20215
Modified Files:
Tag: zagy-patches
FSConnection.py
Log Message:
- Merging HEAD into zagy-patches branch
- Added hidden_filenames parameter. This string is interpreted as comma
separated list of names to be completely ignored.
=== Products/AdaptableStorage/gateway_fs/FSConnection.py 1.6 => 1.6.2.1 ===
--- Products/AdaptableStorage/gateway_fs/FSConnection.py:1.6 Tue Dec 31 16:47:44 2002
+++ Products/AdaptableStorage/gateway_fs/FSConnection.py Mon Jan 13 14:28:24 2003
@@ -23,23 +23,17 @@
from interfaces.public import IFSConnection
from exceptions import FSWriteError
-from mapper_public import ITPCConnection
+from mapper_public import ITPCConnection, NoStateFoundError
-# Try to decipher this one ;-)
+# Try to decipher this regular expression ;-)
# It basically matches "\n[sectionname]...\n", where len(sectionname) > 0.
section_re = re.compile(r'^\[([^\[\]\n]+)\][^\r\n]*(?:\r\n|\r|\n)',
re.MULTILINE)
-NODE_TYPE_SECTION = '@node_type'
-DATA_SECTION = '@data'
-
-
-# Write modes
-WRITE_UNCONDITIONAL = 0
-WRITE_CONDITIONAL = 1
-WRITE_PRESERVE = 2
+NODE_TYPE_SECTION = '@node_type' # Data is 'f' (file) or 'd' (directory)
+DATA_SECTION = '@data' # Data is a string (file) or list of names (directory)
class FSConnection:
@@ -56,24 +50,18 @@
basepath = ''
- def __init__(self, basepath, hidden_filename_prefix='.'):
+ def __init__(self, basepath, hidden_filename_prefix='.', hidden_filenames=[]):
self.basepath = basepath
self.hidden_filename_prefix = hidden_filename_prefix
+ self.hidden_filenames = map(lambda x: x.strip(),
+ hidden_filenames.split(','))
self._final = 0
# _pending holds the data to be written.
# _pending: { subpath string -> { section_name -> data } }
self._pending = {}
- # _conditional holds data that will be written only if the
- # rest of the data for a subpath is in _pending.
- # _conditional: { subpath string -> { section_name -> data } }
- self._conditional = {}
- # _preserve holds the name of sections that will either be
- # copied or changed by another write operation.
- # _preserve: { subpath string -> { section_name -> 1 } }
- self._preserve = {}
- def expandPath(self, subpath, check_exists=0):
+ def expandPath(self, subpath):
if self.basepath:
while subpath.startswith('/') or subpath.startswith('\\'):
subpath = subpath[1:]
@@ -81,8 +69,6 @@
else:
# unchanged.
path = subpath
- if check_exists:
- assert os.path.exists(path), '%s does not exist' % path
return path
@@ -95,7 +81,7 @@
assert section_name != DATA_SECTION
- def _write(self, subpath, section_name, data, mode=WRITE_UNCONDITIONAL):
+ def _write(self, subpath, section_name, data):
# XXX We should be checking for '..'
path = self.expandPath(subpath)
# Do some early checking.
@@ -104,13 +90,12 @@
if not v:
raise FSWriteError(
"Can't get write access to %s" % subpath)
- self.queue(subpath, section_name, data, mode)
+ self.queue(subpath, section_name, data)
- def writeSection(self, subpath, section_name, data,
- mode=WRITE_UNCONDITIONAL):
+ def writeSection(self, subpath, section_name, data):
self.checkSectionName(section_name)
- self._write(subpath, section_name, data, mode)
+ self._write(subpath, section_name, data)
def writeNodeType(self, subpath, data):
@@ -130,30 +115,40 @@
def readSection(self, subpath, section_name, default=None):
self.checkSectionName(section_name)
- path = self.expandPath(subpath, 1)
+ path = self.expandPath(subpath)
sections = self.getPropertiesFromFile(path)
return sections.get(section_name, default)
def readNodeType(self, subpath):
- path = self.expandPath(subpath, 1)
+ path = self.expandPath(subpath)
+ if not os.path.exists(path):
+ raise NoStateFoundError(subpath)
return os.path.isdir(path) and 'd' or 'f'
- def readData(self, subpath):
- path = self.expandPath(subpath, 1)
+ def readData(self, subpath, allow_missing=0):
+ path = self.expandPath(subpath)
isdir = os.path.isdir(path)
# Read either the directory listing or the file contents.
if isdir:
names = []
prefix = self.hidden_filename_prefix
for name in os.listdir(path):
- if not name.startswith(self.hidden_filename_prefix):
- names.append(name)
+ if name.startswith(self.hidden_filename_prefix):
+ continue
+ if name in self.hidden_filenames:
+ continue
+ names.append(name)
# Return a sequence instead of a string.
return names
else:
- f = open(path, 'rb')
+ try:
+ f = open(path, 'rb')
+ except IOError:
+ if allow_missing:
+ return None
+ raise
try:
return f.read()
finally:
@@ -175,9 +170,11 @@
"""Read a properties file next to path."""
props_fn = self.getPropertiesPath(path)
- if not os.path.exists(props_fn):
+ try:
+ f = open(props_fn, 'rb')
+ except IOError:
+ # The file is presumably nonexistent
return {}
- f = open(props_fn, 'rb')
try:
data = f.read()
finally:
@@ -233,10 +230,12 @@
finally:
f.close()
else:
- if not data.endswith('\n'):
- data = data + '\n'
- props_f.write('\n[%s]\n' % name)
+ props_f.write('[%s]\n' % name)
props_f.write(data.replace('[', '[['))
+ if data.endswith('\n'):
+ props_f.write('\n')
+ else:
+ props_f.write('\n\n')
finally:
props_f.close()
@@ -248,7 +247,8 @@
existing = os.listdir(path)
prefix = self.hidden_filename_prefix
for fn in existing:
- if not fn.startswith(prefix) and not linked.get(fn):
+ if (not fn.startswith(prefix) and not fn in self.hidden_filenames
+ and not linked.get(fn)):
item_fn = os.path.join(path, fn)
if os.path.isdir(item_fn):
rmtree(item_fn)
@@ -268,7 +268,7 @@
raise FSWriteError(
'Data or node type not specified for %s' % subpath)
t = sections[NODE_TYPE_SECTION]
- if t not in 'df':
+ if t not in ('d', 'f'):
raise FSWriteError(
'node type must be "d" or "f" at %s' % subpath)
dir = os.path.dirname(subpath)
@@ -287,18 +287,10 @@
'Data for a directory must be a list or tuple at %s'
% subpath)
- def queue(self, subpath, section_name, data, mode=WRITE_UNCONDITIONAL):
+
+ def queue(self, subpath, section_name, data):
"""Queues data to be written at commit time"""
- if mode == WRITE_UNCONDITIONAL:
- m = self._pending
- elif mode == WRITE_CONDITIONAL:
- m = self._conditional
- elif mode == WRITE_PRESERVE:
- m = self._preserve
- # The data doesn't matter in this case.
- data = 1
- else:
- raise RuntimeError('Unknown write mode: %d' % mode)
+ m = self._pending
sections = m.get(subpath)
if sections is None:
sections = {}
@@ -311,6 +303,7 @@
else:
sections[section_name] = data
+
#
# ITPCConnection implementation
#
@@ -333,20 +326,6 @@
This is done while the transaction can still be vetoed safely.
"""
- for subpath, sections in self._conditional.items():
- if self._pending.get(subpath):
- # Add the conditional data.
- for section_name, data in sections.items():
- self.queue(subpath, section_name, data)
- for subpath, sections in self._preserve.items():
- psections = self._pending.get(subpath)
- for section_name, data in sections.items():
- if not psections or not psections.has_key(section_name):
- # Preserve the existing data.
- data = self.readSection(subpath, section_name, '')
- if data:
- self.queue(subpath, section_name, data)
- self._conditional.clear()
items = self._pending.items()
items.sort() # Ensure that base directories come first.
self.beforeWrite(items)
@@ -355,8 +334,6 @@
def reset(self):
self._final = 0
self._pending.clear()
- self._conditional.clear()
- self._preserve.clear()
def abort(self):
self.reset()