[Zope-CVS] CVS: Packages/zpkgtools/zpkgtools - locationmap.py:1.18
Fred L. Drake, Jr.
fred at zope.com
Tue Jun 8 23:07:35 EDT 2004
Update of /cvs-repository/Packages/zpkgtools/zpkgtools
In directory cvs.zope.org:/tmp/cvs-serv22672/zpkgtools
Modified Files:
locationmap.py
Log Message:
Change the syntax for package wildcards, with new tests.
- must be explicitly specified
- tests broken by Jim's implementation now pass
- wildcards must be specified with a trailing ".*" now
=== Packages/zpkgtools/zpkgtools/locationmap.py 1.17 => 1.18 ===
--- Packages/zpkgtools/zpkgtools/locationmap.py:1.17 Thu Jun 3 23:50:31 2004
+++ Packages/zpkgtools/zpkgtools/locationmap.py Tue Jun 8 23:07:00 2004
@@ -16,10 +16,12 @@
import logging
import os.path
import posixpath
+import re
import sets
import urllib
import urllib2
import urlparse
+import UserDict
from zpkgtools import cvsloader
from zpkgtools import loader
@@ -35,79 +37,107 @@
self.lineno = lineno
ValueError.__init__(self, message)
-class LocationMap(dict):
- def get(self, name, default=None):
- """Look up an entry froma map
+class LocationMap(UserDict.UserDict):
- If an entry isn't found directly, check for a prefix
+ def __init__(self, *args, **kw):
+ UserDict.UserDict.__init__(self, *args, **kw)
+ self._wildcards = {}
+
+ def __getitem__(self, key):
+ if key in self.data:
+ v = self.data[key]
+ if v is None:
+ raise KeyError(key)
+ return v
+ # might be supported by the wildcards
+ v = self._get_from_wildcards(key)
+ if v is None:
+ raise KeyError(key)
+ return v
+
+ def __setitem__(self, key, item):
+ self.data[key] = item
+
+ def __delitem__(self, key):
+ if key in self.data and self.data[key] != None:
+ del self.data[key]
+ elif key in self:
+ # must be here as a wildcard
+ self.data[key] = None
+ else:
+ raise KeyError(key)
+
+ def get(self, key, default=None):
+ if key in self.data:
+ v = self.data[key]
+ if v is None:
+ v = default
+ return v
+ try:
+ return self._get_from_wildcards(key)
+ except KeyError:
+ return default
+
+ def has_key(self, key):
+ if key in self.data:
+ return self.data[key] is not None
+ else:
+ return self._get_from_wildcards(key) is not None
+
+ def update(self, dict=None, **kwargs):
+ if dict:
+ for key, value in dict.iteritems():
+ self.data[key] = value
+ if len(kwargs):
+ self.update(kwargs)
+
+ def pop(self, key, *args):
+ return self.data.pop(key, *args)
+
+ def __contains__(self, key):
+ if key in self.data:
+ return self.data[key] is not None
+ else:
+ return self._get_from_wildcards(key) is not None
- >>> map = LocationMap({'foo': 'svn://spam.com/repos/foo'})
- >>> map.get('foo')
- 'svn://spam.com/repos/foo'
- >>> map.get('foo.bar')
- 'svn://spam.com/repos/foo/bar'
- >>> map.get('foo.bar.baz')
- 'svn://spam.com/repos/foo/bar/baz'
- >>> map.get('z')
- >>> map.get('z.x')
- >>> map.get('z.x.y')
-
- """
-
- r = dict.get(self, name)
- if r:
- return r
-
- suffix = ''
- while 1:
- l = name.rfind('.')
- if l > 0:
- suffix = '/'+ name[l+1:] + suffix
- name = name[:l]
+ def _add_wildcard(self, key, location):
+ """Add a location for a wildcarded package."""
+ self._wildcards[key] = location
+
+ def _get_from_wildcards(self, key):
+ """Return location based on wildcards, or None."""
+ prefix = key
+ suffix = ""
+ while "." in prefix:
+ pos = prefix.rfind(".")
+ name = prefix[pos+1:]
+ prefix = prefix[:pos]
+ if suffix:
+ suffix = "%s/%s" % (name, suffix)
else:
- break
- r = dict.get(self, name)
- if r:
- return r + suffix
-
- return default
-
- __contains__ = get
-
- def __getitem__(self, name):
- """Look up an entry froma map
-
- If an entry isn't found directly, check for a prefix
-
- >>> map = LocationMap({'foo': 'svn://spam.com/repos/foo'})
- >>> map['foo']
- 'svn://spam.com/repos/foo'
- >>> map['foo.bar']
- 'svn://spam.com/repos/foo/bar'
- >>> map['foo.bar.baz']
- 'svn://spam.com/repos/foo/bar/baz'
-
- >>> map['z']
- Traceback (most recent call last):
- ...
- KeyError: 'z'
-
- >>> map['z.x']
- Traceback (most recent call last):
- ...
- KeyError: 'z.x'
-
- >>> map['z.x.y']
- Traceback (most recent call last):
- ...
- KeyError: 'z.x.y'
-
- """
- r = self.get(name)
- if r:
- return r
- raise KeyError, name
+ suffix = name
+ base = self._wildcards.get(prefix)
+ if base:
+ # join suffix with the path portion of the base
+ try:
+ parsed = loader.parse(base)
+ except ValueError:
+ # we should distinguish between URLs and local paths here
+ parts = list(urlparse.urlsplit(base))
+ if parts[2]:
+ parts[2] = posixpath.join(parts[2], suffix)
+ else:
+ parts[2] = posixpath.join("", suffix)
+ return urlparse.urlunsplit(parts)
+ else:
+ pathpart = cvsloader.RepositoryUrl(suffix)
+ return parsed.join(pathpart).getUrl()
+ return None
+
+ def _have_wildcard(self, key):
+ """Return true iff we already have a wildcard for key."""
+ return key in self._wildcards
def load(f, base=None, mapping=None):
@@ -159,16 +189,30 @@
url = cvsurl.getUrl()
- # We only want to add it once, so that loading several
- # mappings causes the first defining a resource to "win":
- if resource not in mapping:
- mapping[resource] = url
- elif resource in local_entries:
+ if resource in local_entries:
_logger.warn(
"found duplicate entry for resource %r in %s at line %d",
resource, getattr(f, "name", "<unknown>"), lineno)
+ elif resource.endswith(".*"):
+ # Deal with wildcarded resources;
+ # need to check if it's already there
+ wildcard = resource[:-2]
+ if not is_module_name(wildcard):
+ raise MapLoadingError("wildcard package name specified, but"
+ " prefix is not a legal package name: %r"
+ % wildcard,
+ getattr(f, "name", "<unknown>"), lineno)
+ if not mapping._have_wildcard(wildcard):
+ mapping._add_wildcard(wildcard, url)
+ elif "*" in resource:
+ raise MapLoadingError("invalid wildcard specification: %r"
+ % resource,
+ getattr(f, "name", "<unknown>"), lineno)
+ elif resource not in mapping:
+ # We only want to add it once, so that loading several
+ # mappings causes the first defining a resource to "win":
+ mapping[resource] = url
local_entries.add(resource)
- # else tell the user of the conflict?
return mapping
@@ -194,3 +238,10 @@
return load(f, base, mapping)
finally:
f.close()
+
+
+_ident = "[a-zA-Z_][a-zA-Z_0-9]*"
+_module_match = re.compile(r"%s(\.%s)*$" % (_ident, _ident)).match
+
+def is_module_name(string):
+ return _module_match(string) is not None
More information about the Zope-CVS
mailing list