Project

General

Profile

Revision 0931fc44

ID0931fc4433c34cb270a9a357877c2f252310f8e3
Child 4cdb7492

Added by Thomas BURGUIERE almost 15 years ago

tburguie: ajout du nouveau module vigigraph

git-svn-id: https://vigilo-dev.si.c-s.fr/svn@901 b22e2e97-25c9-44ff-b637-2e5ceca36478

View differences:

MANIFEST.in
1
recursive-include vigigraph/public *
2
include vigigraph/public/favicon.ico
3
recursive-include vigigraph/i18n *
4
recursive-include vigigraph/templates *
Makefile
1
NAME := vigigraph
2
include ../glue/Makefile.common
3
all: build
4
MODULE := $(NAME)
5
CODEPATH := $(NAME)
6
lint: lint_pylint
7
tests: tests_tg
README.txt
1
This file is for you to describe the vigigraph application. Typically
2
you would include information such as the information below:
3

  
4
Installation and Setup
5
======================
6

  
7
Install ``vigigraph`` using the setup.py script::
8

  
9
    $ cd vigigraph
10
    $ python setup.py install
11

  
12
Create the project database for any model classes defined::
13

  
14
    $ paster setup-app development.ini
15

  
16
Start the paste http server::
17

  
18
    $ paster serve development.ini
19

  
20
While developing you may want the server to reload after changes in package files (or its dependencies) are saved. This can be achieved easily by adding the --reload option::
21

  
22
    $ paster serve --reload development.ini
23

  
24
Then you are ready to go.
buildout.cfg
1
[buildout]
2
extends = ../glue/buildout.cfg
3
eggs += vigigraph
4

  
5
# vim: set noexpandtab :
development.ini
1
#
2
# vigigraph - Pylons development environment configuration
3
#
4
# The %(here)s variable will be replaced with the parent directory of this file
5
#
6
# This file is for deployment specific config options -- other configuration
7
# that is always required for the app is done in the config directory, 
8
# and generally should not be modified by end users. 
9

  
10
[DEFAULT]
11
debug = true
12
# Uncomment and replace with the address which should receive any error reports
13
#email_to = you@yourdomain.com
14
smtp_server = localhost
15
error_email_from = paste@localhost
16

  
17
[server:main]
18
use = egg:Paste#http
19
host = 127.0.0.1 
20
port = 8080
21

  
22
[app:main]
23
use = egg:vigigraph
24
full_stack = true
25
#lang = ru
26
cache_dir = %(here)s/data
27
beaker.session.key = vigigraph
28
beaker.session.secret = somesecret
29

  
30
# If you'd like to fine-tune the individual locations of the cache data dirs
31
# for the Cache data, or the Session saves, un-comment the desired settings
32
# here:
33
#beaker.cache.data_dir = %(here)s/data/cache
34
#beaker.session.data_dir = %(here)s/data/sessions
35

  
36
# pick the form for your database
37
# %(here) may include a ':' character on Windows environments; this can
38
# invalidate the URI when specifying a SQLite db via path name
39
# sqlalchemy.url=postgres://username:password@hostname:port/databasename 
40
# sqlalchemy.url=mysql://username:password@hostname:port/databasename
41

  
42

  
43
# If you have sqlite, here's a simple default to get you started
44
# in development
45

  
46
sqlalchemy.url = sqlite:///%(here)s/devdata.db
47
#echo shouldn't be used together with the logging module.
48
sqlalchemy.echo = false
49
sqlalchemy.echo_pool = false
50
sqlalchemy.pool_recycle = 3600
51

  
52
# if you are using Mako and want to be able to reload
53
# the mako template from disk during the development phase
54
# you should say 'true' here
55
# This option is only used for mako templating engine
56
# WARNING: if you want to deploy your application using a zipped egg
57
# (ie: if your application's setup.py defines zip-safe=True, then you
58
# MUST put "false" for the production environment because there will
59
# be no disk and real files to compare time with.
60
# On the contrary if your application defines zip-safe=False and is
61
# deployed in an unzipped manner, then you can leave this option to true
62
templating.mako.reloadfromdisk = true
63

  
64
# the compiled template dir is a directory that must be readable by your
65
# webserver. It will be used to store the resulting templates once compiled
66
# by the TemplateLookup system.
67
# During development you generally don't need this option since paste's HTTP
68
# server will have access to you development directories, but in production
69
# you'll most certainly want to have apache or nginx to write in a directory
70
# that does not contain any source code in any form for obvious security reasons.
71
#
72
#templating.mako.compiled_templates_dir = /some/dir/where/webserver/has/access
73

  
74
# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
75
# Debug mode will enable the interactive debugging tool, allowing ANYONE to
76
# execute malicious code after an exception is raised.
77
#set debug = false
78

  
79
# Logging configuration
80
# Add additional loggers, handlers, formatters here
81
# Uses python's logging config file format
82
# http://docs.python.org/lib/logging-config-fileformat.html
83

  
84
[loggers]
85
keys = root, vigigraph, sqlalchemy, auth
86

  
87
[handlers]
88
keys = console
89

  
90
[formatters]
91
keys = generic
92

  
93
# If you create additional loggers, add them as a key to [loggers]
94
[logger_root]
95
level = INFO
96
handlers = console
97

  
98
[logger_vigigraph]
99
level = DEBUG
100
handlers =
101
qualname = vigigraph
102

  
103
[logger_sqlalchemy]
104
level = INFO
105
handlers =
106
qualname = sqlalchemy.engine
107
# "level = INFO" logs SQL queries.
108
# "level = DEBUG" logs SQL queries and results.
109
# "level = WARN" logs neither.  (Recommended for production systems.)
110

  
111

  
112
# A logger for authentication, identification and authorization -- this is
113
# repoze.who and repoze.what:
114
[logger_auth]
115
level = WARN
116
handlers = 
117
qualname = auth
118

  
119
# If you create additional handlers, add them as a key to [handlers]
120
[handler_console]
121
class = StreamHandler
122
args = (sys.stderr,)
123
level = NOTSET
124
formatter = generic
125

  
126
# If you create additional formatters, add them as a key to [formatters]
127
[formatter_generic]
128
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
129
datefmt = %H:%M:%S
ez_setup/README.txt
1
This directory exists so that Subversion-based projects can share a single
2
copy of the ``ez_setup`` bootstrap module for ``setuptools``, and have it
3
automatically updated in their projects when ``setuptools`` is updated.
4

  
5
For your convenience, you may use the following svn:externals definition::
6

  
7
    ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup
