NEW! Now with i18n support, take a look at the demo in Spanish or English or configure your browser to send the appropiate Accept-Language headers. (This page you're reading hasn't been translated though)
Thanks for taking a look. Funtionality is quite limited at the moment but hey, development
began on the 26th of June... ;)
(I was busy building toscawidgets.org and writting docs before that)
Go ahead, play around. Model objects are listed at your left. List them, edit them, delete them, create new ones...
First download virtualenv to create an isolated Python environment.
$ python virtualenv.py RumDemo
$ cd RumDemo
$ source bin/activate
(In Windows you need to execute bin/activate.bat)
$ easy_install -f http://toscawidgets.org/download SQLAlchemy==0.4.6 Paste WebError RumAlchemy tw.rum
Those lines should get you all the software you need. Note that we "pin" SQLAlchemy 0.4.6 since, although
0.5 can be introspected, etc.. there is some bug that drives the app into infinite recursion with model
inheritance which I need to investigate and report.
WebError is helpful for debugging and Paste seems to have it's metadata messed up in PyPI at the moment
so it can't be pulled automatically.
You can copy and paste the code below, making sure you remove the 'default_directories' hardcoded path, or you can download a clean version from here
import sys import logging import datetime from optparse import OptionParser from sqlalchemy import Column, ForeignKey, Table, PrimaryKeyConstraint from sqlalchemy.types import * from sqlalchemy.orm import relation from sqlalchemy.ext.declarative import declarative_base from rumalchemy.tests.model2 import * from rum import FieldFactory, _, N_, fields # # Metadata declaration # N_("person"); N_("persons") FieldFactory.fields(Person, ( fields.Unicode('name', label=_('Name'), required=True), fields.Integer('age', label=_('Age'), range=(0,150)), fields.UnicodeText('notes', label=_("Notes")), "rentals", "type", "version", )) N_("actor"); N_("actors") FieldFactory.fields(Actor, ( fields.Unicode('name', label=_('Name'), required=True), fields.Integer('age', label=_('Age'), range=(0,150)), fields.Integer('oscars_won', label=_("# Oscars won"), range=(0,10)), fields.UnicodeText('notes', label=_("Notes")), "rentals", "movies", "type", "version", )) N_("director"); N_("directors") FieldFactory.fields(Director, ( fields.Unicode('name', label=_('Name'), required=True), fields.Integer('age', label=_('Age'), range=(0,150)), fields.Integer('chairs_broken', label=_("# Chairs broken"), range=(0,50)), fields.UnicodeText('notes', label=_("Notes")), "rentals", "movies", "type", "version", )) N_("genre"); N_("genres") FieldFactory.fields(Genre, ( fields.Unicode('name', label=_('Name'), required=True), "movies", )) N_("movie"); N_("movies") FieldFactory.fields(Movie, ( fields.Unicode('title', label=_('Title'), required=True), "genre", "director", "actors", fields.JPEGImage('poster', label=_('Poster in JPEG format')), fields.Date('filmed_on', label=_('Filmed on')), fields.HTMLText("synopsis", label=_('Synopsis')), )) N_("rental"); N_("rentals") FieldFactory.fields(Rental, ( "person", "movie", fields.DateTime('date', label=_('Rental date')), fields.DateTime('due_date', label=_('Due date')), fields.Boolean('is_overtime', label=_('Is overtime?'), read_only=True), )) N_("movieInGenre"); N_("moviesInGenres") FieldFactory.fields(MovieInGenre, ( fields.Unicode('title', label=_('Title'), required=True), fields.Unicode("genre_name", label=_('Genre name'), required=True), fields.JPEGImage('poster', label=_('Poster in JPEG format')), fields.Date('filmed_on', label=_('Filmed on')), fields.HTMLText("synopsis", label=_('Synopsis')), )) # # A parser for command line options # parser = OptionParser() parser.add_option('', '--dburl', dest='url', help='SQLAlchemy database uri (eg: postgres:///somedatabase)', default='sqlite:///rum_demo.db') parser.add_option('-d', '--debug', dest='debug', help='Turn on debug mode', default=False, action='store_true') # # Makes the app # def load_app(url, debug=False): from pkg_resources import require require('RumAlchemy', 'tw.rum') from rum import RumApp models = [Person, Genre, Actor, Director, Movie, Rental, MovieInGenre] return RumApp({ 'debug': debug, 'rum.repositoryfactory': { 'use': 'sqlalchemy', 'models': models, 'sqlalchemy.url': url, 'session.transactional': True, }, 'templating': { 'search_path': ['/home/toscawidgets/RumDemo/templates'], }, 'rum.viewfactory': { 'use': 'toscawidgets', }, 'rum.translator': { 'use': 'default', 'locales': ['en', 'es'], }, }) # # Main calling point # def main(argv=None): from sqlalchemy import create_engine from paste.deploy import loadserver logging.basicConfig(level=logging.INFO, stream=sys.stderr) opts, args = parser.parse_args(argv) Model.metadata.create_all(bind=create_engine(opts.url)) app = load_app(opts.url, opts.debug) server = loadserver('egg:Paste#http') try: server(app) except (KeyboardInterrupt, SystemExit): print "Bye!" if __name__ == '__main__': sys.exit(main(sys.argv))
.json suffix to the end of the URL. or
craft a request that lists application/json in it's Accepts header._meta method.
See example.
Of course, this metadata can also be requested in JSON format to generate the UI on the client.Feedback will be greatly appreciated :) Development is going fast now and there's no legacy API to keep compatible with so your input can have a great impact on the direction development takes. I'm also in the look for fellow developers so if you're interested in joining forces by all means drop me a note!.
We've created a mailing list to discuss Rum. Please join us at rum-discuss.
Although I personally find them pretty meaningless (specially the test coverage since I know I'm not yet tesing many things but the coverage is still ridiculously high) you might find them interesting.
Name Stmts Exec Cover Missing
----------------------------------------------------
rum 30 30 100%
rum.component 66 66 100%
rum.controller 225 224 99% 364
rum.exceptions 11 11 100%
rum.fields 63 63 100%
rum.genericfunctions 3 3 100%
rum.interfaces 54 54 100%
rum.json 11 4 36% 6-8, 12-15
rum.middleware 32 31 96% 36
rum.repository 119 118 99% 231
rum.router 170 170 100%
rum.templating 9 9 100%
rum.util 22 22 100%
rum.view 15 15 100%
rum.widgets 3 3 100%
rum.wsgiapp 124 124 100%
rum.wsgiutil 14 14 100%
----------------------------------------------------
TOTAL 971 961 98%
----------------------------------------------------------------------
Ran 140 tests in 27.017s
lines code doc comment blank file
------- ------- ------- ------- ------- -----------------------------------
60 49 0 5 6 rum/__init__.py
125 71 37 5 12 rum/component.py
416 304 23 20 69 rum/controller.py
15 11 0 0 4 rum/exceptions.py
399 65 283 18 33 rum/fields.py
9 8 0 0 1 rum/genericfunctions.py
262 69 142 5 46 rum/interfaces.py
15 13 0 0 2 rum/json.py
48 35 0 7 6 rum/middleware.py
236 139 48 7 42 rum/repository.py
238 183 1 15 39 rum/router.py
10 9 0 0 1 rum/templating.py
0 0 0 0 0 rum/tests/__init__.py *
46 34 0 0 12 rum/tests/model.py *
95 73 0 3 19 rum/tests/test_component.py *
303 248 4 5 46 rum/tests/test_controller.py *
97 66 0 13 18 rum/tests/test_repository.py *
699 605 0 3 91 rum/tests/test_router.py *
42 33 0 0 9 rum/tests/test_view.py *
40 28 4 0 8 rum/tests/test_wsgiapp.py *
38 27 6 1 4 rum/testutil.py
78 24 47 3 4 rum/util.py
52 16 26 2 8 rum/view.py
23 7 0 14 2 rum/widgets/__init__.py
205 154 18 2 31 rum/wsgiapp.py
18 14 0 0 4 rum/wsgiutil.py
3569 2285 639 128 517 [total]
Test code: 1087 other code: 1198 ratio: 1:0.9 code to tests
2285 lines of code, 26 modules, 3 packages.
Name Stmts Exec Cover Missing
------------------------------------------------------------
rumalchemy 3 3 100%
rumalchemy.json 3 3 100%
rumalchemy.repository 116 74 63% 76-78, 121-122, 126-130, 134-136, 143-146, 148-152, 155-158, 166, 172, 178, 185-186, 194-199, 202-206, 209, 212, 230
rumalchemy.util 10 7 70% 13-15
rumalchemy.validators 28 15 53% 19, 23, 26-33, 35-41
rumalchemy.viewfactory 88 78 88% 76, 104, 108, 118, 140-141, 162-163, 195-196
rumalchemy.widgets 45 36 80% 17-26
rumalchemy.widgets.grid 19 14 73% 22-23, 26-29
rumalchemy.widgets.templates 0 0 100%
------------------------------------------------------------
TOTAL 312 230 73%
----------------------------------------------------------------------
Ran 9 tests in 12.054s
lines code doc comment blank file
------- ------- ------- ------- ------- -----------------------------------
4 3 0 1 0 rumalchemy/__init__.py
4 3 0 0 1 rumalchemy/json.py
232 153 35 8 36 rumalchemy/repository.py
0 0 0 0 0 rumalchemy/tests/__init__.py *
88 62 0 5 21 rumalchemy/tests/model.py *
38 30 0 1 7 rumalchemy/tests/test_resource_introspection.py *
54 43 0 1 10 rumalchemy/tests/test_sawidget_factory.py *
15 11 0 1 3 rumalchemy/util.py
42 32 0 3 7 rumalchemy/validators.py
198 137 4 23 34 rumalchemy/viewfactory.py
99 47 34 3 15 rumalchemy/widgets/__init__.py
34 29 0 1 4 rumalchemy/widgets/grid.py
0 0 0 0 0 rumalchemy/widgets/templates/__init__.py
808 550 73 47 138 [total]
Test code: 135 other code: 415 ratio: 1:0.3 code to tests
© 2008 Alberto Valverde González.
Sponsored by Google's Summer of code 2008 program for the TurboGears organization. Mentored by Mark Ramm
This software is released under the terms of the MIT License