Changeset 8030 for trunk/ndg_oauth/ndg_oauth_server
- Timestamp:
- 29/02/12 13:13:19 (9 years ago)
- Location:
- trunk/ndg_oauth/ndg_oauth_server
- Files:
-
- 10 added
- 9 deleted
- 17 edited
- 1 copied
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/ndg_oauth/ndg_oauth_server/client_register.ini
r7950 r8030 10 10 #id=477bfc8c-a739-45b3-a63b-5b1662cc12d7 11 11 type=confidential 12 redirect_uris=http:// ice.badc.rl.ac.uk:5001/client/redirect_target13 authentication_data=/O=STFC/OU=BADC/OU=simpleCA- ice.badc.rl.ac.uk/OU=badc.rl.ac.uk/CN=test1.client12 redirect_uris=http://localhost:5001/client/redirect_target 13 authentication_data=/O=STFC/OU=BADC/OU=simpleCA-localhost/OU=badc.rl.ac.uk/CN=test1.client 14 14 15 15 [client:test2] … … 18 18 #id=691ad8cc-293c-4fbe-b8eb-980fcd621157 19 19 type=confidential 20 redirect_uris=http:// ice.badc.rl.ac.uk:5002/oauth2/oauth_redirect21 authentication_data=/O=STFC/OU=BADC/OU=simpleCA- ice.badc.rl.ac.uk/OU=badc.rl.ac.uk/CN=test.client20 redirect_uris=http://localhost:5002/oauth2/oauth_redirect 21 authentication_data=/O=STFC/OU=BADC/OU=simpleCA-localhost/OU=badc.rl.ac.uk/CN=test.client -
trunk/ndg_oauth/ndg_oauth_server/development.ini
r8004 r8030 1 1 # 2 # ndgoauthserver - Pylons development environment configuration2 # NDG OAuth Server - Pylons development environment configuration 3 3 # 4 4 # The %(here)s variable will be replaced with the parent directory of this file … … 51 51 # fully qualified domain name or else set the MYPROXY_SERVER environment 52 52 # variable. See the documentation for the MyProxyClient egg for details 53 myproxy.client.hostname = ice.badc.rl.ac.uk53 myproxy.client.hostname = localhost 54 54 #myproxy.client.port = 7512 55 55 … … 62 62 [filter:OAuth2Authz] 63 63 # Authorization filter configuration options - defaults are commented out. 64 paste.filter_app_factory = ndg oauthserver.wsgi.authorization_filter:Oauth2AuthorizationMiddleware.filter_app_factory64 paste.filter_app_factory = ndg.oauth.server.wsgi.authorization_filter:Oauth2AuthorizationMiddleware.filter_app_factory 65 65 oauth2authorization.base_url_path=/client_authorization 66 oauth2authorization.client_authorization_form=%(here)s/ndg oauthserver/templates/auth_client_form.html66 oauth2authorization.client_authorization_form=%(here)s/ndg/oauth/server/templates/auth_client_form.html 67 67 #oauth2authorization.client_authorizations_key=client_authorizations 68 68 oauth2authorization.client_register=%(here)s/client_register.ini … … 71 71 72 72 [app:OAuth2Server] 73 paste.app_factory = ndg oauthserver.wsgi.oauth2_server:Oauth2ServerMiddleware.app_factory73 paste.app_factory = ndg.oauth.server.wsgi.oauth2_server:Oauth2ServerMiddleware.app_factory 74 74 75 75 # OAuth2 server configuration options - defaults are commented out. … … 133 133 level = DEBUG 134 134 handlers = 135 qualname = ndg oauthserver135 qualname = ndg.oauth.server 136 136 137 137 [handler_console] -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/access_token/bearer_token_generator.py
r7952 r8030 10 10 import uuid 11 11 12 from ndg oauthserver.lib.access_token.access_token_interface import AccessTokenInterface13 from ndg oauthserver.lib.register.access_token import AccessToken12 from ndg.oauth.server.lib.access_token.access_token_interface import AccessTokenInterface 13 from ndg.oauth.server.lib.register.access_token import AccessToken 14 14 15 15 class BearerTokenGenerator(AccessTokenInterface): … … 32 32 Gets an access token with an ID that is a random UUID used as a bearer 33 33 token. 34 @type token_request: ndg oauthserver.lib.access_token.AccessTokenRequest34 @type token_request: ndg.oauth.server.lib.access_token.AccessTokenRequest 35 35 @param token_request: access token request 36 36 37 @type grant: ndg oauthserver.lib.register.authorization_grant.AuthorizationGrant37 @type grant: ndg.oauth.server.lib.register.authorization_grant.AuthorizationGrant 38 38 @param grant: authorization grant 39 39 … … 41 41 @param request: HTTP request object 42 42 43 @rtype: ndg oauthserver.lib.register.access_token.AccessToken43 @rtype: ndg.oauth.server.lib.register.access_token.AccessToken 44 44 @return: access token or None if an error occurs 45 45 """ -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/access_token/make_access_token.py
r7952 r8030 10 10 from datetime import datetime 11 11 12 from ndg oauthserver.lib.oauth.oauth_exception import OauthException13 from ndg oauthserver.lib.oauth.access_token import AccessTokenResponse12 from ndg.oauth.server.lib.oauth.oauth_exception import OauthException 13 from ndg.oauth.server.lib.oauth.access_token import AccessTokenResponse 14 14 15 15 AUTHORIZATION_CODE_GRANT_TYPE = 'authorization_code' … … 49 49 # This requires that the client has authenticated itself so that the 50 50 # client identity is known. 51 # TODO client_id is None if client authentication is not configured. Is there52 # a better way to signal that authentication is disabled for testing?51 # client_id is None if client authentication is not configured - this 52 # signals that authentication is disabled for testing. 53 53 if client_id and (grant.client_id != client_id): 54 54 raise OauthException('invalid_grant', 'Token granted for different client') -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/access_token/myproxy_cert_token_generator.py
r7952 r8030 11 11 import logging 12 12 13 from ndg oauthserver.lib.access_token.access_token_interface import AccessTokenInterface14 from ndg oauthserver.lib.register.access_token import AccessToken13 from ndg.oauth.server.lib.access_token.access_token_interface import AccessTokenInterface 14 from ndg.oauth.server.lib.register.access_token import AccessToken 15 15 16 16 log = logging.getLogger(__name__) … … 41 41 """ 42 42 Gets an access token using MyProxyClient. 43 @type token_request: ndg oauthserver.lib.access_token.AccessTokenRequest43 @type token_request: ndg.oauth.server.lib.access_token.AccessTokenRequest 44 44 @param token_request: access token request 45 45 46 @type grant: ndg oauthserver.lib.register.authorization_grant.AuthorizationGrant46 @type grant: ndg.oauth.server.lib.register.authorization_grant.AuthorizationGrant 47 47 @param grant: authorization grant 48 48 … … 50 50 @param request: HTTP request object 51 51 52 @rtype: ndg oauthserver.lib.register.access_token.AccessToken52 @rtype: ndg.oauth.server.lib.register.access_token.AccessToken 53 53 @return: access token or None if an error occurs 54 54 """ -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/authenticate/certificate_client_authenticator.py
r7952 r8030 8 8 __revision__ = "$Id$" 9 9 10 from ndg oauthserver.lib.authenticate.client_authenticator_interface import ClientAuthenticatorInterface11 from ndg oauthserver.lib.oauth.oauth_exception import OauthException12 from ndg oauthserver.lib.register.client import ClientRegister10 from ndg.oauth.server.lib.authenticate.client_authenticator_interface import ClientAuthenticatorInterface 11 from ndg.oauth.server.lib.oauth.oauth_exception import OauthException 12 from ndg.oauth.server.lib.register.client import ClientRegister 13 13 14 14 class CertificateClientAuthenticator(ClientAuthenticatorInterface): -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/authenticate/noop_client_authenticator.py
r7952 r8030 8 8 __revision__ = "$Id$" 9 9 10 from ndg oauthserver.lib.authenticate.client_authenticator_interface import ClientAuthenticatorInterface10 from ndg.oauth.server.lib.authenticate.client_authenticator_interface import ClientAuthenticatorInterface 11 11 12 12 class NoopClientAuthenticator(ClientAuthenticatorInterface): -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/authenticate/test_authenticator.py
r7952 r8030 8 8 __revision__ = "$Id$" 9 9 10 from ndg oauthserver.lib.authenticate.authenticator_interface import AuthenticatorInterface10 from ndg.oauth.server.lib.authenticate.authenticator_interface import AuthenticatorInterface 11 11 12 12 class TestAuthenticator(AuthenticatorInterface): -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/authorization_server.py
r7952 r8030 13 13 import urllib 14 14 15 from ndg oauthserver.lib.access_token.make_access_token import make_access_token16 from ndg oauthserver.lib.oauth.access_token import AccessTokenRequest17 from ndg oauthserver.lib.oauth.authorize import AuthorizeRequest, AuthorizeResponse18 from ndg oauthserver.lib.oauth.oauth_exception import OauthException19 from ndg oauthserver.lib.register.access_token import AccessTokenRegister20 from ndg oauthserver.lib.register.client import ClientRegister21 from ndg oauthserver.lib.register.authorization_grant import AuthorizationGrantRegister15 from ndg.oauth.server.lib.access_token.make_access_token import make_access_token 16 from ndg.oauth.server.lib.oauth.access_token import AccessTokenRequest 17 from ndg.oauth.server.lib.oauth.authorize import AuthorizeRequest, AuthorizeResponse 18 from ndg.oauth.server.lib.oauth.oauth_exception import OauthException 19 from ndg.oauth.server.lib.register.access_token import AccessTokenRegister 20 from ndg.oauth.server.lib.register.client import ClientRegister 21 from ndg.oauth.server.lib.register.authorization_grant import AuthorizationGrantRegister 22 22 23 23 log = logging.getLogger(__name__) … … 33 33 self.client_authenticator = client_authenticator 34 34 self.access_token_generator = access_token_generator 35 # TODO Need configuration36 35 self.access_token_register = AccessTokenRegister(config) 37 36 self.authorization_grant_register = AuthorizationGrantRegister(config) … … 39 38 def authorize(self, request, client_authorized): 40 39 """Handle an authorization request. 40 41 It is assumed that the caller has checked whether the user is 42 authenticated and that the user has authorised the client and scope. 41 43 42 44 Request query parameters (from http://tools.ietf.org/html/draft-ietf-oauth-v2-22): … … 128 130 return (None, httplib.BAD_REQUEST, 'An authorization request has been made without a return URI.') 129 131 130 131 # TODO Check this: 132 # Assume other preconditions enforced elsewhere: 133 # o User authenticated. 134 # o User authorises the client and scope. 132 # Preconditions satisfied - generate grant. 135 133 (grant, code) = self.authorizer.generate_authorization_grant(auth_request, request) 136 134 auth_response = AuthorizeResponse(code, auth_request.state) … … 150 148 completed. 151 149 152 @type resp: ndg oauthserver.lib.oauth.authorize.AuthorizeRequest150 @type resp: ndg.oauth.server.lib.oauth.authorize.AuthorizeRequest 153 151 @param resp: OAuth authorize request 154 152 155 @type resp: ndg oauthserver.lib.oauth.authorize.AuthorizeResponse153 @type resp: ndg.oauth.server.lib.oauth.authorize.AuthorizeResponse 156 154 @param resp: OAuth authorize response 157 155 … … 299 297 def _access_token_response(self, resp): 300 298 """Constructs the JSON response to an access token request. 301 @type resp: ndg oauthserver.lib.oauth.access_token.AccessTokenResponse299 @type resp: ndg.oauth.server.lib.oauth.access_token.AccessTokenResponse 302 300 @param resp: OAuth access token response 303 301 … … 334 332 o Optionally, must use the POST method. 335 333 o Parameters must not be repeated. 336 If the request is directly from the client :337 o TODO Must be authenticated.334 If the request is directly from the client, the user must be 335 authenticated - it is assumed that the caller has checked this. 338 336 339 337 Raises OauthException if any check fails. -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/authorize/authorizer.py
r7952 r8030 11 11 import uuid 12 12 13 from ndg oauthserver.lib.authorize.authorizer_interface import AuthorizerInterface14 from ndg oauthserver.lib.register.authorization_grant import AuthorizationGrant13 from ndg.oauth.server.lib.authorize.authorizer_interface import AuthorizerInterface 14 from ndg.oauth.server.lib.register.authorization_grant import AuthorizationGrant 15 15 16 16 log = logging.getLogger(__name__) … … 26 26 def generate_authorization_grant(self, auth_request, request): 27 27 """Generates an authorization grant. 28 @type auth_request: ndg oauthserver.lib.oauth.authorize.AuthorizeRequest28 @type auth_request: ndg.oauth.server.lib.oauth.authorize.AuthorizeRequest 29 29 @param auth_request: authorization request 30 30 … … 33 33 34 34 @rtype: tuple ( 35 ndg oauthserver.lib.register.authorization_grant.AuthorizationGrant35 ndg.oauth.server.lib.register.authorization_grant.AuthorizationGrant 36 36 str 37 37 ) -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/authorize/authorizer_storing_identifier.py
r7952 r8030 11 11 import uuid 12 12 13 from ndg oauthserver.lib.authorize.authorizer_interface import AuthorizerInterface14 from ndg oauthserver.lib.oauth.oauth_exception import OauthException15 from ndg oauthserver.lib.register.authorization_grant import AuthorizationGrant13 from ndg.oauth.server.lib.authorize.authorizer_interface import AuthorizerInterface 14 from ndg.oauth.server.lib.oauth.oauth_exception import OauthException 15 from ndg.oauth.server.lib.register.authorization_grant import AuthorizationGrant 16 16 17 17 log = logging.getLogger(__name__) … … 39 39 def generate_authorization_grant(self, auth_request, request): 40 40 """Generates an authorization grant. 41 @type auth_request: ndg oauthserver.lib.oauth.authorize.AuthorizeRequest41 @type auth_request: ndg.oauth.server.lib.oauth.authorize.AuthorizeRequest 42 42 @param auth_request: authorization request 43 43 … … 46 46 47 47 @rtype: tuple ( 48 ndg oauthserver.lib.register.authorization_grant.AuthorizationGrant48 ndg.oauth.server.lib.register.authorization_grant.AuthorizationGrant 49 49 str 50 50 ) -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/register/access_token.py
r7952 r8030 11 11 import logging 12 12 13 from ndg oauthserver.lib.register.register_base import RegisterBase13 from ndg.oauth.server.lib.register.register_base import RegisterBase 14 14 15 15 log = logging.getLogger(__name__) -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/lib/register/authorization_grant.py
r7952 r8030 11 11 import logging 12 12 13 from ndg oauthserver.lib.register.register_base import RegisterBase13 from ndg.oauth.server.lib.register.register_base import RegisterBase 14 14 15 15 log = logging.getLogger(__name__) -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/wsgi/authorization_filter.py
r8004 r8030 14 14 from webob import Request 15 15 16 from ndgoauthserver.lib.register.client import ClientRegister 17 from ndgoauthserver.lib.register.client_authorization import ClientAuthorization, ClientAuthorizationRegister 16 from ndg.oauth.server.lib.register.client import ClientRegister 17 from ndg.oauth.server.lib.register.client_authorization import ( 18 ClientAuthorization, ClientAuthorizationRegister) 19 from ndg.oauth.server.lib.render.factory import callModuleObject 20 from ndg.oauth.server.lib.render.renderer_interface import RendererInterface 18 21 19 22 log = logging.getLogger(__name__) … … 34 37 CLIENT_AUTHORIZATIONS_KEY_OPTION = 'client_authorizations_key' 35 38 CLIENT_REGISTER_OPTION = 'client_register' 39 RENDERER_CLASS_OPTION = 'renderer_class' 36 40 SESSION_KEY_OPTION = 'session_key_name' 37 41 USER_IDENTIFIER_KEY_OPTION = 'user_identifier_key' … … 43 47 propertyDefaults = { 44 48 BASE_URL_PATH_OPTION: 'client_authorization', 49 RENDERER_CLASS_OPTION: 'ndg.oauth.server.lib.render.genshi_renderer.GenshiRenderer', 45 50 SESSION_KEY_OPTION: 'beaker.session.oauth2authorization', 46 51 CLIENT_AUTHORIZATIONS_KEY_OPTION: 'client_authorizations', … … 71 76 self._set_configuration(prefix, local_conf) 72 77 self.client_register = ClientRegister(self.client_register_file) 78 self.renderer = callModuleObject(self.renderer_class, 79 objectName=None, moduleFilePath=None, 80 objectType=RendererInterface, 81 objectArgs=None, objectProperties=None) 73 82 74 83 def __call__(self, environ, start_response): … … 129 138 if client_authorizations: 130 139 log.debug("_set_client_authorizations_in_environ %s", client_authorizations.__repr__()) 131 # TODO Should this be a deep copy so that the session copy cannot132 # be modified by other filters?133 140 environ[self.client_authorizations_env_key] = client_authorizations 134 141 else: … … 198 205 """ 199 206 client = self.client_register.register.get(client_id) 200 tmpl_file = open(self.client_authorization_form)201 tmpl = MarkupTemplate(tmpl_file)202 tmpl_file.close()207 # tmpl_file = open(self.client_authorization_form) 208 # tmpl = MarkupTemplate(tmpl_file) 209 # tmpl_file.close() 203 210 submit_url = req.application_url + self.base_path + '/client_auth' 204 211 c = {'client_name': client.name, … … 206 213 'scope': scope, 207 214 'submit_url': submit_url} 208 response = tmpl.generate(c=c).render('html') 215 # response = tmpl.generate(c=c).render('html') 216 response = self.renderer.render(self.client_authorization_form, c) 209 217 start_response(self._get_http_status_string(httplib.OK), 210 218 [('Content-type', 'text/html'), … … 273 281 self.base_path = cls._get_config_option(prefix, local_conf, cls.BASE_URL_PATH_OPTION) 274 282 self.client_register_file = cls._get_config_option(prefix, local_conf, cls.CLIENT_REGISTER_OPTION) 283 self.renderer_class = cls._get_config_option(prefix, local_conf, cls.RENDERER_CLASS_OPTION) 275 284 self.session_env_key = cls._get_config_option(prefix, local_conf, cls.SESSION_KEY_OPTION) 276 285 self.client_authorization_form = cls._get_config_option(prefix, local_conf, cls.CLIENT_AUTHORIZATION_FORM_OPTION) -
trunk/ndg_oauth/ndg_oauth_server/ndg/oauth/server/wsgi/oauth2_server.py
r8004 r8030 15 15 from webob import Request 16 16 17 from ndg oauthserver.lib.access_token.bearer_token_generator import BearerTokenGenerator18 from ndg oauthserver.lib.access_token.myproxy_cert_token_generator import MyProxyCertTokenGenerator19 from ndg oauthserver.lib.authenticate.certificate_client_authenticator import CertificateClientAuthenticator20 from ndg oauthserver.lib.authenticate.noop_client_authenticator import NoopClientAuthenticator21 from ndg oauthserver.lib.authorization_server import AuthorizationServer22 from ndg oauthserver.lib.authorize.authorizer import Authorizer23 from ndg oauthserver.lib.authorize.authorizer_storing_identifier import AuthorizerStoringIdentifier17 from ndg.oauth.server.lib.access_token.bearer_token_generator import BearerTokenGenerator 18 from ndg.oauth.server.lib.access_token.myproxy_cert_token_generator import MyProxyCertTokenGenerator 19 from ndg.oauth.server.lib.authenticate.certificate_client_authenticator import CertificateClientAuthenticator 20 from ndg.oauth.server.lib.authenticate.noop_client_authenticator import NoopClientAuthenticator 21 from ndg.oauth.server.lib.authorization_server import AuthorizationServer 22 from ndg.oauth.server.lib.authorize.authorizer import Authorizer 23 from ndg.oauth.server.lib.authorize.authorizer_storing_identifier import AuthorizerStoringIdentifier 24 24 25 25 log = logging.getLogger(__name__) … … 34 34 o MyProxyClientMiddleware 35 35 o Middleware to set user's decisions for authorization of OAuth clients in 36 the environ, e.g., ndg oauthserver.wsgi.authorization_filter.36 the environ, e.g., ndg.oauth.server.wsgi.authorization_filter. 37 37 """ 38 38 PARAM_PREFIX = 'oauth2server.' -
trunk/ndg_oauth/ndg_oauth_server/setup.cfg
r8004 r8030 2 2 #tag_build = dev 3 3 tag_svn_revision = true 4 5 [easy_install]6 find_links = http://www.pylonshq.com/download/7 8 [nosetests]9 with-pylons = test.ini10 11 # Babel configuration12 [compile_catalog]13 domain = ndgoauthserver14 directory = ndgoauthserver/i18n15 statistics = true16 17 [extract_messages]18 add_comments = TRANSLATORS:19 output_file = ndgoauthserver/i18n/ndgoauthserver.pot20 width = 8021 22 [init_catalog]23 domain = ndgoauthserver24 input_file = ndgoauthserver/i18n/ndgoauthserver.pot25 output_dir = ndgoauthserver/i18n26 27 [update_catalog]28 domain = ndgoauthserver29 input_file = ndgoauthserver/i18n/ndgoauthserver.pot30 output_dir = ndgoauthserver/i18n31 previous = true -
trunk/ndg_oauth/ndg_oauth_server/setup.py
r8026 r8030 1 __author__ = "R B Wilkinson" 2 __date__ = "29/02/12" 3 __copyright__ = "(C) 2012 Science and Technology Facilities Council" 4 __license__ = "BSD - see LICENSE file in top-level directory" 5 __contact__ = "Philip.Kershaw@stfc.ac.uk" 6 __revision__ = "$Id$" 7 1 8 try: 2 9 from setuptools import setup, find_packages … … 6 13 from setuptools import setup, find_packages 7 14 15 _long_description = """\ 16 This is an OAuth 2.0 server library and WSGI middleware filter. 17 18 Prerequisites 19 ============= 20 This has been developed and tested for Python 2.6. 21 22 Installation 23 ============ 24 Installation can be performed using easy_install or pip. 25 26 Configuration 27 ============= 28 An example of configuration is provided in the file development.ini. This 29 configures the components needed to authenticate users, obtain user 30 authorisation for an OAuth client and obtain a certificate to use as an access 31 token using MyProxyClient. 32 """ 33 8 34 setup( 9 name='ndgoauthserver', 10 version='0.1.1', 11 description='OAuth 2.0 server providing MyProxy certificates as access tokens', 12 author='R. B. Wilkinson', 13 #author_email='', 14 #url='', 15 install_requires=[ 16 "Pylons>=1.0", 17 "Genshi>=0.4", 35 name = 'ndg_oauth_server', 36 version = '0.2.0', 37 description = 'OAuth 2.0 server providing MyProxy certificates as access tokens', 38 long_description = _long_description, 39 author = 'R. B. Wilkinson', 40 maintainer = 'Philip Kershaw', 41 maintainer_email = 'Philip.Kershaw@stfc.ac.uk', 42 #url ='', 43 license = 'BSD - See LICENCE file for details', 44 install_requires =[ 45 "PasteScript", 46 "Beaker", 47 "WebOb", 48 "repoze.who", 49 "MyProxyWebService", 50 "Genshi", 18 51 ], 19 setup_requires=["PasteScript>=1.6.3"], 20 packages=find_packages(exclude=['ez_setup']), 21 include_package_data=True, 22 test_suite='nose.collector', 23 package_data={'ndgoauthserver': ['i18n/*/LC_MESSAGES/*.mo']}, 24 #message_extractors={'ndgoauthserver': [ 25 # ('**.py', 'python', None), 26 # ('public/**', 'ignore', None)]}, 27 zip_safe=False, 28 paster_plugins=['PasteScript', 'Pylons'], 29 entry_points=""" 30 [paste.app_factory] 31 main = ndgoauthserver.config.middleware:make_app 32 33 [paste.app_install] 34 main = pylons.util:PylonsInstaller 35 """, 52 packages =find_packages(), 53 zip_safe =False, 36 54 )
Note: See TracChangeset
for help on using the changeset viewer.