8

  
9
You can set this by executing this command in your project directory::
10

  
11
    svn propedit svn:externals .
12

  
13
And then adding the line shown above to the file that comes up for editing.
14
Then, whenever you update your project, ``ez_setup`` will be updated as well.
ez_setup/__init__.py
1
#!python
2
"""Bootstrap setuptools installation
3

  
4
If you want to use setuptools in your package's setup.py, just include this
5
file in the same directory with it, and add this to the top of your setup.py::
6

  
7
    from ez_setup import use_setuptools
8
    use_setuptools()
9

  
10
If you want to require a specific version of setuptools, set a download
11
mirror, or use an alternate download directory, you can do so by supplying
12
the appropriate options to ``use_setuptools()``.
13

  
14
This file can also be run as a script to install or upgrade setuptools.
15
"""
16
import sys
17
DEFAULT_VERSION = "0.6c7"
18
DEFAULT_URL     = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
19

  
20
md5_data = {
21
    'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
22
    'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
23
    'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
24
    'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
25
    'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
26
    'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
27
    'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
28
    'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
29
    'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
30
    'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
31
    'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
32
    'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
33
    'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
34
    'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
35
    'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
36
    'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
37
    'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
38
    'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
39
    'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
40
    'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
41
    'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
42
    'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
43
    'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
44
    'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
45
    'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
46
    'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
47
    'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
48
}
49

  
50
import sys, os
51

  
52
def _validate_md5(egg_name, data):
53
    if egg_name in md5_data:
54
        from md5 import md5
55
        digest = md5(data).hexdigest()
56
        if digest != md5_data[egg_name]:
57
            print >>sys.stderr, (
58
                "md5 validation of %s failed!  (Possible download problem?)"
59
                % egg_name
60
            )
61
            sys.exit(2)
62
    return data
63

  
64

  
65
def use_setuptools(
66
    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
67
    download_delay=15
68
):
69
    """Automatically find/download setuptools and make it available on sys.path
70

  
71
    `version` should be a valid setuptools version number that is available
72
    as an egg for download under the `download_base` URL (which should end with
73
    a '/').  `to_dir` is the directory where setuptools will be downloaded, if
74
    it is not already available.  If `download_delay` is specified, it should
75
    be the number of seconds that will be paused before initiating a download,
76
    should one be required.  If an older version of setuptools is installed,
77
    this routine will print a message to ``sys.stderr`` and raise SystemExit in
78
    an attempt to abort the calling script.
79
    """
80
    try:
81
        import setuptools
82
        if setuptools.__version__ == '0.0.1':
83
            print >>sys.stderr, (
84
            "You have an obsolete version of setuptools installed.  Please\n"
85
            "remove it from your system entirely before rerunning this script."
86
            )
87
            sys.exit(2)
88
    except ImportError:
89
        egg = download_setuptools(version, download_base, to_dir, download_delay)
90
        sys.path.insert(0, egg)
91
        import setuptools; setuptools.bootstrap_install_from = egg
92

  
93
    import pkg_resources
94
    try:
95
        pkg_resources.require("setuptools>="+version)
96

  
97
    except pkg_resources.VersionConflict, e:
98
        # XXX could we install in a subprocess here?
99
        print >>sys.stderr, (
100
            "The required version of setuptools (>=%s) is not available, and\n"
101
            "can't be installed while this script is running. Please install\n"
102
            " a more recent version first.\n\n(Currently using %r)"
103
        ) % (version, e.args[0])
104
        sys.exit(2)
105

  
106
def download_setuptools(
107
    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
108
    delay = 15
109
):
110
    """Download setuptools from a specified location and return its filename
111

  
112
    `version` should be a valid setuptools version number that is available
113
    as an egg for download under the `download_base` URL (which should end
114
    with a '/'). `to_dir` is the directory where the egg will be downloaded.
115
    `delay` is the number of seconds to pause before an actual download attempt.
116
    """
117
    import urllib2, shutil
118
    egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
119
    url = download_base + egg_name
120
    saveto = os.path.join(to_dir, egg_name)
121
    src = dst = None
122
    if not os.path.exists(saveto):  # Avoid repeated downloads
123
        try:
124
            from distutils import log
125
            if delay:
126
                log.warn("""
127
---------------------------------------------------------------------------
128
This script requires setuptools version %s to run (even to display
129
help).  I will attempt to download it for you (from
130
%s), but
131
you may need to enable firewall access for this script first.
132
I will start the download in %d seconds.
133

  
134
(Note: if this machine does not have network access, please obtain the file
135

  
136
   %s
137

  
138
and place it in this directory before rerunning this script.)
139
---------------------------------------------------------------------------""",
140
                    version, download_base, delay, url
141
                ); from time import sleep; sleep(delay)
142
            log.warn("Downloading %s", url)
143
            src = urllib2.urlopen(url)
144
            # Read/write all in one block, so we don't create a corrupt file
145
            # if the download is interrupted.
