diff --git a/fas/dev.cfg b/fas/dev.cfg index 3f500b7..7892f04 100644 --- a/fas/dev.cfg +++ b/fas/dev.cfg @@ -24,7 +24,7 @@ base_url_filter.use_x_forwarded_host = True # If you have sqlite, here's a simple default to get you started # in development -sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite?debug=True" +sqlalchemy.dburi="sqlite:///devdata.sqlite" # if you are using a database or table type without transactions @@ -82,3 +82,16 @@ level='INFO' qualname='turbogears.access' handlers=['access_out'] propagate=0 + +[[[identity]]] +level='INFO' +qualname='turbogears.identity' +handlers=['access_out'] +propagate=0 + +[[[database]]] +# Set to INFO to make SQLAlchemy display SQL commands +level='ERROR' +qualname='sqlalchemy.engine' +handlers=['debug_out'] +propagate=0 diff --git a/fas/fas/commands.py b/fas/fas/commands.py new file mode 100644 index 0000000..7d6c30b --- /dev/null +++ b/fas/fas/commands.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +"""This module contains functions called from console script entry points.""" + +import os +import sys + +from os.path import dirname, exists, join + +import pkg_resources +pkg_resources.require("TurboGears") + +import turbogears +import cherrypy + +cherrypy.lowercase_api = True + +class ConfigurationError(Exception): + pass + +def start(): + """Start the CherryPy application server.""" + + setupdir = dirname(dirname(__file__)) + curdir = os.getcwd() + + # First look on the command line for a desired config file, + # if it's not on the command line, then look for 'setup.py' + # in the current directory. If there, load configuration + # from a file called 'dev.cfg'. If it's not there, the project + # is probably installed and we'll look first for a file called + # 'prod.cfg' in the current directory and then for a default + # config file called 'default.cfg' packaged in the egg. + if len(sys.argv) > 1: + configfile = sys.argv[1] + elif exists(join(setupdir, "setup.py")): + configfile = join(setupdir, "dev.cfg") + elif exists(join(curdir, "prod.cfg")): + configfile = join(curdir, "prod.cfg") + else: + try: + configfile = pkg_resources.resource_filename( + pkg_resources.Requirement.parse("fas"), + "config/default.cfg") + except pkg_resources.DistributionNotFound: + raise ConfigurationError("Could not find default configuration.") + + turbogears.update_config(configfile=configfile, + modulename="fas.config") + + from fas.controllers import Root + + turbogears.start_server(Root()) diff --git a/fas/fas/config/app.cfg b/fas/fas/config/app.cfg index 051b6b7..d596c79 100644 --- a/fas/fas/config/app.cfg +++ b/fas/fas/config/app.cfg @@ -35,13 +35,27 @@ genshi.encoding="utf-8" # Allow every exposed function to be called as json, # tg.allow_json = False +# Suppress the inclusion of the shipped MochiKit version, which is rather outdated. +# Attention: setting this to True and listing 'turbogears.mochikit' in 'tg.include_widgets' +# is a contradiction. This option will overrule the default-inclusion to prevent version +# mismatch bugs. +# tg.mochikit_suppress = True + # List of Widgets to include on every page. -# for exemple ['turbogears.mochikit'] +# for example ['turbogears.mochikit'] # tg.include_widgets = [] # Set to True if the scheduler should be started # tg.scheduler = False +# Set to True to allow paginate decorator redirects when page number gets +# out of bound. Useful for getting the real page id in the url +# paginate.redirect_on_out_of_range = True + +# Set to True to allow paginate decorator redirects when last page is requested. +# This is useful for getting the real last page id in the url +# paginate.redirect_on_last_page = True + # i18n session_filter.on = True i18n.run_template_filter = True @@ -70,7 +84,7 @@ visit.timeout=20 # visit.cookie.path="/" # The name of the VisitManager plugin to use for visitor tracking. -visit.manager="safas" +visit.manager="sqlalchemy" #visit.manager="sqlobject" # Database class to use for visit tracking @@ -107,29 +121,28 @@ identity.provider='safas2' # Valid sources: form, visit, http_auth # identity.source="form,http_auth,visit" -# SqlObjectIdentityProvider +# SqlAlchemyIdentityProvider # Configuration options for the default IdentityProvider # ------------------------- # The classes you wish to use for your Identity model. Remember to not use reserved # SQL keywords for class names (at least unless you specify a different table # name using sqlmeta). -#identity.soprovider.model.user="fas.model.User" -#identity.soprovider.model.group="fas.model.Group" -#identity.soprovider.model.permission="fas.model.Permission" -#identity.soprovider.model.autocreate="True" +#identity.saprovider.model.user="fas.model.User" +#identity.saprovider.model.group="fas.model.Group" +#identity.saprovider.model.permission="fas.model.Permission" # The password encryption algorithm used when comparing passwords against what's # stored in the database. Valid values are 'md5' or 'sha1'. If you do not # specify an encryption algorithm, passwords are expected to be clear text. -# The SqlObjectProvider *will* encrypt passwords supplied as part of your login +# The SqlAlchemyProvider *will* encrypt passwords supplied as part of your login # form. If you set the password through the password property, like: # my_user.password = 'secret' -# the password will be encrypted in the database, provided identity is up and +# the password will be encrypted in the database, provided identity is up and # running, or you have loaded the configuration specifying what encryption to # use (in situations where identity may not yet be running, like tests). -# identity.soprovider.encryption_algorithm=None +# identity.saprovider.encryption_algorithm=None accounts_mail = "accounts@fedoraproject.org" diff --git a/fas/fas/tests/test_controllers.py b/fas/fas/tests/test_controllers.py index 88960e9..b3acfac 100644 --- a/fas/fas/tests/test_controllers.py +++ b/fas/fas/tests/test_controllers.py @@ -1,33 +1,37 @@ +import unittest import turbogears -from nose import with_setup from turbogears import testutil from fas.controllers import Root import cherrypy -def teardown_func(): - """Tests for apps using identity need to stop CP/TG after each test to - stop the VisitManager thread. See http://trac.turbogears.org/turbogears/ticket/1217 - for details. - """ - turbogears.startup.stopTurboGears() - cherrypy.root = Root() -def test_method(): - "the index method should return a string called now" - import types - result = testutil.call(cherrypy.root.index) - assert type(result["now"]) == types.StringType -test_method = with_setup(teardown=teardown_func)(test_method) +class TestPages(unittest.TestCase): -def test_indextitle(): - "The indexpage should have the right title" - testutil.createRequest("/") - assert "Welcome to TurboGears" in cherrypy.response.body[0] -test_indextitle = with_setup(teardown=teardown_func)(test_indextitle) + def setUp(self): + turbogears.startup.startTurboGears() -def test_logintitle(): - "login page should have the right title" - testutil.createRequest("/login") - assert "Login" in cherrypy.response.body[0] -test_logintitle = with_setup(teardown=teardown_func)(test_logintitle) + def tearDown(self): + """Tests for apps using identity need to stop CP/TG after each test to + stop the VisitManager thread. + See http://trac.turbogears.org/turbogears/ticket/1217 for details. + """ + turbogears.startup.stopTurboGears() + + def test_method(self): + "the index method should return a string called now" + import types + result = testutil.call(cherrypy.root.index) + assert type(result["now"]) == types.StringType + + def test_indextitle(self): + "The indexpage should have the right title" + testutil.createRequest("/") + response = cherrypy.response.body[0].lower() + assert "welcome to turbogears" in response + + def test_logintitle(self): + "login page should have the right title" + testutil.createRequest("/login") + response = cherrypy.response.body[0].lower() + assert "login" in response