' % (
self.email_address, self.display_name)
@property
def permissions(self):
perms = set()
for g in self.groups:
perms = perms | set(g.permissions)
return perms
@classmethod
def by_email_address(cls, email):
"""A class method that can be used to search users
based on their email addresses since it is unique.
"""
return DBSession.query(cls).filter(cls.email_address==email).first()
@classmethod
def by_user_name(cls, username):
"""A class method that permits to search users
based on their user_name attribute.
"""
return DBSession.query(cls).filter(cls.user_name==username).first()
def _set_password(self, password):
"""encrypts password on the fly using the encryption
algo defined in the configuration
"""
#unfortunately, this causes coverage not to work
#self._password = self._encrypt_password(algorithm, password)
def _get_password(self):
"""returns password
"""
return self._password
password = synonym('password', descriptor=property(_get_password,
_set_password))
def _encrypt_password(self, algorithm, password):
"""Hash the given password with the specified algorithm. Valid values
for algorithm are 'md5' and 'sha1'. All other algorithm values will
be essentially a no-op."""
hashed_password = password
if isinstance(password, unicode):
password_8bit = password.encode('UTF-8')
else:
password_8bit = password
#creates a salted sha password
salt = sha1()
salt.update(os.urandom(60))
hash = sha1()
hash.update(password_8bit + salt.hexdigest())
hashed_password = salt.hexdigest() + hash.hexdigest()
# make sure the hased password is an UTF-8 object at the end of the
# process because SQLAlchemy _wants_ a unicode object for Unicode columns
if not isinstance(hashed_password, unicode):
hashed_password = hashed_password.decode('UTF-8')
return hashed_password
def validate_password(self, password):
"""Check the password against existing credentials.
this method _MUST_ return a boolean.
@param password: the password that was provided by the user to
try and authenticate. This is the clear text version that we will
need to match against the (possibly) encrypted one in the database.
@type password: unicode object
"""
hashed_pass = sha1()
hashed_pass.update(password + self.password[:40])
return self.password[40:] == hashed_pass.hexdigest()
class Permission(DeclarativeBase):
"""A relationship that determines what each Group can do
"""
__tablename__ = 'tg_permission'
permission_id = Column(Integer, autoincrement=True, primary_key=True)
permission_name = Column(Unicode(16), unique=True)
description = Column(Unicode(255))
groups = relation(Group, secondary=group_permission_table,
backref='permissions')
class Example(DeclarativeBase):
__tablename__ = 'example'
example_id = Column(Integer, primary_key=True)
created = Column(DateTime, default=datetime.now)
blob = Column(BLOB )
binary = Column(Binary )
boolean = Column(Boolean )
char = Column(CHAR(200) )
cLOB = Column(CLOB(200) )
date_ = Column( DATE )
datetime_ = Column( DATETIME )
decimal = Column(DECIMAL )
date = Column(Date )
dateTime = Column(DateTime )
float__ = Column( FLOAT )
float_ = Column(Float )
int_ = Column(INT )
integer = Column(Integer, default=10)
# (NCHAR = #Column NCHAR )
numeric = Column(Numeric )
pickletype = Column(PickleType )
smallint = Column(SMALLINT )
smalliunteger = Column(SmallInteger )
string = Column(String(20) )
text = Column(TEXT(20) )
time_ = Column(TIME )
time = Column(Time )
timestamp = Column(TIMESTAMP )
unicode_ = Column(Unicode(200) )
varchar = Column(VARCHAR(200) )
password = Column(String(20) )
class Document(DeclarativeBase):
__tablename__ = 'document'
document_id = Column(Integer, primary_key=True)
created = Column(DateTime, default=datetime.now)
blob = Column(BLOB )
owner = Column(Integer, ForeignKey('tg_user.user_id'))
url = Column(String(500))
def _get_address(self):
return self.url
def _set_address(self, value):
self.url = value
address = synonym('address', descriptor=property(_get_address,
_set_address))
#model_initialized = False
def init_model(engine):
global model_initialized
DBSession.configure(bind=engine) python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/test/test_controller.py 0000644 0001750 0001750 00000023470 11160515153 025607 0 ustar zack zack import os, sys
import tgext.admin
from tg.test_stack import TestConfig, app_from_config
from tgext.admin.test.model import User, Group, Town
from tg.util import Bunch
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from tgext.admin.test.model import metadata, DBSession
root = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, root)
test_db_path = 'sqlite:///'+root+'/test.db'
paths=Bunch(
root=root,
controllers=os.path.join(root, 'controllers'),
static_files=os.path.join(root, 'public'),
templates=os.path.join(root, 'templates')
)
base_config = TestConfig(folder = 'rendering',
values = {'use_sqlalchemy': True,
'model':tgext.admin.test.model,
'session':tgext.admin.test.model.DBSession,
'pylons.helpers': Bunch(),
'use_legacy_renderer': False,
# this is specific to mako
# to make sure inheritance works
'use_dotted_templatenames': True,
'paths':paths,
'package':tgext.admin.test,
'sqlalchemy.url':test_db_path
}
)
def setup_records(session):
#session.expunge_all()
user = User()
user.user_name = u'asdf'
user.email_address = u"asdf@asdf.com"
user.password = u"asdf"
session.add(user)
arvada = Town(name=u'Arvada')
session.add(arvada)
session.flush()
user.town = arvada
session.add(Town(name=u'Denver'))
session.add(Town(name=u'Golden'))
session.add(Town(name=u'Boulder'))
#test_table.insert(values=dict(BLOB=FieldStorage('asdf', StringIO()).value)).execute()
#user_reference_table.insert(values=dict(user_id=user.user_id)).execute()
# print user.user_id
for i in ['managers', 'users']:
group = Group(group_name=unicode(i))
session.add(group)
user.groups.append(group)
session.flush()
return user
def setup():
engine = create_engine(test_db_path)
metadata.bind = engine
metadata.drop_all()
metadata.create_all()
session = sessionmaker(bind=engine)()
setup_records(session)
session.commit()
def teardown():
os.remove(test_db_path[10:])
class TestAdminController:
def __init__(self, *args, **kargs):
self.app = app_from_config(base_config)
def test_index(self):
resp = self.app.get('/admin/')
assert 'Document' in resp, resp
def test_list_documents(self):
resp = self.app.get('/admin/documents').follow()
assert """
__actions__
| document_id
| created
| blob
| owner
| url
| address
|
""" in resp, resp
def _test_documents_new(self):
resp = self.app.get('/admin/documents/new')
assert """
|
|
""" in resp, resp
def test_get_users(self):
resp = self.app.get('/admin/users/')
assert """
__actions__
| _password
| user_id
| user_name
| email_address
| display_name
| created
| town_id
| town
| password
| groups
|
""" in resp, resp
def test_get_users_json(self):
resp = self.app.get('/admin/users.json')
assert """{"numRows": 1, "items": [{"town": "Arvada", "user_id": "1", "created":""" in resp, resp
def test_edit_user(self):
resp = self.app.get('/admin/users/1/edit')
assert """
|
|
""" in resp, resp
def test_edit_user_success(self):
resp = self.app.post('/admin/users/1/', params={'sprox_id':'put__User',
'_method':'PUT',
'user_name':'someone',
'display_name':'someone2',
'email_address':'asdf2@asdf2.com',
'_password':'pass',
'password':'pass',
'town':'1',
'town_id':'1',
'user_id':'1',
'created':'2009-01-11 13:54:01'}).follow()
#resp = self.app.get('/admin/user.json')
#assert """"email_address": "asdf2@asdf2.com",""" in resp, resp
resp = self.app.post('/admin/users/1/', params={'sprox_id':'put__User',
'_method':'PUT',
'user_name':'someone',
'display_name':'someone2',
'email_address':'asdf@asdf.com',
'_password':'pass',
'password':'pass',
'town':'1',
'town_id':'1',
'user_id':'1',
'created':'2009-01-11 13:54:01'}).follow()
# resp = self.app.get('/admin/user.json')
# assert """"email_address": "asdf@asdf.com",""" in resp, resp
#this tests causes other tests to fail, so, no go
def _test_add_and_remove_user(self):
resp = self.app.post('/admin/users/', params={'sprox_id':'add__User',
'user_name':'someone',
'display_name':'someone2',
'email_address':'asdf2@asdf2.com',
'_password':'pass',
'password':'pass',
'town':'1',
'town_id':'1',
'user_id':'2',
'created':'2009-01-11 13:54:01'}).follow()
#assert 'asdf2@asdf2' in resp, resp
resp = self.app.get('/admin/users/2/', params={'user_id':'2', '_method':'DELETE'}).follow()
#assert 'asdf2@asdf2' not in resp, resp
def test_add_user_existing_username(self):
resp = self.app.post('/admin/users/create', params={'sprox_id':'add__User',
'user_name':u'asdf',
'display_name':'someone2',
'email_address':'asdf2@asdf2.com',
'_password':'pass',
'password':'pass',
'town':'1',
'town_id':'1',
'user_id':'2',
'created':'2009-01-11 13:54:01'})
assert 'That value already exists' in resp, resp
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/test/lib/ 0000755 0001750 0001750 00000000000 11236060527 022557 5 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/test/lib/helpers.py 0000644 0001750 0001750 00000000000 11135653114 024557 0 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/test/lib/__init__.py 0000644 0001750 0001750 00000000000 11135653114 024654 0 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/test/lib/base.py 0000644 0001750 0001750 00000000000 11135653114 024027 0 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/test/controllers/ 0000755 0001750 0001750 00000000000 11236060527 024357 5 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/test/controllers/root.py 0000644 0001750 0001750 00000000522 11135653114 025711 0 ustar zack zack from tg.controllers import TGController
from tgext.admin import AdminController
from tgext.admin.test.model import DBSession
import tgext.admin.test.model as model
class UnSecuredAdminController(AdminController):
allow_only = None
class RootController(TGController):
admin =UnSecuredAdminController(model, DBSession)
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/test/controllers/__init__.py 0000644 0001750 0001750 00000000000 11135653114 026454 0 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/test/base.py 0000644 0001750 0001750 00000003431 11135653114 023274 0 ustar zack zack # -*- coding: utf-8 -*-
import os, shutil
from unittest import TestCase
from xmlrpclib import loads, dumps
import beaker
from paste.registry import RegistryManager
from webtest import TestApp
from paste import httpexceptions
import tg
from routes import Mapper
from tg.controllers import TGController
from pylons.testutil import ControllerWrap, SetupCacheGlobal
from beaker.middleware import CacheMiddleware
data_dir = os.path.dirname(os.path.abspath(__file__))
session_dir = os.path.join(data_dir, 'session')
def setup_session_dir():
if not os.path.exists(session_dir):
os.makedirs(session_dir)
def teardown_session_dir():
shutil.rmtree(session_dir, ignore_errors=True)
default_environ = {
'pylons.use_webob' : True,
'pylons.routes_dict': dict(action='index'),
'paste.config': dict(global_conf=dict(debug=True))
}
default_map = Mapper()
# Setup a default route for the error controller:
default_map.connect('error/:action/:id', controller='error')
# Setup a default route for the root of object dispatch
default_map.connect('*url', controller='root', action='routes_placeholder')
def make_app(controller_klass=None, environ=None):
"""Creates a `TestApp` instance."""
if environ is None:
environ = {}
environ['pylons.routes_dict'] = {}
environ['pylons.routes_dict']['action'] = "routes_placeholder"
if controller_klass is None:
controller_klass = TGController
app = ControllerWrap(controller_klass)
app = SetupCacheGlobal(app, environ, setup_cache=True, setup_session=True)
app = RegistryManager(app)
app = beaker.middleware.SessionMiddleware(app, {}, data_dir=session_dir)
app = CacheMiddleware(app, {}, data_dir=os.path.join(data_dir, 'cache'))
app = httpexceptions.make_middleware(app)
return TestApp(app)
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/controller.py 0000644 0001750 0001750 00000006066 11175427560 023605 0 ustar zack zack """Admin Controller"""
from sqlalchemy.orm import class_mapper
import inspect
from tg.controllers import TGController
from tg.decorators import with_trailing_slash, override_template, expose
from tg.exceptions import HTTPNotFound
Rum = None
from tgext.crud import CrudRestController
from config import AdminConfig
engine = 'genshi'
try:
import chameleon.genshi
import pylons.config
if 'renderers' in pylons.config and 'chameleon_genshi' in pylons.config['renderers']:
engine = 'chameleon_genshi'
except ImportError:
pass
from repoze.what.predicates import in_group
class AdminController(TGController):
"""
A basic controller that handles User Groups and Permissions for a TG application.
"""
allow_only = in_group('managers')
def __init__(self, models, session, config_type=None, translations=None):
super(AdminController, self).__init__()
if translations is None:
translations = {}
if config_type is None:
config = AdminConfig(models, translations)
else:
config = config_type(models, translations)
if config.allow_only:
self.allow_only = config.allow_only
self.config = config
self.session = session
self.default_index_template = ':'.join(self.index.decoration.engines.get('text/html')[:2])
if self.config.default_index_template:
self.default_index_template = self.config.default_index_template
@with_trailing_slash
@expose('tgext.admin.templates.index')
def index(self):
#overrides the template for this method
original_index_template = self.index.decoration.engines['text/html']
new_engine = self.default_index_template.split(':')
new_engine.extend(original_index_template[2:])
self.index.decoration.engines['text/html'] = new_engine
return dict(models=[model.__name__ for model in self.config.models.values()])
def _make_controller(self, config, session):
m = config.model
Controller = config.defaultCrudRestController
class ModelController(Controller):
model = m
table = config.table_type(session)
table_filler = config.table_filler_type(session)
new_form = config.new_form_type(session)
new_filler = config.new_filler_type(session)
edit_form = config.edit_form_type(session)
edit_filler = config.edit_filler_type(session)
allow_only = config.allow_only
menu_items = None
if self.config.include_left_menu:
menu_items = self.config.models
return ModelController(session, menu_items)
@expose()
def lookup(self, model_name, *args):
model_name = model_name[:-1]
try:
model = self.config.models[model_name]
except KeyError:
raise HTTPNotFound().exception
config = self.config.lookup_controller_config(model_name)
controller = self._make_controller(config, self.session)
return controller, args
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/config.py 0000644 0001750 0001750 00000006621 11235654375 022667 0 ustar zack zack import inspect
from tw.forms import TextField
from sqlalchemy.orm import class_mapper
from sqlalchemy.orm.exc import UnmappedClassError
from tgext.crud import CrudRestController
try:
import tw.dojo
from sprox.dojo.tablebase import DojoTableBase as TableBase
from sprox.dojo.fillerbase import DojoTableFiller as TableFiller
from sprox.dojo.formbase import DojoAddRecordForm as AddRecordForm, DojoEditableForm as EditableForm
except ImportError:
from sprox.tablebase import TableBase
from sprox.fillerbase import TableFiller
from sprox.formbase import AddRecordForm, EditableForm
from sprox.fillerbase import RecordFiller, AddFormFiller
class CrudRestControllerConfig(object):
allow_only = None
defaultCrudRestController = CrudRestController
def _post_init(self):
if not hasattr(self, 'table_type'):
class Table(TableBase):
__entity__=self.model
self.table_type = Table
if not hasattr(self, 'table_filler_type'):
class MyTableFiller(TableFiller):
__entity__ = self.model
self.table_filler_type = MyTableFiller
if not hasattr(self, 'edit_form_type'):
class EditForm(EditableForm):
__entity__ = self.model
self.edit_form_type = EditForm
if not hasattr(self, 'edit_filler_type'):
class EditFiller(RecordFiller):
__entity__ = self.model
self.edit_filler_type = EditFiller
if not hasattr(self, 'new_form_type'):
class NewForm(AddRecordForm):
__entity__ = self.model
self.new_form_type = NewForm
if not hasattr(self, 'new_filler_type'):
class NewFiller(AddFormFiller):
__entity__ = self.model
self.new_filler_type = NewFiller
def __init__(self, model, translations=None):
super(CrudRestControllerConfig, self).__init__()
self.model = model
self._do_init_with_translations(translations)
self._post_init()
def _do_init_with_translations(self, translations):
pass
class AdminConfig(object):
DefaultControllerConfig = CrudRestControllerConfig
default_index_template = None
allow_only = None
include_left_menu = True
def __init__(self, models, translations=None):
if translations is None:
translations = {}
if inspect.ismodule(models):
models = [getattr(models, model) for model in dir(models) if inspect.isclass(getattr(models, model))]
#purge all non-model objects
try_models = models
models = {}
for model in try_models:
if not inspect.isclass(model):
continue
try:
mapper = class_mapper(model)
models[model.__name__.lower()] = model
except UnmappedClassError:
pass
self.models = models
self.translations = translations
self.index_template = self.default_index_template
def lookup_controller_config(self, model_name):
model_name_lower = model_name.lower()
if hasattr(self, model_name_lower):
return getattr(self, model_name_lower)(self.models[model_name], self.translations)
return self.DefaultControllerConfig(self.models[model_name], self.translations)
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/admin/tgadminconfig.py 0000644 0001750 0001750 00000017405 11235657477 024243 0 ustar zack zack import inspect
from tg import expose, redirect
from tw.forms import TextField, PasswordField
from tgext.crud import CrudRestController
from tgext.crud.decorators import registered_validate
from sqlalchemy.orm import class_mapper
from sqlalchemy.orm.exc import UnmappedClassError
from config import AdminConfig, CrudRestControllerConfig
from sprox.fillerbase import EditFormFiller
from sprox.formbase import FilteringSchema
from formencode.validators import FieldsMatch
class PasswordFieldsMatch(FieldsMatch):
field_names = ['password', 'verify_password']
def validate_partial(self, field_dict, state):
#no password is set to change
if not field_dict.get('verify_password') and not field_dict.get('password'):
return
for name in self.field_names:
if not field_dict.has_key(name):
return
self.validate_python(field_dict, state)
try:
import tw.dojo
from sprox.dojo.tablebase import DojoTableBase as TableBase
from sprox.dojo.fillerbase import DojoTableFiller as TableFiller
from sprox.dojo.formbase import DojoAddRecordForm as AddRecordForm, DojoEditableForm as EditableForm
except ImportError:
from sprox.tablebase import TableBase
from sprox.fillerbase import TableFiller
from sprox.formbase import AddRecordForm, EditableForm
from sprox.fillerbase import RecordFiller, AddFormFiller
class UserControllerConfig(CrudRestControllerConfig):
def _do_init_with_translations(self, translations):
user_id_field = translations.get('user_id', 'user_id')
user_name_field = translations.get('user_name', 'user_name')
email_field = translations.get('email_address', 'email_address')
password_field = translations.get('password', 'password')
display_name_field = translations.get('display_name', 'display_name')
class Table(TableBase):
__entity__ = self.model
__omit_fields__ = [user_id_field, '_password', password_field]
__url__ = '../users.json'
self.table_type = Table
class MyTableFiller(TableFiller):
__entity__ = self.model
__omit_fields__ = ['_password', password_field]
self.table_filler_type = MyTableFiller
edit_form_validator = FilteringSchema(chained_validators=(FieldsMatch('password',
'verify_password',
messages={'invalidNoMatch':
'Passwords do not match'}),))
class EditForm(EditableForm):
__entity__ = self.model
__require_fields__ = [user_name_field, email_field]
__omit_fields__ = ['created', '_password']
__hidden_fields__ = [user_id_field]
__field_order__ = [user_id_field, user_name_field, email_field, display_name_field, 'password', 'verify_password', 'groups']
password = PasswordField('password', value='')
verify_password = PasswordField('verify_password')
__base_validator__ = edit_form_validator
if email_field is not None:
setattr(EditForm, email_field, TextField)
if display_name_field is not None:
setattr(EditForm, display_name_field, TextField)
self.edit_form_type = EditForm
class UserEditFormFiller(EditFormFiller):
__entity__ = self.model
def get_value(self, *args, **kw):
v = super(UserEditFormFiller, self).get_value(*args, **kw)
del v['password']
return v
self.edit_filler_type = UserEditFormFiller
class NewForm(AddRecordForm):
__entity__ = self.model
__require_fields__ = [user_name_field, email_field]
__omit_fields__ = [password_field, 'created', '_password']
__hidden_fields__ = [user_id_field]
__field_order__ = [user_name_field, email_field, display_name_field, 'groups']
if email_field is not None:
setattr(NewForm, email_field, TextField)
if display_name_field is not None:
setattr(NewForm, display_name_field, TextField)
self.new_form_type = NewForm
class defaultCrudRestController(CrudRestController):
@expose('genshi:tgext.crud.templates.edit')
def edit(self, *args, **kw):
return CrudRestController.edit(self, *args, **kw)
@expose()
@registered_validate(error_handler=edit)
def put(self, *args, **kw):
"""update"""
if not kw['password']:
del kw['password']
pks = self.provider.get_primary_fields(self.model)
for i, pk in enumerate(pks):
if pk not in kw and i < len(args):
kw[pk] = args[i]
self.provider.update(self.model, params=kw)
redirect('../')
class GroupControllerConfig(CrudRestControllerConfig):
def _do_init_with_translations(self, translations):
group_id_field = translations.get('group_id', 'group_id')
group_name_field = translations.get('group_name', 'group_name')
class GroupTable(TableBase):
__model__ = self.model
__limit_fields__ = [group_name_field, 'permissions']
__url__ = '../groups.json'
self.table_type = GroupTable
class GroupTableFiller(TableFiller):
__model__ = self.model
__limit_fields__ = [group_id_field, group_name_field, 'permissions']
self.table_filler_type = GroupTableFiller
class GroupNewForm(AddRecordForm):
__model__ = self.model
__limit_fields__ = [group_name_field, 'permissions']
self.new_form_type = GroupNewForm
class GroupEditForm(EditableForm):
__model__ = self.model
__limit_fields__ = [group_id_field, 'group_name', 'permissions']
self.edit_form_type = GroupEditForm
class PermissionControllerConfig(CrudRestControllerConfig):
def _do_init_with_translations(self, translations):
permission_id_field = translations.get('permission_id', 'permission_id')
permission_name_field = translations.get('permission_name', 'permission_name')
permission_description_field = translations.get('permission_description', 'description')
class PermissionTable(TableBase):
__model__ = self.model
__limit_fields__ = [permission_name_field, permission_description_field, 'groups']
__url__ = '../permissions.json'
self.table_type = PermissionTable
class PermissionTableFiller(TableFiller):
__model__ = self.model
__limit_fields__ = [permission_id_field, permission_name_field, permission_description_field, 'groups']
self.table_filler_type = PermissionTableFiller
class PermissionNewForm(AddRecordForm):
__model__ = self.model
__limit_fields__ = [permission_name_field, permission_description_field, 'groups']
self.new_form_type = PermissionNewForm
class PermissionEditForm(EditableForm):
__model__ = self.model
__limit_fields__ = [permission_name_field, permission_description_field,'groups']
self.edit_form_type = PermissionEditForm
class PermissionEditFiller(RecordFiller):
__model__ = self.model
self.edit_filler_type = PermissionEditFiller
class TGAdminConfig(AdminConfig):
user = UserControllerConfig
group = GroupControllerConfig
permission = PermissionControllerConfig
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext/__init__.py 0000644 0001750 0001750 00000000364 11133175743 022061 0 ustar zack zack # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
python-tgext.admin-0.2.6/tgext.admin-0.2.6/README.txt 0000644 0001750 0001750 00000000465 11236060355 020311 0 ustar zack zack Introduction
============
Changelog
===========
0.2.6
-----
Bugfix release. Support for _method fields in TG2.1
0.2.5
------
* Addition of defaultCrudRestController to
CRCConfig allows one to customize the controller
that the admin uses.
* Fixes tgadminconfig to override the Password properly for Users
python-tgext.admin-0.2.6/tgext.admin-0.2.6/run_tests.sh 0000644 0001750 0001750 00000000034 11160515205 021160 0 ustar zack zack nosetests tgext/admin/test/
python-tgext.admin-0.2.6/tgext.admin-0.2.6/license.txt 0000644 0001750 0001750 00000002046 11135653115 020773 0 ustar zack zack Copyright (c) 2009 Christopher Perkins
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. python-tgext.admin-0.2.6/tgext.admin-0.2.6/PKG-INFO 0000644 0001750 0001750 00000001762 11236060527 017712 0 ustar zack zack Metadata-Version: 1.0
Name: tgext.admin
Version: 0.2.6
Summary: Admin Controller add-on for basic TG identity model.
Home-page: tgtools.googlecode.com
Author: Christopher Perkins
Author-email: chris@percious.com
License: MIT
Description: Introduction
============
Changelog
===========
0.2.6
-----
Bugfix release. Support for _method fields in TG2.1
0.2.5
------
* Addition of defaultCrudRestController to
CRCConfig allows one to customize the controller
that the admin uses.
* Fixes tgadminconfig to override the Password properly for Users
Changelog
=========
0.1 - Unreleased
----------------
* Initial release
Keywords: TG2,TG,sprox,Rest,internet,adminn
Platform: UNKNOWN
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Libraries :: Python Modules
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext.admin.egg-info/ 0000755 0001750 0001750 00000000000 11236060527 022523 5 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext.admin.egg-info/requires.txt 0000644 0001750 0001750 00000000051 11236060526 025116 0 ustar zack zack setuptools
sprox>=0.6.4
tgext.crud>=0.2.4 python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext.admin.egg-info/namespace_packages.txt 0000644 0001750 0001750 00000000006 11236060526 027051 0 ustar zack zack tgext
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext.admin.egg-info/dependency_links.txt 0000644 0001750 0001750 00000000001 11236060526 026570 0 ustar zack zack
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext.admin.egg-info/zip-safe 0000644 0001750 0001750 00000000001 11133175743 024156 0 ustar zack zack
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext.admin.egg-info/PKG-INFO 0000644 0001750 0001750 00000001762 11236060526 023625 0 ustar zack zack Metadata-Version: 1.0
Name: tgext.admin
Version: 0.2.6
Summary: Admin Controller add-on for basic TG identity model.
Home-page: tgtools.googlecode.com
Author: Christopher Perkins
Author-email: chris@percious.com
License: MIT
Description: Introduction
============
Changelog
===========
0.2.6
-----
Bugfix release. Support for _method fields in TG2.1
0.2.5
------
* Addition of defaultCrudRestController to
CRCConfig allows one to customize the controller
that the admin uses.
* Fixes tgadminconfig to override the Password properly for Users
Changelog
=========
0.1 - Unreleased
----------------
* Initial release
Keywords: TG2,TG,sprox,Rest,internet,adminn
Platform: UNKNOWN
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Libraries :: Python Modules
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext.admin.egg-info/entry_points.txt 0000644 0001750 0001750 00000000045 11236060526 026017 0 ustar zack zack
# -*- Entry points: -*-
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext.admin.egg-info/top_level.txt 0000644 0001750 0001750 00000000006 11236060526 025250 0 ustar zack zack tgext
python-tgext.admin-0.2.6/tgext.admin-0.2.6/tgext.admin.egg-info/SOURCES.txt 0000644 0001750 0001750 00000002005 11236060526 024403 0 ustar zack zack README.txt
license.txt
run_tests.sh
setup.cfg
setup.py
docs/HISTORY.txt
docs/source/conf.py
docs/source/index.rst
docs/source/images/class_diagram.png
tgext/__init__.py
tgext.admin.egg-info/PKG-INFO
tgext.admin.egg-info/SOURCES.txt
tgext.admin.egg-info/dependency_links.txt
tgext.admin.egg-info/entry_points.txt
tgext.admin.egg-info/namespace_packages.txt
tgext.admin.egg-info/requires.txt
tgext.admin.egg-info/top_level.txt
tgext.admin.egg-info/zip-safe
tgext/admin/__init__.py
tgext/admin/config.py
tgext/admin/controller.py
tgext/admin/tgadminconfig.py
tgext/admin/templates/__init__.py
tgext/admin/templates/index.html
tgext/admin/templates/index.mak
tgext/admin/test/__init__.py
tgext/admin/test/base.py
tgext/admin/test/test_controller.py
tgext/admin/test/controllers/__init__.py
tgext/admin/test/controllers/root.py
tgext/admin/test/lib/__init__.py
tgext/admin/test/lib/base.py
tgext/admin/test/lib/helpers.py
tgext/admin/test/model/__init__.py
tgext/admin/test/templates/__init__.py
tgext/admin/test/templates/master.html python-tgext.admin-0.2.6/tgext.admin-0.2.6/docs/ 0000755 0001750 0001750 00000000000 11236060527 017537 5 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/docs/source/ 0000755 0001750 0001750 00000000000 11236060527 021037 5 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/docs/source/images/ 0000755 0001750 0001750 00000000000 11236060527 022304 5 ustar zack zack python-tgext.admin-0.2.6/tgext.admin-0.2.6/docs/source/images/class_diagram.png 0000644 0001750 0001750 00001003170 11135653113 025602 0 ustar zack zack ‰PNG
IHDR ½ 7Ôíä !iCCPICC Profile x“ÏkÔ@Ç¿ÉR[TŠhõä!©
«,Ý‹i³Ý¶¬a›Zœ²IvÝdC’ÝÚEðè݃GožêÁÂ/DÐê_àÁƒPèA)ñMÆÉRpñâƒÉ|føÎ{oÞ› …ïf¶e ~Dõ+óÊõ7•ñ/0†)œÅ¬iÅᜮ¯’d„í}"5ÙÇÌ×ѨíɈR‘S-Î*ãgƒñf&¤q[®iß#.FF]#~A<Ùâüšqƒó;Æ=«ÅÎî—Û y‚ø’íıJlÛ±å?#þéûò_xB|Î
#:[`~ΰºÐL¶ÕÔé/÷®Ñ½_Þgé
÷¦ 'à̓áÞîNV+éÔDÜ,Ïdî¤#ÛÀØ£4ÝÝ ÆÏûŸÓô×všî?§Ø_ÁžÕ(WKïù¹ø@w ËzôwæuÉT%àé Ø ±Lã±
Lo'n:±¡B.—Åà5³Ãš8¾©,U²åÿûøí.õ)³ãô=4jWifü-LtCpÜ[[Üô«‚m³²"¸ïj5ÁÍh±.ø¶¹¬v‚õ5Áa;{÷bÍçz'^È5}× ¾ñ|¢n}]ðÎJ®·Jž[Ю
—Tóü¡ÁC >L(X’¿ERãÐ1àáiYHo_±ç~ÐçnÖcnE^ËM”9ú¢R
¬‹Ee¦TšÅo‹W©smõk pHYs .# .#x¥?v IDATxì½ ¼eU}绪nM@1
(ƒ@iD%ŠQÛ…Ø€y "ILˆ#D”Ÿ(/N¨¯;iœ’V¢‚câÜDAì˜ v3ˆQ"Ð"jd™„*¨ñVÕ}ÿïïÿÿ¯½Ï©{«.TU÷޵ꞽ×úÏë·ö©ý;ûìsάmÌZöÛ¾!Ðh4
†@C !0˜=&ÓæÒh4
†@C !ÐFzÇC¥É
†@C !Ðh4¦ôN«ål“i4
†@C !ÐFzÇC¥É
†@C !Ðh4¦ôN«ål“i4
†@C !ÐFzÇC¥É
†@C !Ðh4¦ôN«ål“i4
†@C !ÐFzÇC¥É
†@C !Ðh4¦ôN«ål“i4
†@C !ÐFzÇC¥É
†@C !Ðh4¦ôN«ål“i4
†@C !ÐFzÇC¥É
†@C !Ðh4¦ôN«ål“i4
†@C !ÐFzÇC¥É
†@C !Ðh4¦ôN«ål“™IŒ•Õ«WϤ)·¹6
†@Cà#ÐHï#†®9N5î¹çž2kÖ¬õ>:è ™ÄnšpŠØñØTíÐC-‹-št¸Ë/¿¼Ìž=»Ì;WõRË>ðIûojÃûï¿_uw2ømêü“ׯó_ø‚ÖyÍš5r_¶lYY¹rådC=b»Ï|æ3Ê»víÚqc çøûÿøqõ}áÖŒu¿ÎÖo4[ôn
«ÐjxTX°`AyÚÓžV9ä=vÚi'åÍ1ûÃ?|Rµ,^¼¸ðØTíáÆzÕ«^¥ÔŸþô§En¾ùæ²téÒMUÎÊ˃]vÙ¥üâ¿xX~¶ñpË—/(a»í¶+ïyÏ{d›c ¹^_ƒÈ¶Öh4›9›>d‹ØØ:Ø~ûíËÕW_]‹ãŠÛ 'œP.¹ä’*£“¤ƒ«¨µo¼q"Õ£"ßqÇË~ûíWŽ?þxåã
æ–jEZõá—6æ>ëËýk^óšÂ#xî¾ûî9Üì{®Ô×FFFê18ž~<ÙÖ†õx56YC !ÐØÒŒÿ¿î–®ªåo<
ä·‰Þf¾êª«ÊK_úR]IåíæoûÛµ*n%èßNpÎ9çT»wÞ¹\{íµÕv¼„;ÄùÉO~R ²Ùx›½ŸûŒ3ΨDˆ>ö\¹|å+_)dYß›ßüæò•¯|E¼#í&›Ÿÿüçª-ýûsÍì|ðÁJŸÿüç—o|ãU½>ü0#né {nÙØPëã>}²¿¾yW'/€Ž:ê¨Âú<ßùÎwâ€%·œä1B]¼Ân<,N:é$ùeýøsËI¿>|ûøÐgý™?{j¤QuÝ{ï½®p¼äZ`;ŒÕ†°®Z§!Ðh4ôºýŸÞZC`æ ðÑ~”÷‘ÇìžÎIé]ýûò—¿òxAÏ\X£œþÔÃø—¿ü%®ZcÆäÀ?Å»ï¾{RX+HÛ4
† ÿ·zkX4fI>&"½ŒlK–,IÂÁ‚ØÐ’lõã$AIÿÜ'áìÇUìŒ÷ŠW¼BcäÙ.»ì2É’H÷ócƒ/䉖õ¬X±Bc6è'2eÿ+ˆ`e b'iNYîÓ>kKÒÛŸã0~Äïë‰ÅyÇŒÏþšk®Y§¦Ä-Éø†æ=\çÙgŸ˜LøôI.µä
ôY_‘Ó û؃zú<¨‰–$šó¸cM³%ñÅ7ý!½y¼ð‚"[ΟÉ`~mßh4f:sì?æÖ
qxãßX¥.Tÿg?û™Þâ®
ëœzꩺ7˜{1ù0÷ É)Ûn»mßL}#^ÚèCªº9sæ#ºåûßÿ¾d?ýéOµ?í´Óô–7÷"ÛUFÉ.¸à‚ròÉ'W߉:FàÊüùó«š['òÃrŠŸ’;âˆ#Š‘¾¯}íkË^{íUãõ;«VÒÐÈX_,¿ôñ{Îsž#ñE]¤[x[Ÿ92¦ÙÊz+_ƒØ|ë[ßRψj¡Ÿ>¹•ããÿ¸ôë›÷DuÊ16F2ëЮ²k-ùÖ]wÝUõÁÖ·fT£èä7yØ•Øn´ÓO?½¼ûÝïÖí
Ftõ!JÖ:ÛÁœÝuî‡NE/çž{nŠ
1Γ
#°¢MöXAZ§!ÐhÌ@Ú=½3pÑÛ”'‡À“žô¤Iòa2È $ç–[nQâÃRýû73ÐD8ÚsÏ=Ó¤ÞÛ›÷x²?à€Ÿ{=7¶å½ÃŇ€ÚÕÆé{êSŸ*â¶÷Þ{?¬¯T£Æ‰ðKb ¡ÎF-våRsäÞÕá–>£¶~ÝøœuÖYÃæ›dÌ÷Ó^wÝuê¿ë]ïÒ~xµ«ºÂ‚
ù~ûÛß.³ï~÷»åÒK/-ïxÇ;Ü’°‡y¼äüS=ŒÑDX§}Û7
†@)Ýe‡†FC !0€Àð•ËeoÀ‡˜þøÿ¸œqÆzpŽ«¾oxÃÖ¹*œn|Ðiÿý÷ÏaáÊ/D‰q¦åÕKú| êØc¸¢‡ü‘´
ŧ¶O}êS…ï±…ÐÓøp5òcý«•RÆ& ZÊ&ÂMãê$˜e#ïW¿úÕu®ò¢Ï«æ\éÝm·ÝÒEu=ýéO¯ãÉt†ëœÈ‡+å\¹ë[ßZÎ<óL™MtµåßüÍß”£>Z—+»øCìóʯÝ1Qª
ÊûWøYæ ág]ha½ÁÀÍ !ÐhÌ Ú•Þ´Ømª›üà"6?úÑôãW\q…½úÕ¯^'!¤ "tÊ)§èJ0W-ùT?-¯ÀþÃ?üƒÆÈÑóM
\éãíÿ´‘Á#ÜL&þ¿øE}Kß"ÁÛûRÚx„wÞ¼yÒqŵÿm޳!d’·þ¹ŠŠ{ÈáwÜ1ŽG)Çwœä|¥xðàï_1×9„“©r{ûí·×0ùÈGÔàt·*ÆévØaUú²—½Lý¼í€“¸W£It8^x1”ÇkñÌg>Sž'žxâ$"4“†@C !ÐX™~ss›ÿÌCÀ޾ׇøàP¿å‡ƒø¶”áCãJù!¥üd¾=©=:»ú&Ûá
03Tmé÷ãaŸµõcòA¬lØ÷?ÜdÄhàƒlY[ÚcÛ—m(~~h«ŸŸ“MÔr>v‹GýpÕúðOjêÇïÏg¼<Ì¿oOŸˆeÆùð¼ûužwÞyŠ—d£öŒŸ1Ù§l¢õìÛ²Ø3?Z~ãCÿr‰}ÿ¸Ëº!ãAŒüöÆ7kÉyçq¹>¬ûõµ~C !ИÉÔ›ç ÁþCm!Ðx„põ‘·žùå7î=ÝPË{S'²5B£Ÿq…°ÿ¡´
Ŭ~Cñ¹Ëý·\™å»a7Ôˆ7Ñ.LäK#ue›m¶÷*òx~‰Ž¾·u<ûaÙúêD—߇›~Œ¹5a¼{´ÓæÑØsÕ¬ÉãG£¾–£!Ðhlí4Ò»µ¯P«¯!ÐØ"pÅ'>ñ ÝBa_E6á·Wl‘âZÒ†@C !ÐxØ´²=lÈšCC !0à3h|‹Ãú>À6°hsl4ÓFz§Ã*¶94›¾Û 6Ç%›¼Ø°!Ðh46ˆ@»½aƒ5ƒ†@C !Ðh4
©Ž@ûʲ©¾‚þ†@C !Ðh4
"ÐHï!j3¾a€OÎOç¶hÑ"}/ïDsä§~ù¾Ý`S´Å”oʘŽ_8Ãw?œYü6‹É¬KÆïñdüšMC !И4Ò;V±Ía³"ÀC¼ç=ïÙ¬9¶öà÷Þ{ï&-qc0½é¦›Ê.»ìR~ñ‹_lÒš¦b0~œc‡vxØ/FÚ/¸MÅÕn57‹@#½‹`óŸöØ~ l&·“O>YWVî÷ðN„ÙÆ`
a¦å~¢SQž¿7ÙÚó'™îºLö§˜'[G³k4SFz§Â*Mñ¹2Çä—þŸqÆõiÞž}å+_Yut~ö6§üæ7¿¹ðÖz¾½Nì³ñÓ¿üíå—_^x‹=¹xû»ßÎ9眚ûa=?ƒ›õáO<¶ÔÿÎw¾³PïoíÏçø€äÃÞv>ôÐC×ùQr!Ï·çûs£†þ PGß–}1Ð_{íµªÿñnAØÎÄýñ¬9&ýyeü¬û-…i¾ yþóŸ_±šÌü¨™ÆO*ƒ·Xdc^¬uÎyCñ8†yôãôÏã’=x‚Õxc‹ã–ã‰üßüæ7̸føùÁñGc'œp‚úÄÈcšµây”ëxÒI's{ιçž[mÈO¿õ×=Çl¿
ë×ç?Þó«õ
†À£Ž€ý§ßZC`“#ÀÏ£ÚÁ¬ÇÅ_?ùJK?ÓŠ>Çù“»ü´lÊÞÿþ÷åÏã¾éMo’?~©Ýë^§ŸâͱÙdôùs¯ØðóÁ4b1&65äOÕRCþ4í~öó²äÊŸæçm±%&¾ìÇk舗šåOg|r_yå•õ§y™+-çÇOÑfëË/ÄÉy§=ûÔã»!œÁ("˜õ¢Q1²Ž-…©ýBœ°£j3Ú†æ'£Øä1 Ùòç‚/¼ðB‰6ã¡¿®8õe¹FÄÁ̇[Ö
ö‰)ãÄ9ëà§‹©-Í%K–Œñ³Ð9fåñ™9sݨf?²Q±âXé?òg¦Ó‡cšºó9›xåÜ8vÑ›:‰MËyLô|“QÛ4
-€€ý_åmän)g y\±bE-2NÊœÄíèÓÉ;•dØÐÆóç$›'ñ<÷IEIˆ'râõõv?£dœ”3*[ê“x’+OøááxØ% ϹO‘;ë¬eî$–é!ä5ç—$›¾l˜DgŒþþáàÜ÷K²3\GÎaKašk$k2óëÏ‹>ørfKÌÁy2ñ8.óÌ}Y®du¢6ޱݯܩ1É(q’(³§Ÿ¹dCÞŸrŽó¬5I/Ï‘ly¼Suï“yŒåó!ëî“ÔÍñ°¡c#s¶}C !ÐØ´ÛìŒÑÚæAÀèò“Ÿü¤¡ø‚ÿ«¯¾º ,·Þz«xീm·Ý¶ØIµ,^¼¸Êì„=à¿ãŽ;V]v;ì°ìÜþðo}Kò³Ï>[oÝóVïi§&·RŸ·{³Í™3G·¼å-oIQ1‚ªþ‚´?âˆ#ô–4oióöó?øÁjÛïüå_þ¥†ä§½ãïÐþÏxFÍ=ü6ù‘G)›åË—k?™› Í&ƒ3x©ˆññßqÇò-éªU«TO~k2ó˜€
Œ,–x@·Òpœ^tÑE¹7ö‘ÄŽŸc#ÙØ‘ÔsÃÈçÀ±ý±}¬Úq{Â=÷ÜS®¿þúÂqË-ÜÆÐoy‹ñhYûñì†1H‚?ü᪴ÛR˜×>Ã6Ãã$£¶ë®»Nêw½ë]Ú?’x8ö_¨)mrs<¼è¡‡†EuÌý¼ø{ì±…rHòú/ä¸çùo}kÙsÏ=Ëç>÷¹bWaÇm¢8ë¼àåüóÏ//|áu¬c›ë~üñÇëµÜrË-º¯÷¢§ÍDÇÆD9›¼!Ðh<4Òûh |