146
            data = _validate_md5(egg_name, src.read())
147
            dst = open(saveto,"wb"); dst.write(data)
148
        finally:
149
            if src: src.close()
150
            if dst: dst.close()
151
    return os.path.realpath(saveto)
152

  
153
def main(argv, version=DEFAULT_VERSION):
154
    """Install or upgrade setuptools and EasyInstall"""
155

  
156
    try:
157
        import setuptools
158
    except ImportError:
159
        egg = None
160
        try:
161
            egg = download_setuptools(version, delay=0)
162
            sys.path.insert(0,egg)
163
            from setuptools.command.easy_install import main
164
            return main(list(argv)+[egg])   # we're done here
165
        finally:
166
            if egg and os.path.exists(egg):
167
                os.unlink(egg)
168
    else:
169
        if setuptools.__version__ == '0.0.1':
170
            # tell the user to uninstall obsolete version
171
            use_setuptools(version)
172

  
173
    req = "setuptools>="+version
174
    import pkg_resources
175
    try:
176
        pkg_resources.require(req)
177
    except pkg_resources.VersionConflict:
178
        try:
179
            from setuptools.command.easy_install import main
180
        except ImportError:
181
            from easy_install import main
182
        main(list(argv)+[download_setuptools(delay=0)])
183
        sys.exit(0) # try to force an exit
184
    else:
185
        if argv:
186
            from setuptools.command.easy_install import main
187
            main(argv)
188
        else:
189
            print "Setuptools version",version,"or greater has been installed."
190
            print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
191

  
192

  
193

  
194
def update_md5(filenames):
195
    """Update our built-in md5 registry"""
196

  
197
    import re
198
    from md5 import md5
199

  
200
    for name in filenames:
201
        base = os.path.basename(name)
202
        f = open(name,'rb')
203
        md5_data[base] = md5(f.read()).hexdigest()
204
        f.close()
205

  
206
    data = ["    %r: %r,\n" % it for it in md5_data.items()]
207
    data.sort()
208
    repl = "".join(data)
209

  
210
    import inspect
211
    srcfile = inspect.getsourcefile(sys.modules[__name__])
212
    f = open(srcfile, 'rb'); src = f.read(); f.close()
213

  
214
    match = re.search("\nmd5_data = {\n([^}]+)}", src)
215
    if not match:
216
        print >>sys.stderr, "Internal error!"
217
        sys.exit(2)
218

  
219
    src = src[:match.start(1)] + repl + src[match.end(1):]
220
    f = open(srcfile,'w')
221
    f.write(src)
222
    f.close()
223

  
224

  
225
if __name__=='__main__':
226
    if len(sys.argv)>2 and sys.argv[1]=='--md5update':
227
        update_md5(sys.argv[2:])
228
    else:
229
        main(sys.argv[1:])
setup.cfg
1
[egg_info]
2
tag_build = dev
3
tag_svn_revision = true
4

  
5
[easy_install]
6
find_links = http://vigilo-dev.si.c-s.fr/python/eggs
7
allow_hosts = *.si.c-s.fr
8
#find_links = http://www.pylonshq.com/download/
9

  
10
[nosetests]
11
with-pylons=test.ini
12

  
13
# Babel configuration
14
[compile_catalog]
15
domain = vigigraph
16
directory = vigigraph/i18n
17
statistics = true
18

  
19
[extract_messages]
20
add_comments = TRANSLATORS:
21
msgid_bugs_address = contact@projet-vigilo.org
22
output_file = vigigraph/i18n/vigigraph.pot
23
width = 80
24
keywords = l_
25

  
26
[init_catalog]
27
domain = vigigraph
28
input_file = vigigraph/i18n/vigigraph.pot
29
output_dir = vigigraph/i18n
30

  
31
[update_catalog]
32
domain = vigigraph
33
input_file = vigigraph/i18n/vigigraph.pot
34
output_dir = vigigraph/i18n
35
previous = true
setup.py
1
# -*- coding: utf-8 -*-
2
try:
3
    from setuptools import setup, find_packages
4
except ImportError:
5
    from ez_setup import use_setuptools
6
    use_setuptools()
7
    from setuptools import setup, find_packages
