[z3-checkins] r37244 - in z3/deliverance/DeliveranceVHoster/trunk: . dvhoster tests
ianb at codespeak.net
ianb at codespeak.net
Wed Jan 24 02:12:39 CET 2007
Author: ianb
Date: Wed Jan 24 02:12:31 2007
New Revision: 37244
Modified:
z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py
z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py
z3/deliverance/DeliveranceVHoster/trunk/setup.cfg
z3/deliverance/DeliveranceVHoster/trunk/tests/ (props changed)
z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py
Log:
Started the API, using OHM. Also functional tests (not all passing) for the API
Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py
==============================================================================
--- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py (original)
+++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py Wed Jan 24 02:12:31 2007
@@ -1,5 +1,13 @@
import re
import os
+from ohm import persist
+from ohm import server
+from ohm import descriptors
+from ohm import lildav
+from ohm.validators import LineConverter
+from formencode import validators
+from formencode.foreach import ForEach
+from formencode.compound import All
domain_re = re.compile(r'^localhost|[a-z][a-z0-9.\-]+\.[a-z]+$', re.I)
@@ -48,7 +56,7 @@
dir = os.path.join(self.dir, domain_name)
if not os.path.exists(dir):
os.mkdir(dir)
- return DomainDataProvider(domain_name, dir)
+ return DomainDataProvider(self, domain_name, dir)
def normalize(self, domain_name):
domain_name = domain_name.strip().lower()
@@ -57,51 +65,22 @@
'Bad domain name: %r' % domain_name)
return domain_name
-class file_property(object):
-
- def __init__(self, basename):
- self.basename = basename
-
- def filename(self, obj):
- return os.path.join(obj.dir, self.basename)
-
- def __get__(self, obj, type=None):
- if obj is None:
- return self
- if not os.path.exists(self.filename(obj)):
- return None
- f = open(self.filename(obj), 'rb')
- c = f.read()
- f.close()
- return c
-
- def __set__(self, obj, value):
- f = open(self.filename(obj), 'wb')
- f.write(value)
- f.close()
-
- def __del__(self, obj):
- os.unlink(self.filename(obj))
-
- def __repr__(self):
- return '%s(%r)' % (
- self.__class__.__name__, self.basename)
-
class DomainDataProvider(object):
- def __init__(self, domain_name, dir):
- self.domain_name = domain_name
- self.dir = dir
+ def __init__(self, provider, domain_name, base_dir):
+ self._domain_name = domain_name
+ self.base_dir = base_dir
+ self.provider = provider
def __repr__(self):
return '<%s %s for %s in %r>' % (
self.__class__.__name__,
hex(id(self)),
- self.domain_name,
- self.dir)
+ self._domain_name,
+ self.base_dir)
def initialize(self):
- for dir in [self.dir, self.rule_dir,
+ for dir in [self.base_dir, self.rule_dir,
self.static_dir]:
if not os.path.exists(dir):
os.mkdir(dir)
@@ -116,25 +95,99 @@
@property
def initialized(self):
- return bool(self.remote)
+ return hasattr(self, 'remote')
@property
def rule_dir(self):
- return os.path.join(self.dir, 'rules')
+ return os.path.join(self.base_dir, 'rules')
@property
def static_dir(self):
- return os.path.join(self.dir, 'static')
-
- remote = file_property('remote.txt')
- theme_uri = file_property('theme_uri.txt')
- theme_id = file_property('theme_id.txt')
- rule_ids = file_property('rule_ids.txt')
+ return os.path.join(self.base_dir, 'static')
+
+ remote = persist.file_property('remote.txt')
+ theme_uri = persist.file_property('theme_uri.txt')
+ theme_id = persist.file_property('theme_id.txt')
+ rule_ids = persist.file_property('rule_ids.txt')
+ aliases = descriptors.line_converter(persist.file_property('aliases.txt'))
def set_rule_file(self, filename, content):
filename = os.path.join(self.rule_dir, filename)
f = open(filename, 'wb')
f.write(content)
f.close()
-
+ def domain__get(self):
+ return self._domain_name
+
+ def domain__set(self, value):
+ new_obj = self.provider.rename_domain(self.domain, value)
+ # Clone new object as self:
+ self.__dict__.update(new_obj.__dict__)
+
+ domain = property(domain__get, domain__set)
+
+class DomainValidator(validators.Regex):
+ regex = r'^[a-z0-9\-]+|[a-z0-9][a-z0-9\-\.\_]*\.[a-z]+$'
+
+class ListDictValidator(validators.FancyValidator):
+ required_keys = ()
+ optional_keys = ()
+
+ def validate_python(self, value, state=None):
+ # Should be like [{'path': path, 'remote_uri': uri, 'comment': str}]
+ # comment is optional
+ try:
+ assert isinstance(value, list), 'Must be list'
+ for d in value:
+ keys = d.keys()
+ for key in self.required_keys:
+ assert key in d, "Must have key %r in %r" % d
+ assert isinstance(d[key], basestring), (
+ '%s must be string (not %r)' % (key, d[key]))
+ keys.remove(key)
+ for key in self.optional_keys:
+ if key not in d:
+ continue
+ assert isinstance(d[key], basestring), (
+ '%s must be string (not %r)' % (key, d[key]))
+ keys.remove(key)
+ assert not keys, (
+ "Key(s) not allowed: %s in %r"
+ % (', '.join(map(repr, keys)), d))
+ except AssertionError, e:
+ raise validators.Invalid(str(e), value, state)
+
+class RemoteURIValidator(ListDictValidator):
+ required_keys = ('path', 'remote_uri')
+ optional_keys = ('comment', )
+
+class RewriteValidator(ListDictValidator):
+ required_keys = ('rewrite', )
+ # @@: Really we should require one of path or prefix
+ optional_keys = ('path', 'prefix', 'comment')
+
+class ProviderApp(server.ApplicationWrapper):
+
+ theme_uri = server.Setter(
+ validator=validators.URL())
+ domain = server.Setter(
+ validator=DomainValidator())
+ aliases = server.Setter(
+ validator=All(ForEach(DomainValidator()), LineConverter()))
+ remote_uris = server.JSONSetter(
+ validator=RemoteURIValidator())
+ redirects = server.JSONSetter(
+ validator=RewriteValidator())
+
+ @server.appfactory()
+ def rules(self):
+ if not os.path.exists(self.rule_dir):
+ os.makedirs(self.rule_dir)
+ return lildav.LilDAV(self.rule_dir)
+
+ @server.appfactory()
+ def static(self):
+ if not os.path.exists(self.static_dir):
+ os.makedirs(self.static_dir)
+ return lildav.LilDAV(self.rule_dir)
Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py
==============================================================================
--- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original)
+++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Wed Jan 24 02:12:31 2007
@@ -8,7 +8,7 @@
from wsgifilter import proxyapp
from wsgifilter import relocateresponse
from deliverance.wsgimiddleware import DeliveranceMiddleware
-from dvhoster.dataprovider import DataProvider
+from dvhoster.dataprovider import DataProvider, ProviderApp
from dvhoster import current_environ
from dvhoster.debuginterp import Renderer
@@ -38,20 +38,16 @@
environ, with_query_string=False,
path_info='')
path_info = norm_path(environ.get('PATH_INFO', ''))
- if (not domain_info.initialized
- or not domain_info.remote
- or not domain_info.theme_uri):
- new_url = construct_url(
- environ, with_query_string=False,
- path_info='/_deliverance')
- exc = httpexceptions.HTTPTemporaryRedirect(
- headers=[('location', new_url)])
- return exc(environ, start_response)
+ if path_info.startswith('/.deliverance'):
+ path_info_pop(environ)
+ subapp = ProviderApp(domain_info)
+ return subapp(environ, start_response)
if path_info.startswith('/_rules'):
path_info_pop(environ)
subapp = StaticURLParser(
domain_info.rule_dir)
return subapp(environ, start_response)
+
static_path = os.path.join(domain_info.static_dir,
path_info.lstrip('/'))
static_fn = self.find_file(static_path)
Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.cfg
==============================================================================
--- z3/deliverance/DeliveranceVHoster/trunk/setup.cfg (original)
+++ z3/deliverance/DeliveranceVHoster/trunk/setup.cfg Wed Jan 24 02:12:31 2007
@@ -1,6 +1,6 @@
[egg_info]
tag_build = dev
-tag_svn_revision = true
+#tag_svn_revision = true
[easy_install]
find_links = http://www.pylonshq.com/download/
Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py
==============================================================================
--- z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py (original)
+++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Wed Jan 24 02:12:31 2007
@@ -1,15 +1,16 @@
+import os
+import shutil
from paste.fixture import TestApp
from paste.urlparser import StaticURLParser
from dvhoster.wsgiapp import make_app
import wsgi_intercept
-wsgi_app = make_app(
- {},
- data_dir=os.path.join(os.path.dirname(__file__), 'test-data'))
+data_filename = os.path.join(os.path.dirname(__file__), 'test-data')
+wsgi_app = make_app({}, data_dir=data_filename)
app = TestApp(wsgi_app)
def put(uri, data):
- app.post(uri, data, extra_environ={'REQUEST_METHOD': 'PUT'})
+ app.post(uri, data, extra_environ={'REQUEST_METHOD': 'PUT'}, status=(201, 204))
rule_data = '''
<?xml version="1.0" encoding="UTF-8"?>
@@ -32,14 +33,19 @@
def test_everything():
+ yield (reset_env,)
yield (create_api,)
yield (use_api, 'localhost')
yield (rename_site,)
yield (use_api, 'localhost2')
-def create_api():
- app = make_test_app()
+def reset_env():
+ if os.path.exists(data_filename):
+ shutil.rmtree(data_filename)
+ os.mkdir(data_filename)
+
+def create_api():
# Theme:
uri = 'http://wsgify.org/theme.html'
put('/.deliverance/theme_uri', uri)
@@ -54,13 +60,13 @@
assert res.body == 'localhost'
# Aliases:
- data = "localhost.localhost\nexample.com"
+ data = "localhost.localhost\nexample.com\n"
put('/.deliverance/aliases', data)
assert app.get('/.deliverance/aliases').body == data
data = '''
[{"path": "/", "remote_uri": "http://wsgify.org/"},
- {"path": "/bar", "remote_uri": "http://wsgify.org/blah", comment="x"}]
+ {"path": "/bar", "remote_uri": "http://wsgify.org/blah", "comment": "x"}]
'''
put('/.deliverance/remote_uris', data)
@@ -76,9 +82,9 @@
data = '<html>some data!</html>'
put('/.deliverance/static/data.html', data)
res = app.get('/.deliverance/static/data.html')
- assert res.data == data
+ assert res.body == data
app.get('/.deliverance/static/subdir',
- extra_environ={'REQUEST_METHOD', 'MKCOL'})
+ extra_environ={'REQUEST_METHOD': 'MKCOL'}, status=201)
put('/.deliverance/static/subdir/foo.html', 'blah')
res = app.get('/.deliverance/static/subdir/foo.html')
assert res.body == 'blah'
@@ -88,7 +94,6 @@
res = app.get('/subdir/', status=404)
def use_api(hostname):
- app.extra_environ['HTTP_HOST'] = hostname
res = app.get('/index.html')
res.mustcontain(
# From the theme:
@@ -117,4 +122,10 @@
res = app.get('/subdir/foo.html')
assert res.body == 'blah'
-
+def rename_site():
+ put('/.deliverance/domain', 'localhost2')
+ app.extra_environ['HTTP_HOST'] = 'localhost2'
+ res = app.get('/.deliverance/aliases')
+ res.mustcontain('localhost')
+ assert app.get('/.deliverance/domain').body == 'localhost2'
+
More information about the z3-checkins
mailing list