Compare commits

...

12 commits

Author SHA1 Message Date
Lance Edgar
a0b35dfadb Remove custom PyPI stuff from Fabric release task. 2014-04-28 14:28:54 -07:00
Lance Edgar
8fabdf8b72 update changelog 2014-04-28 14:27:32 -07:00
Lance Edgar
73978ffeb7 Allow config file to prevent logging configuration from happening. 2014-04-28 14:26:21 -07:00
Lance Edgar
183530afc9 update changelog 2014-01-28 09:13:45 -08:00
Lance Edgar
8a0f300fc0 Add minimum version requirement for pytz. 2013-07-31 22:36:54 -07:00
Lance Edgar
ee9c6622ff Add mock import for testing on Linux. 2013-06-18 22:46:58 -07:00
Lance Edgar
4fe5ad9bf0 Prepare for tests.
This doesn't add any actual tests but it should pave the way for that.  Tests
may be run like so:

.. code-block:: sh

   python setup.py nosetests --with-coverage
2013-06-18 22:19:52 -07:00
Lance Edgar
25611f1e68 Tweaked Fabric `release` command. 2013-05-22 18:09:51 -07:00
Lance Edgar
4ed6b09a24 update changelog 2013-05-21 22:30:03 -07:00
Lance Edgar
3766dbfff1 Updated `repr()` output for model classes. 2013-05-17 12:21:39 -07:00
Lance Edgar
3bfda431fa Changed some logging instances from INFO to DEBUG.
I was just getting tired of the noise.
2013-05-16 07:00:40 -07:00
Lance Edgar
4dc4f3f1ec Removed setup.cfg file.
The `tag_build` setting was not doing us any favors.
2013-05-09 21:47:07 -07:00
17 changed files with 126 additions and 60 deletions

View file

@ -1,4 +1,29 @@
0.1.2
-----
* Allow config file to prevent logging configuration from happening.
0.1.1
-----
* Some random things required in production at MaMa Jean's...
Specifically this is known to replace occurrences of e.g. ``edbob.User`` with
a more standard (properly imported) reference to ``User``.
0.1a29
------
* Removed ``setup.cfg`` file.
* Changed some logging instances from ``INFO`` to ``DEBUG``.
* Updated ``repr()`` output for model classes.
0.1a28
------

View file

@ -1 +1 @@
__version__ = '0.1a28'
__version__ = '0.1.2'

View file

@ -366,7 +366,7 @@ def extend_framework():
session.close()
for name in sorted(extensions, extension_sorter(extensions)):
log.info("Applying active extension: %s" % name)
log.debug("Applying active extension: %s" % name)
ext = extensions[name]
# merge_extension_metadata(ext)
# ext.extend_classes()

View file

@ -51,7 +51,8 @@ class Permission(Base):
permission = Column(String(50), primary_key=True)
def __repr__(self):
return "<Permission: %s, %s>" % (self.role, self.permission)
return "Permission(role_uuid={0}, permission={1})".format(
repr(self.role_uuid), repr(self.permission))
def __unicode__(self):
return unicode(self.permission or '')
@ -69,7 +70,7 @@ class UserRole(Base):
role_uuid = Column(String(32), ForeignKey('roles.uuid'))
def __repr__(self):
return "<UserRole: %s : %s>" % (self.user, self.role)
return "UserRole(uuid={0})".format(repr(self.uuid))
class Role(Base):
@ -97,7 +98,7 @@ class Role(Base):
getset_factory=getset_factory)
def __repr__(self):
return "<Role: %s>" % self.name
return "Role(uuid={0})".format(repr(self.uuid))
def __unicode__(self):
return unicode(self.name or '')
@ -124,7 +125,7 @@ class User(Base):
getset_factory=getset_factory)
def __repr__(self):
return "<User: %s>" % self.username
return "User(uuid={0})".format(repr(self.uuid))
def __unicode__(self):
return unicode(self.username or '')

View file

@ -72,7 +72,8 @@ class PhoneNumber(Base):
__mapper_args__ = {'polymorphic_on': parent_type}
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self.number)
return "{0}(uuid={1})".format(
self.__class__.__name__, repr(self.uuid))
def __unicode__(self):
return unicode(self.number)
@ -103,7 +104,8 @@ class EmailAddress(Base):
__mapper_args__ = {'polymorphic_on': parent_type}
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self.address)
return "{0}(uuid={1})".format(
self.__class__.__name__, repr(self.uuid))
def __unicode__(self):
return unicode(self.address)
@ -131,7 +133,7 @@ class Person(Base):
display_name = Column(String(100), default=get_person_display_name)
def __repr__(self):
return "<Person: %s>" % self.display_name
return "Person(uuid={0})".format(repr(self.uuid))
def __unicode__(self):
return unicode(self.display_name or '')

View file

@ -54,7 +54,7 @@ class ActiveExtension(Base):
name = Column(String(50), primary_key=True)
def __repr__(self):
return "<ActiveExtension: %s>" % self.name
return "ActiveExtension(name={0})".format(repr(self.name))
def __str__(self):
return str(self.name or '')
@ -71,4 +71,4 @@ class Setting(Base):
value = Column(Text)
def __repr__(self):
return "<Setting: %s>" % self.name
return "Setting(name={0})".format(repr(self.name))