8

  
9
setup(
10
    name='vigigraph',
11
    version='0.1',
12
    description='',
13
    author='',
14
    author_email='',
15
    #url='',
16
    install_requires=[
17
        "TurboGears2 >= 2.0b7",
18
        "Catwalk >= 2.0.2",
19
        "Babel >=0.9.4",
20
        #can be removed iif use_toscawidgets = False
21
        "toscawidgets >= 0.9.7.1",
22
        "zope.sqlalchemy >= 0.4 ",
23
        "repoze.tm2 >= 1.0a4",
24
        
25
        "repoze.what-quickstart >= 1.0",
26
                ],
27
    paster_plugins=['PasteScript', 'Pylons', 'TurboGears2', 'tg.devtools'],
28
    packages=find_packages(exclude=['ez_setup']),
29
    include_package_data=True,
30
    test_suite='nose.collector',
31
    tests_require=['WebTest', 'BeautifulSoup'],
32
    package_data={'vigigraph': ['i18n/*/LC_MESSAGES/*.mo',
33
                                 'templates/*/*',
34
                                 'public/*/*']},
35
    message_extractors={'vigigraph': [
36
            ('**.py', 'python', None),
37
            ('templates/**.mako', 'mako', None),
38
            ('templates/**.html', 'genshi', None),
39
            ('public/**', 'ignore', None)]},
40

  
41
    entry_points="""
42
    [paste.app_factory]
43
    main = vigigraph.config.middleware:make_app
44

  
45
    [paste.app_install]
46
    main = pylons.util:PylonsInstaller
47
    """,
48
)
test.ini
1
#
2
# vigigraph - TurboGears 2 testing environment configuration
3
#
4
# The %(here)s variable will be replaced with the parent directory of this file
5
#
6
[DEFAULT]
7
debug = true
8
# Uncomment and replace with the address which should receive any error reports
9
# email_to = you@yourdomain.com
10
smtp_server = localhost
11
error_email_from = paste@localhost
12

  
13
[server:main]
14
use = egg:Paste#http
15
host = 0.0.0.0
16
port = 5000
17

  
18
[app:main]
19
sqlalchemy.url = sqlite:///:memory:
20
use = config:development.ini
21

  
22
[app:main_without_authn]
23
use = main
24
skip_authentication = True
25

  
26
# Add additional test specific configuration options as necessary.
vigigraph/__init__.py
1
# -*- coding: utf-8 -*-
2
"""The vigigraph package"""
vigigraph/config/__init__.py
1
# -*- coding: utf-8 -*-
2

  
vigigraph/config/app_cfg.py
1
# -*- coding: utf-8 -*-
2
"""
3
Global configuration file for TG2-specific settings in vigigraph.
4

  
5
This file complements development/deployment.ini.
6

  
7
Please note that **all the argument values are strings**. If you want to
8
convert them into boolean, for example, you should use the
9
:func:`paste.deploy.converters.asbool` function, as in::
10
    
11
    from paste.deploy.converters import asbool
12
    setting = asbool(global_conf.get('the_setting'))
13
 
14
"""
15

  
16
from tg.configuration import AppConfig
17

  
18
import vigigraph
19
from vigigraph import model
20
from vigigraph.lib import app_globals, helpers 
21

  
22
base_config = AppConfig()
23
base_config.renderers = []
24

  
25
base_config.package = vigigraph
26

  
27
#Set the default renderer
28
base_config.default_renderer = 'genshi'
29
base_config.renderers.append('genshi')
30
# if you want raw speed and have installed chameleon.genshi
31
# you should try to use this renderer instead.
32
# warning: for the moment chameleon does not handle i18n translations
33
#base_config.renderers.append('chameleon_genshi')
34

  
35
#Configure the base SQLALchemy Setup
36
base_config.use_sqlalchemy = True
37
base_config.model = vigigraph.model
38
base_config.DBSession = vigigraph.model.DBSession
39

  
40
# Configure the authentication backend
41
base_config.auth_backend = 'sqlalchemy'
42
base_config.sa_auth.dbsession = model.DBSession
43
# what is the class you want to use to search for users in the database
44
base_config.sa_auth.user_class = model.User
45
# what is the class you want to use to search for groups in the database
46
base_config.sa_auth.group_class = model.Group
47
# what is the class you want to use to search for permissions in the database
48
base_config.sa_auth.permission_class = model.Permission
49

  
50
# override this if you would like to provide a different who plugin for
51
# managing login and logout of your application
52
base_config.sa_auth.form_plugin = None
53

  
54
# You may optionally define a page where you want users to be redirected to
55
# on login:
56
base_config.sa_auth.post_login_url = '/post_login'
57

  
58
# You may optionally define a page where you want users to be redirected to
59
# on logout:
60
base_config.sa_auth.post_logout_url = '/post_logout'
vigigraph/config/deployment.ini_tmpl
1
#
2
# vigigraph - TurboGears configuration
3
#
4
# The %(here)s variable will be replaced with the parent directory of this file
5
#
6
[DEFAULT]
7
# WARGING == If debug is not set to false, you'll get the interactive
8
# debugger on production, which is a huge security hole. 
9

  
10
debug = false
11
email_to = you@yourdomain.com
12
smtp_server = localhost
13
error_email_from = paste@localhost
14

  
15
[server:main]
16
use = egg:Paste#http
17
host = 0.0.0.0
18
port = 8080
19

  
20
[app:main]
21
use = egg:vigigraph
22
full_stack = true
23
cache_dir = %(here)s/data
24
beaker.session.key = vigigraph
25
beaker.session.secret = ${app_instance_secret}
26
app_instance_uuid = ${app_instance_uuid}
27

  
28
# If you'd like to fine-tune the individual locations of the cache data dirs
29
# for the Cache data, or the Session saves, un-comment the desired settings
30
# here:
31
#beaker.cache.data_dir = %(here)s/data/cache
32
#beaker.session.data_dir = %(here)s/data/sessions
33
# Specify the database for SQLAlchemy to use via
34
# turbogears.database
35
# %(here) may include a ':' character on Windows environments; this can
36
# invalidate the URI when specifying a SQLite db via path name
37
sqlalchemy.url = sqlite:///%(here)s/somedb.db
38
sqlalchemy.echo = False
39

  
40
# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
41
# Debug mode will enable the interactive debugging tool, allowing ANYONE to
42
# execute malicious code after an exception is raised.
43
#set debug = false
44

  
45
# Logging configuration
46
# Add additional loggers, handlers, formatters here
47
# Uses python's logging config file format
48
# http://docs.python.org/lib/logging-config-fileformat.html
49

  
50
[loggers]
51
keys = root, vigigraph, sqlalchemy, auth
52

  
53
[handlers]
54
keys = console
55

  
56
[formatters]
57
keys = generic
58

  
59
# If you create additional loggers, add them as a key to [loggers]
60
[logger_root]
61
level = INFO
62
handlers = console
63

  
64
[logger_vigigraph]
65
level = INFO
66
handlers =
67
qualname = vigigraph
68

  
69
[logger_sqlalchemy]
70
level = WARN
71
handlers =
72
qualname = sqlalchemy.engine
73
# "level = INFO" logs SQL queries.
74
# "level = DEBUG" logs SQL queries and results.
75
# "level = WARN" logs neither.  (Recommended for production systems.)
76

  
77

  
78
# A logger for authentication, identification and authorization -- this is
79
# repoze.who and repoze.what:
80
[logger_auth]
81
level = WARN
82
handlers = 
83
qualname = auth
84

  
85
# If you create additional handlers, add them as a key to [handlers]
86
[handler_console]
87
class = StreamHandler
88
args = (sys.stderr,)
89
level = NOTSET
90
formatter = generic
91

  
92
# If you create additional formatters, add them as a key to [formatters]
93
[formatter_generic]
94
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
95
datefmt = %H:%M:%S
vigigraph/config/environment.py
1
# -*- coding: utf-8 -*-
2
"""WSGI environment setup for vigigraph."""
3

  
4
from vigigraph.config.app_cfg import base_config
5

  
6
__all__ = ['load_environment']
7

  
8
#Use base_config to setup the environment loader function
9
load_environment = base_config.make_load_environment()
vigigraph/config/middleware.py
1
# -*- coding: utf-8 -*-
2
"""WSGI middleware initialization for the vigigraph application."""
3

  
4
from vigigraph.config.app_cfg import base_config
5
from vigigraph.config.environment import load_environment
6

  
7

  
8
__all__ = ['make_app']
9

  
10
# Use base_config to setup the necessary PasteDeploy application factory. 
11
# make_base_app will wrap the TG2 app with all the middleware it needs. 
12
make_base_app = base_config.setup_tg_wsgi_app(load_environment)
13

  
14

  
15
def make_app(global_conf, full_stack=True, **app_conf):
16
    """
17
    Set vigigraph up with the settings found in the PasteDeploy configuration
18
    file used.
19
    
20
    :param global_conf: The global settings for vigigraph (those
21
        defined under the ``[DEFAULT]`` section).
22
    :type global_conf: dict
23
    :param full_stack: Should the whole TG2 stack be set up?
24
    :type full_stack: str or bool
25
    :return: The vigigraph application with all the relevant middleware
26
        loaded.
27
    
28
    This is the PasteDeploy factory for the vigigraph application.
29
    
30
    ``app_conf`` contains all the application-specific settings (those defined
31
    under ``[app:main]``.
32
    
33
   
34
    """
