From 25611f1e6895338d682dfad54e7b65163e519438 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 22 May 2013 18:09:51 -0700 Subject: [PATCH 1/8] Tweaked Fabric ``release`` command. --- fabfile.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fabfile.py b/fabfile.py index 8e01404..4e02e11 100644 --- a/fabfile.py +++ b/fabfile.py @@ -23,6 +23,7 @@ ################################################################################ import os.path +import shutil from fabric.api import * @@ -36,7 +37,8 @@ def release(): Release a new version of 'edbob'. """ - local("python setup.py egg_info --tag-build='' sdist --formats=gztar") + shutil.rmtree('edbob.egg-info') + local('python setup.py sdist --formats=gztar register upload') filename = 'edbob-{0}.tar.gz'.format(__version__) From 4fe5ad9bf03b69b31239780f47cf64bc0ba82a80 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 18 Jun 2013 22:19:52 -0700 Subject: [PATCH 2/8] 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 --- edbob/filemon/linux.py | 10 +++++++++- edbob/pyramid/views/people.py | 27 ++++++++++++++------------- edbob/pyramid/views/roles.py | 6 +++--- edbob/pyramid/views/users.py | 27 ++++++++++++++------------- edbob/tests/__init__.py | 19 +++++++++++++++++++ setup.cfg | 7 +++++++ setup.py | 2 ++ 7 files changed, 68 insertions(+), 30 deletions(-) create mode 100644 edbob/tests/__init__.py create mode 100644 setup.cfg diff --git a/edbob/filemon/linux.py b/edbob/filemon/linux.py index 6d5ab83..ae1c4a0 100644 --- a/edbob/filemon/linux.py +++ b/edbob/filemon/linux.py @@ -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 diff --git a/edbob/pyramid/views/people.py b/edbob/pyramid/views/people.py index afdf657..1f50470 100644 --- a/edbob/pyramid/views/people.py +++ b/edbob/pyramid/views/people.py @@ -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): diff --git a/edbob/pyramid/views/roles.py b/edbob/pyramid/views/roles.py index 2d0aa57..531c95a 100644 --- a/edbob/pyramid/views/roles.py +++ b/edbob/pyramid/views/roles.py @@ -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 diff --git a/edbob/pyramid/views/users.py b/edbob/pyramid/views/users.py index a2e201e..42ba461 100644 --- a/edbob/pyramid/views/users.py +++ b/edbob/pyramid/views/users.py @@ -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)) diff --git a/edbob/tests/__init__.py b/edbob/tests/__init__.py new file mode 100644 index 0000000..e5c6980 --- /dev/null +++ b/edbob/tests/__init__.py @@ -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) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..28110c5 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,7 @@ +[nosetests] +nocapture = 1 +cover-package = edbob +cover-erase = 1 +cover-inclusive = 1 +cover-html = 1 +cover-html-dir = htmlcov diff --git a/setup.py b/setup.py index f81a1fb..0b5b2e5 100644 --- a/setup.py +++ b/setup.py @@ -209,6 +209,8 @@ setup( install_requires = requires, extras_require = extras, + tests_require = requires + ['nose'], + test_suite = 'nose.collector', packages = find_packages(), include_package_data = True, From ee9c6622fff2a9daf750dd5547864025bf0c7ce6 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 18 Jun 2013 22:46:58 -0700 Subject: [PATCH 3/8] Add mock import for testing on Linux. --- edbob/win32.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/edbob/win32.py b/edbob/win32.py index 96a76bd..314ddaa 100644 --- a/edbob/win32.py +++ b/edbob/win32.py @@ -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 From 8a0f300fc0e5a9c1fde9cd7e5b9e5128588aa93f Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 31 Jul 2013 22:36:54 -0700 Subject: [PATCH 4/8] Add minimum version requirement for `pytz`. --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0b5b2e5..6c9bf9a 100644 --- a/setup.py +++ b/setup.py @@ -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): From 183530afc9c2fe2a5e577861d6d81615c53e08c1 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 28 Jan 2014 09:13:45 -0800 Subject: [PATCH 5/8] update changelog --- CHANGES.txt | 9 +++++++++ edbob/_version.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 0e4fdc0..688705d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,13 @@ +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 ------ diff --git a/edbob/_version.py b/edbob/_version.py index 36ef6a9..df9144c 100644 --- a/edbob/_version.py +++ b/edbob/_version.py @@ -1 +1 @@ -__version__ = '0.1a29' +__version__ = '0.1.1' From 73978ffeb7c2721b25add9c4f8000a1a3327b180 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 28 Apr 2014 14:26:21 -0700 Subject: [PATCH 6/8] Allow config file to prevent logging configuration from happening. --- edbob/initialization.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/edbob/initialization.py b/edbob/initialization.py index 410b572..af2aeff 100644 --- a/edbob/initialization.py +++ b/edbob/initialization.py @@ -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) From 8fabdf8b72af2ced5893643e30371e9517ef6a76 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 28 Apr 2014 14:27:32 -0700 Subject: [PATCH 7/8] update changelog --- CHANGES.txt | 6 ++++++ edbob/_version.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 688705d..8bfbfbc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,10 @@ +0.1.2 +----- + +* Allow config file to prevent logging configuration from happening. + + 0.1.1 ----- diff --git a/edbob/_version.py b/edbob/_version.py index df9144c..10939f0 100644 --- a/edbob/_version.py +++ b/edbob/_version.py @@ -1 +1 @@ -__version__ = '0.1.1' +__version__ = '0.1.2' From a0b35dfadba1fe61c48edc0b1bcaa460a470ce07 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 28 Apr 2014 14:28:54 -0700 Subject: [PATCH 8/8] Remove custom PyPI stuff from Fabric `release` task. --- fabfile.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/fabfile.py b/fabfile.py index 4e02e11..1eb4728 100644 --- a/fabfile.py +++ b/fabfile.py @@ -22,27 +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'. """ - shutil.rmtree('edbob.egg-info') local('python setup.py sdist --formats=gztar register upload') - - 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')