View file

@ -28,11 +28,19 @@
import sys
import os.path
import pyinotify
import threading
import Queue
import logging
try:
import pyinotify
except ImportError:
# Mock out for testing on Windows.
class Dummy(object):
pass
pyinotify = Dummy()
pyinotify.ProcessEvent = Dummy
import edbob
from edbob import filemon
from edbob.daemon import Daemon

View file

@ -89,7 +89,8 @@ def init(appname='edbob', *args, **kwargs):
shell = kwargs.get('shell', False)
for paths in config_paths:
config.read(paths, recurse=not shell)
config.configure_logging()
if config.getboolean('edbob', 'configure_logging', default=True):
config.configure_logging()
default_modules = 'edbob.time'
modules = config.get('edbob', 'init', default=default_modules)

View file

@ -33,37 +33,38 @@ from sqlalchemy import and_
# from formalchemy import Field
import edbob
# from edbob.pyramid import filters
# from edbob.pyramid import forms
# from edbob.pyramid import grids
# from edbob.pyramid import Session
from edbob.pyramid.views import SearchableAlchemyGridView, CrudView
from edbob.db.extensions.contact.model import (
Person, PersonEmailAddress, PersonPhoneNumber)
class PeopleGrid(SearchableAlchemyGridView):
mapped_class = edbob.Person
mapped_class = Person
config_prefix = 'people'
sort = 'first_name'
def join_map(self):
return {
'email':
lambda q: q.outerjoin(edbob.PersonEmailAddress, and_(
edbob.PersonEmailAddress.parent_uuid == edbob.Person.uuid,
edbob.PersonEmailAddress.preference == 1)),
lambda q: q.outerjoin(PersonEmailAddress, and_(
PersonEmailAddress.parent_uuid == Person.uuid,
PersonEmailAddress.preference == 1)),
'phone':
lambda q: q.outerjoin(edbob.PersonPhoneNumber, and_(
edbob.PersonPhoneNumber.parent_uuid == edbob.Person.uuid,
edbob.PersonPhoneNumber.preference == 1)),
lambda q: q.outerjoin(PersonPhoneNumber, and_(
PersonPhoneNumber.parent_uuid == Person.uuid,
PersonPhoneNumber.preference == 1)),
}
def filter_map(self):
return self.make_filter_map(
ilike=['first_name', 'last_name'],
email=self.filter_ilike(edbob.PersonEmailAddress.address),
phone=self.filter_ilike(edbob.PersonPhoneNumber.number))
email=self.filter_ilike(PersonEmailAddress.address),
phone=self.filter_ilike(PersonPhoneNumber.number))
def filter_config(self):
return self.make_filter_config(
@ -77,8 +78,8 @@ class PeopleGrid(SearchableAlchemyGridView):
def sort_map(self):
return self.make_sort_map(
'first_name', 'last_name',
email=self.sorter(edbob.PersonEmailAddress.address),
phone=self.sorter(edbob.PersonPhoneNumber.number))
email=self.sorter(PersonEmailAddress.address),
phone=self.sorter(PersonPhoneNumber.number))
def grid(self):
g = self.make_grid()
@ -97,7 +98,7 @@ class PeopleGrid(SearchableAlchemyGridView):
class PersonCrud(CrudView):
mapped_class = edbob.Person
mapped_class = Person
home_route = 'people'
def fieldset(self, model):

View file