35
    app = make_base_app(global_conf, full_stack=True, **app_conf)
36
    
37
    # Wrap your base TurboGears 2 application with custom middleware here
38
    
39
    return app
vigigraph/controllers/__init__.py
1
# -*- coding: utf-8 -*-
2
"""Controllers for the vigigraph application."""
vigigraph/controllers/controller.template
1
# -*- coding: utf-8 -*-
2
"""Sample controller module"""
3

  
4
# turbogears imports
5
from tg import expose
6
#from tg import redirect, validate, flash
7

  
8
# third party imports
9
#from pylons.i18n import ugettext as _
10
#from repoze.what import predicates
11

  
12
# project specific imports
13
from vigigraph.lib.base import BaseController
14
#from vigigraph.model import DBSession, metadata
15

  
16

  
17
class SampleController(BaseController):
18
    #Uncomment this line if your controller requires an authenticated user
19
    #allow_only = authorize.not_anonymous()
20
    
21
    @expose('vigigraph.templates.index')
22
    def index(self):
23
        return dict(page='index')
vigigraph/controllers/error.py
1
# -*- coding: utf-8 -*-
2
"""Error controller"""
3

  
4
from tg import request, expose
5

  
6
__all__ = ['ErrorController']
7

  
8

  
9
class ErrorController(object):
10
    """
11
    Generates error documents as and when they are required.
12

  
13
    The ErrorDocuments middleware forwards to ErrorController when error
14
    related status codes are returned from the application.
15

  
16
    This behaviour can be altered by changing the parameters to the
17
    ErrorDocuments middleware in your config/middleware.py file.
18
    
19
    """
20

  
21
    @expose('vigigraph.templates.error')
22
    def document(self, *args, **kwargs):
23
        """Render the error document"""
24
        resp = request.environ.get('pylons.original_response')
25
        default_message = ("<p>We're sorry but we weren't able to process "
26
                           " this request.</p>")
27
        values = dict(prefix=request.environ.get('SCRIPT_NAME', ''),
28
                      code=request.params.get('code', resp.status_int),
29
                      message=request.params.get('message', default_message))
30
        return values
vigigraph/controllers/root.py
1
# -*- coding: utf-8 -*-
2
"""Main Controller"""
3

  
4
from tg import expose, flash, require, url, request, redirect
5
from pylons.i18n import ugettext as _, lazy_ugettext as l_
6
from catwalk.tg2 import Catwalk
7
from repoze.what import predicates
8

  
9
from vigigraph.lib.base import BaseController
10
from vigigraph.model import DBSession, metadata
11
from vigigraph.controllers.error import ErrorController
12
from vigigraph import model
13
from vigigraph.controllers.secure import SecureController
14

  
15
__all__ = ['RootController']
16

  
17

  
18
class RootController(BaseController):
19
    """
20
    The root controller for the vigigraph application.
21
    
22
    All the other controllers and WSGI applications should be mounted on this
23
    controller. For example::
24
    
25
        panel = ControlPanelController()
26
        another_app = AnotherWSGIApplication()
27
    
28
    Keep in mind that WSGI applications shouldn't be mounted directly: They
29
    must be wrapped around with :class:`tg.controllers.WSGIAppController`.
30
    
31
    """
32
    secc = SecureController()
33
    
34
    admin = Catwalk(model, DBSession)
35
    
36
    error = ErrorController()
37

  
38
    @expose('vigigraph.templates.index')
39
    def index(self):
40
        """Handle the front-page."""
41
        return dict(page='index')
42

  
43
    @expose('vigigraph.templates.about')
44
    def about(self):
45
        """Handle the 'about' page."""
46
        return dict(page='about')
47

  
48
    @expose('vigigraph.templates.authentication')
49
    def auth(self):
50
        """Display some information about auth* on this application."""
51
        return dict(page='auth')
52

  
53
    @expose('vigigraph.templates.index')
54
    @require(predicates.has_permission('manage', msg=l_('Only for managers')))
55
    def manage_permission_only(self, **kw):
56
        """Illustrate how a page for managers only works."""
57
        return dict(page='managers stuff')
58

  
59
    @expose('vigigraph.templates.index')
60
    @require(predicates.is_user('editor', msg=l_('Only for the editor')))
61
    def editor_user_only(self, **kw):
62
        """Illustrate how a page exclusive for the editor works."""
63
        return dict(page='editor stuff')
64

  
65
    @expose('vigigraph.templates.login')
66
    def login(self, came_from=url('/')):
67
        """Start the user login."""
68
        login_counter = request.environ['repoze.who.logins']
69
        if login_counter > 0:
70
            flash(_('Wrong credentials'), 'warning')
71
        return dict(page='login', login_counter=str(login_counter),
72
                    came_from=came_from)
73
    
74
    @expose()
75
    def post_login(self, came_from=url('/')):
76
        """
77
        Redirect the user to the initially requested page on successful
78
        authentication or redirect her back to the login page if login failed.
79
        
80
        """
81
        if not request.identity:
82
            login_counter = request.environ['repoze.who.logins'] + 1
83
            redirect(url('/login', came_from=came_from, __logins=login_counter))
84
        userid = request.identity['repoze.who.userid']
85
        flash(_('Welcome back, %s!') % userid)
86
        redirect(came_from)
87

  
88
    @expose()
89
    def post_logout(self, came_from=url('/')):
90
        """
91
        Redirect the user to the initially requested page on logout and say
92
        goodbye as well.
93
        
94
        """
95
        flash(_('We hope to see you soon!'))
96
        redirect(came_from)
vigigraph/controllers/secure.py
1
# -*- coding: utf-8 -*-
2
"""Sample controller with all its actions protected."""
3
from tg import expose, flash
4
from pylons.i18n import ugettext as _, lazy_ugettext as l_
5
from repoze.what.predicates import has_permission
6
#from dbsprockets.dbmechanic.frameworks.tg2 import DBMechanic
7
#from dbsprockets.saprovider import SAProvider
8

  
9
from vigigraph.lib.base import BaseController
10
#from vigigraph.model import DBSession, metadata
11

  
12
__all__ = ['SecureController']
13

  
14

  
15
class SecureController(BaseController):
16
    """Sample controller-wide authorization"""
17
    
18
    # The predicate that must be met for all the actions in this controller:
19
    allow_only = has_permission('manage',
20
                                msg=l_('Only for people with the "manage" permission'))
21
    
22
    @expose('vigigraph.templates.index')
23
    def index(self):
24
        """Let the user know that's visiting a protected controller."""
25
        flash(_("Secure Controller here"))
26
        return dict(page='index')
27
    
28
    @expose('vigigraph.templates.index')
29
    def some_where(self):
30
        """Let the user know that this action is protected too."""
31
        return dict(page='some_where')
vigigraph/controllers/template.py
1
# -*- coding: utf-8 -*-
2
"""Fallback controller."""
3

  
4
from vigigraph.lib.base import BaseController
5

  
6
__all__ = ['TemplateController']
7

  
8

  
9
class TemplateController(BaseController):
10
    """
11
    The fallback controller for vigigraph.
12
    
13
    By default, the final controller tried to fulfill the request
14
    when no other routes match. It may be used to display a template
15
    when all else fails, e.g.::
16
    
17
        def view(self, url):
18
            return render('/%s' % url)
19
    
20
    Or if you're using Mako and want to explicitly send a 404 (Not
21
    Found) response code when the requested template doesn't exist::
22
    
23
        import mako.exceptions
24
        
25
        def view(self, url):
26
            try:
27
                return render('/%s' % url)
28
            except mako.exceptions.TopLevelLookupException:
29
                abort(404)
30
    
31
    """
32
    
33
    def view(self, url):
34
        """Abort the request with a 404 HTTP status code."""
35
        abort(404)
vigigraph/i18n/ru/LC_MESSAGES/vigigraph.po
1
# Russian translations for ${package}.
2
# Copyright (C) 2008 ORGANIZATION
3
# This file is distributed under the same license as the ${package} project.
4
# FIRST AUTHOR <EMAIL@ADDRESS>, 2008.
5
#
6
msgid ""
7
msgstr ""
8
"Project-Id-Version: ${package} 0.0.0\n"
9
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
10
"POT-Creation-Date: 2008-01-13 14:00+0200\n"
11
"PO-Revision-Date: 2008-01-13 14:00+0200\n"
12
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
"Language-Team: ru <LL@li.org>\n"
14
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
15
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
16
"MIME-Version: 1.0\n"
17
"Content-Type: text/plain; charset=utf-8\n"
18
"Content-Transfer-Encoding: 8bit\n"
19
"Generated-By: Babel 0.9.1\n"
20

  
21
#: ${package}/controllers/root.py:13
22
msgid "Your application is now running"
23
msgstr "Ваши приложение успешно запущено"
24

  
vigigraph/lib/__init__.py
1
# -*- coding: utf-8 -*-
2

  
vigigraph/lib/app_globals.py
1
# -*- coding: utf-8 -*-
2

  
3
"""The application's Globals object"""
4

  
5
__all__ = ['Globals']
6

  
7

  
8
class Globals(object):
9
    """Container for objects available throughout the life of the application.
10

  
11
    One instance of Globals is created during application initialization and
12
    is available during requests via the 'app_globals' variable.
13

  
14
    """