@ -32,10 +32,10 @@ import formalchemy
from webhelpers.html import tags
from webhelpers.html.builder import HTML
import edbob
from edbob.db import auth
from edbob.pyramid import Session
from edbob.pyramid.views import SearchableAlchemyGridView, CrudView
from edbob.db.extensions.auth.model import Role
default_permissions = [
@ -68,7 +68,7 @@ default_permissions = [
class RolesGrid(SearchableAlchemyGridView):
mapped_class = edbob.Role
mapped_class = Role
config_prefix = 'roles'
sort = 'name'
@ -161,7 +161,7 @@ def PermissionsFieldRenderer(permissions, *args, **kwargs):
class RoleCrud(CrudView):
mapped_class = edbob.Role
mapped_class = Role
home_route = 'roles'
permissions = default_permissions

View file

@ -32,28 +32,29 @@ from webhelpers.html.builder import HTML
import formalchemy
from formalchemy.fields import SelectFieldRenderer
import edbob
from edbob.db import auth
from edbob.pyramid import Session
from edbob.pyramid.views import SearchableAlchemyGridView, CrudView
from edbob.db.extensions.auth.model import User, Role
from edbob.db.extensions.contact.model import Person
class UsersGrid(SearchableAlchemyGridView):
mapped_class = edbob.User
mapped_class = User
config_prefix = 'users'
sort = 'username'
def join_map(self):
return {
'person':
lambda q: q.outerjoin(edbob.Person),
lambda q: q.outerjoin(Person),
}
def filter_map(self):
return self.make_filter_map(
ilike=['username'],
person=self.filter_ilike(edbob.Person.display_name))
person=self.filter_ilike(Person.display_name))
def filter_config(self):
return self.make_filter_config(
@ -65,7 +66,7 @@ class UsersGrid(SearchableAlchemyGridView):
def sort_map(self):
return self.make_sort_map(
'username',
person=self.sorter(edbob.Person.display_name))
person=self.sorter(Person.display_name))
def grid(self):
g = self.make_grid()
@ -92,7 +93,7 @@ def RolesFieldRenderer(request):
class RolesFieldRenderer(SelectFieldRenderer):
def render_readonly(self, **kwargs):
roles = Session.query(edbob.Role)
roles = Session.query(Role)
html = ''
for uuid in self.value:
role = roles.get(uuid)
@ -117,15 +118,15 @@ class RolesField(formalchemy.Field):
return [x.uuid for x in user.roles]
def get_options(self):
q = Session.query(edbob.Role.name, edbob.Role.uuid)
q = q.filter(edbob.Role.uuid != auth.guest_role(Session()).uuid)
q = q.order_by(edbob.Role.name)
q = Session.query(Role.name, Role.uuid)
q = q.filter(Role.uuid != auth.guest_role(Session()).uuid)
q = q.order_by(Role.name)
return q.all()
def sync(self):
if not self.is_readonly():
user = self.model
roles = Session.query(edbob.Role)
roles = Session.query(Role)
data = self.renderer.deserialize()
user.roles = [roles.get(x) for x in data]
@ -140,7 +141,7 @@ class _ProtectedPersonRenderer(formalchemy.FieldRenderer):
def ProtectedPersonRenderer(uuid):
person = Session.query(edbob.Person).get(uuid)
person = Session.query(Person).get(uuid)
assert person
return type('ProtectedPersonRenderer', (_ProtectedPersonRenderer,),
{'person': person})
@ -187,7 +188,7 @@ class PasswordField(formalchemy.Field):
class UserCrud(CrudView):
mapped_class = edbob.User
mapped_class = User
home_route = 'users'
def fieldset(self, user):
@ -213,7 +214,7 @@ class UserCrud(CrudView):
del fs.confirm_password
# if fs.edit and user.person:
if isinstance(user, edbob.User) and user.person:
if isinstance(user, User) and user.person:
fs.person.set(readonly=True,
renderer=LinkedPersonRenderer(self.request))

19
edbob/tests/__init__.py Normal file
View file

@ -0,0 +1,19 @@
import unittest
from pyramid import testing
class TestCase(unittest.TestCase):
"""
Base class for all test suites.
"""
def setUp(self):
self.config = testing.setUp()
def tearDown(self):
testing.tearDown()
def test_something(self):
self.assertTrue(1)

View file

@ -75,7 +75,7 @@ def init(config):
tz = config.get('edbob.time', key)
if tz:
key = key[5:]
log.info("'%s' timezone set to '%s'" % (key, tz))
log.debug("'%s' timezone set to '%s'" % (key, tz))
set_timezone(tz, key)
if 'local' not in timezones:

View file

@ -38,9 +38,17 @@ if sys.platform == 'win32': # docs should build for everyone
import win32file
import win32print
import win32service
import win32serviceutil
import winerror
try:
import win32serviceutil
except ImportError:
# Mock out for testing on Linux.
class Object(object):
pass
win32serviceutil = Object()
win32serviceutil.ServiceFramework = Object
import edbob

16
fabfile.py vendored
View file

@ -22,25 +22,15 @@
#
################################################################################
import os.path
import shutil
from fabric.api import *
execfile(os.path.join(os.path.dirname(__file__), 'edbob', '_version.py'))
@task
def release():
"""
Release a new version of 'edbob'.
"""
local("python setup.py egg_info --tag-build='' sdist --formats=gztar")
filename = 'edbob-{0}.tar.gz'.format(__version__)
put(os.path.join('dist', filename), '/srv/pypi/{0}'.format(filename))
with cd('/srv/pypi'):
run('rm --recursive --force simple')
run('compoze index')
shutil.rmtree('edbob.egg-info')
local('python setup.py sdist --formats=gztar register upload')

View file

@ -1,2 +1,7 @@
[egg_info]
tag_build = .dev
[nosetests]
nocapture = 1
cover-package = edbob
cover-erase = 1
cover-inclusive = 1
cover-html = 1
cover-html-dir = htmlcov

View file

@ -73,7 +73,10 @@ requires = [
'decorator', # 3.3.2
'lockfile', # 0.9.1
'progressbar', # 2.3
'pytz', # 2012b
# Hardcode ``pytz`` minimum since apparently it isn't (any longer?) enough
# to simply require the library.
'pytz>=2013b', # 2013b
]
if sys.version_info < (2, 7):
@ -209,6 +212,8 @@ setup(
install_requires = requires,
extras_require = extras,
tests_require = requires + ['nose'],
test_suite = 'nose.collector',
packages = find_packages(),
include_package_data = True,