15

  
16
    def __init__(self):
17
        """Do nothing, by default."""
18
        pass
vigigraph/lib/base.py
1
# -*- coding: utf-8 -*-
2

  
3
"""The base Controller API."""
4

  
5
from tg import TGController, tmpl_context
6
from tg.render import render
7
from tg import request
8
from pylons.i18n import _, ungettext, N_
9
from tw.api import WidgetBunch
10
import vigigraph.model as model
11

  
12
__all__ = ['Controller', 'BaseController']
13

  
14

  
15
class BaseController(TGController):
16
    """
17
    Base class for the controllers in the application.
18

  
19
    Your web application should have one of these. The root of
20
    your application is used to compute URLs used by your app.
21

  
22
    """
23

  
24
    def __call__(self, environ, start_response):
25
        """Invoke the Controller"""
26
        # TGController.__call__ dispatches to the Controller method
27
        # the request is routed to. This routing information is
28
        # available in environ['pylons.routes_dict']
29

  
30
        request.identity = request.environ.get('repoze.who.identity')
31
        tmpl_context.identity = request.identity
32
        return TGController.__call__(self, environ, start_response)
vigigraph/lib/helpers.py
1
# -*- coding: utf-8 -*-
2

  
3
"""WebHelpers used in vigigraph."""
4

  
5
from webhelpers import date, feedgenerator, html, number, misc, text
vigigraph/model/__init__.py
1
# -*- coding: utf-8 -*-
2
"""The application's model objects"""
3

  
4
from zope.sqlalchemy import ZopeTransactionExtension
5
from sqlalchemy.orm import scoped_session, sessionmaker
6
#from sqlalchemy import MetaData
7
from sqlalchemy.ext.declarative import declarative_base
8

  
9
# Global session manager: DBSession() returns the Thread-local
10
# session object appropriate for the current web request.
11
maker = sessionmaker(autoflush=True, autocommit=False,
12
                     extension=ZopeTransactionExtension())
13
DBSession = scoped_session(maker)
14

  
15
# Base class for all of our model classes: By default, the data model is
16
# defined with SQLAlchemy's declarative extension, but if you need more
17
# control, you can switch to the traditional method.
18
DeclarativeBase = declarative_base()
19

  
20
# There are two convenient ways for you to spare some typing.
21
# You can have a query property on all your model classes by doing this:
22
# DeclarativeBase.query = DBSession.query_property()
23
# Or you can use a session-aware mapper as it was used in TurboGears 1:
24
# DeclarativeBase = declarative_base(mapper=DBSession.mapper)
25

  
26
# Global metadata.
27
# The default metadata is the one from the declarative base.
28
metadata = DeclarativeBase.metadata
29

  
30
# If you have multiple databases with overlapping table names, you'll need a
31
# metadata for each database. Feel free to rename 'metadata2'.
32
#metadata2 = MetaData()
33

  
34
#####
35
# Generally you will not want to define your table's mappers, and data objects
36
# here in __init__ but will want to create modules them in the model directory
37
# and import them at the bottom of this file.
38
#
39
######
40

  
41
def init_model(engine):
42
    """Call me before using any of the tables or classes in the model."""
43

  
44
    DBSession.configure(bind=engine)
45
    # If you are using reflection to introspect your database and create
46
    # table objects for you, your tables must be defined and mapped inside
47
    # the init_model function, so that the engine is available if you
48
    # use the model outside tg2, you need to make sure this is called before
49
    # you use the model.
50

  
51
    #
52
    # See the following example:
53

  
54
    #global t_reflected
55

  
56
    #t_reflected = Table("Reflected", metadata,
57
    #    autoload=True, autoload_with=engine)
58

  
59
    #mapper(Reflected, t_reflected)
60

  
61
# Import your model modules here.
62
from vigigraph.model.auth import User, Group, Permission
vigigraph/model/auth.py
1
# -*- coding: utf-8 -*-
2
"""
3
Auth* related model.
4

  
5
This is where the models used by :mod:`repoze.who` and :mod:`repoze.what` are
6
defined.
7

  
8
It's perfectly fine to re-use this definition in the vigigraph application,
9
though.
10

  
11
"""
12
import os
13
from datetime import datetime
14
import sys
15
try:
16
    from hashlib import sha1
17
except ImportError:
18
    sys.exit('ImportError: No module named hashlib\n'
19
             'If you are on python2.4 this library is not part of python. '
20
             'Please install it. Example: easy_install hashlib')
21

  
22
from sqlalchemy import Table, ForeignKey, Column
23
from sqlalchemy.types import Unicode, Integer, DateTime
24
from sqlalchemy.orm import relation, synonym
25

  
26
from vigigraph.model import DeclarativeBase, metadata, DBSession
27

  
28
__all__ = ['User', 'Group', 'Permission']
29

  
30

  
31
#{ Association tables
32

  
33

  
34
# This is the association table for the many-to-many relationship between
35
# groups and permissions. This is required by repoze.what.
36
group_permission_table = Table('tg_group_permission', metadata,
37
    Column('group_id', Integer, ForeignKey('tg_group.group_id',
38
        onupdate="CASCADE", ondelete="CASCADE")),
39
    Column('permission_id', Integer, ForeignKey('tg_permission.permission_id',
40
        onupdate="CASCADE", ondelete="CASCADE"))
41
)
42

  
43
# This is the association table for the many-to-many relationship between
44
# groups and members - this is, the memberships. It's required by repoze.what.
45
user_group_table = Table('tg_user_group', metadata,
46
    Column('user_id', Integer, ForeignKey('tg_user.user_id',
47
        onupdate="CASCADE", ondelete="CASCADE")),
48
    Column('group_id', Integer, ForeignKey('tg_group.group_id',
49
        onupdate="CASCADE", ondelete="CASCADE"))
50
)
51

  
52

  
53
#{ The auth* model itself
54

  
55

  
56
class Group(DeclarativeBase):
57
    """
58
    Group definition for :mod:`repoze.what`.
59
    
60
    Only the ``group_name`` column is required by :mod:`repoze.what`.
61
    
62
    """
63
    
64
    __tablename__ = 'tg_group'
65
    
66
    #{ Columns
67
    
68
    group_id = Column(Integer, autoincrement=True, primary_key=True)
69
    
70
    group_name = Column(Unicode(16), unique=True, nullable=False)
71
    
72
    display_name = Column(Unicode(255))
73
    
74
    created = Column(DateTime, default=datetime.now)
75
    
76
    #{ Relations
77
    
78
    users = relation('User', secondary=user_group_table, backref='groups')
79
    
80
    #{ Special methods
81
    
82
    def __repr__(self):
83
        return '<Group: name=%s>' % self.group_name
84
    
85
    def __unicode__(self):
86
        return self.group_name
87
    
88
    #}
89

  
90

  
91
# The 'info' argument we're passing to the email_address and password columns
92
# contain metadata that Rum (http://python-rum.org/) can use generate an
93
# admin interface for your models.
94
class User(DeclarativeBase):
95
    """
96
    User definition.
97
    
98
    This is the user definition used by :mod:`repoze.who`, which requires at
99
    least the ``user_name`` column.
100
    
101
    """
102
    __tablename__ = 'tg_user'
103
    
104
    #{ Columns
105

  
106
    user_id = Column(Integer, autoincrement=True, primary_key=True)
107
    
108
    user_name = Column(Unicode(16), unique=True, nullable=False)
109
    
110
    email_address = Column(Unicode(255), unique=True, nullable=False,
111
                           info={'rum': {'field':'Email'}})
112
    
113
    display_name = Column(Unicode(255))
114
    
115
    _password = Column('password', Unicode(80),
116
                       info={'rum': {'field':'Password'}})
117
    
118
    created = Column(DateTime, default=datetime.now)
119
    
120
    #{ Special methods
121

  
122
    def __repr__(self):
123
        return '<User: email="%s", display name="%s">' % (
124
                self.email_address, self.display_name)
125

  
126
    def __unicode__(self):
127
        return self.display_name or self.user_name
128
    
129
    #{ Getters and setters
130

  
131
    @property
132
    def permissions(self):
133
        """Return a set of strings for the permissions granted."""
134
        perms = set()
135
        for g in self.groups:
136
            perms = perms | set(g.permissions)
137
        return perms
138

  
139
    @classmethod
140
    def by_email_address(cls, email):
141
        """Return the user object whose email address is ``email``."""
142
        return DBSession.query(cls).filter(cls.email_address==email).first()
143

  
144
    @classmethod
145
    def by_user_name(cls, username):
146
        """Return the user object whose user name is ``username``."""
147
        return DBSession.query(cls).filter(cls.user_name==username).first()
148

  
149
    def _set_password(self, password):
150
        """Hash ``password`` on the fly and store its hashed version."""
151
        hashed_password = password
152
        
153
        if isinstance(password, unicode):
154
            password_8bit = password.encode('UTF-8')
155
        else:
156
            password_8bit = password
157

  
158
        salt = sha1()
159
        salt.update(os.urandom(60))
160
        hash = sha1()
161
        hash.update(password_8bit + salt.hexdigest())
162
        hashed_password = salt.hexdigest() + hash.hexdigest()
163

  
164
        # Make sure the hashed password is an UTF-8 object at the end of the
165
        # process because SQLAlchemy _wants_ a unicode object for Unicode
166
        # columns
167
        if not isinstance(hashed_password, unicode):
168
            hashed_password = hashed_password.decode('UTF-8')
169

  
170
        self._password = hashed_password
171

  
172
    def _get_password(self):
173
        """Return the hashed version of the password."""
174
        return self._password
175

  
176
    password = synonym('_password', descriptor=property(_get_password,
177
                                                        _set_password))
178
    
179
    #}
180
    
181
    def validate_password(self, password):
182
        """
183
        Check the password against existing credentials.
184
        
185
        :param password: the password that was provided by the user to
186
            try and authenticate. This is the clear text version that we will
187
            need to match against the hashed one in the database.
188
        :type password: unicode object.
189
        :return: Whether the password is valid.
190
        :rtype: bool
191

  
192
        """
193
        hashed_pass = sha1()
194
        hashed_pass.update(password + self.password[:40])
195
        return self.password[40:] == hashed_pass.hexdigest()
196

  
197

  
198
class Permission(DeclarativeBase):
199
    """
200
    Permission definition for :mod:`repoze.what`.
201
    
202
    Only the ``permission_name`` column is required by :mod:`repoze.what`.
203
    
204
    """
205
    
206
    __tablename__ = 'tg_permission'
207
    
208
    #{ Columns
209

  
210
    permission_id = Column(Integer, autoincrement=True, primary_key=True)
211
    
212
    permission_name = Column(Unicode(16), unique=True, nullable=False)
213
    
214
    description = Column(Unicode(255))
215
    
216
    #{ Relations
217
    
218
    groups = relation(Group, secondary=group_permission_table,
219
                      backref='permissions')
220
    
221
    #{ Special methods
222
    
223
    def __repr__(self):
224
        return '<Permission: name=%s>' % self.permission_name
225

  
226
    def __unicode__(self):
227
        return self.permission_name
228
    
229
    #}
230

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff