Compare commits
10 commits
3bfda431fa
...
a0b35dfadb
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a0b35dfadb | ||
![]() |
8fabdf8b72 | ||
![]() |
73978ffeb7 | ||
![]() |
183530afc9 | ||
![]() |
8a0f300fc0 | ||
![]() |
ee9c6622ff | ||
![]() |
4fe5ad9bf0 | ||
![]() |
25611f1e68 | ||
![]() |
4ed6b09a24 | ||
![]() |
3766dbfff1 |
15 changed files with 124 additions and 56 deletions
25
CHANGES.txt
25
CHANGES.txt
|
@ -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
|
0.1a28
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__version__ = '0.1a28'
|
__version__ = '0.1.2'
|
||||||
|
|
|
@ -51,7 +51,8 @@ class Permission(Base):
|
||||||
permission = Column(String(50), primary_key=True)
|
permission = Column(String(50), primary_key=True)
|
||||||
|
|
||||||
def __repr__(self):
|
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):
|
def __unicode__(self):
|
||||||
return unicode(self.permission or '')
|
return unicode(self.permission or '')
|
||||||
|
@ -69,7 +70,7 @@ class UserRole(Base):
|
||||||
role_uuid = Column(String(32), ForeignKey('roles.uuid'))
|
role_uuid = Column(String(32), ForeignKey('roles.uuid'))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<UserRole: %s : %s>" % (self.user, self.role)
|
return "UserRole(uuid={0})".format(repr(self.uuid))
|
||||||
|
|
||||||
|
|
||||||
class Role(Base):
|
class Role(Base):
|
||||||
|
@ -97,7 +98,7 @@ class Role(Base):
|
||||||
getset_factory=getset_factory)
|
getset_factory=getset_factory)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Role: %s>" % self.name
|
return "Role(uuid={0})".format(repr(self.uuid))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return unicode(self.name or '')
|
return unicode(self.name or '')
|
||||||
|
@ -124,7 +125,7 @@ class User(Base):
|
||||||
getset_factory=getset_factory)
|
getset_factory=getset_factory)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<User: %s>" % self.username
|
return "User(uuid={0})".format(repr(self.uuid))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return unicode(self.username or '')
|
return unicode(self.username or '')
|
||||||
|
|
|
@ -72,7 +72,8 @@ class PhoneNumber(Base):
|
||||||
__mapper_args__ = {'polymorphic_on': parent_type}
|
__mapper_args__ = {'polymorphic_on': parent_type}
|
||||||
|
|
||||||
def __repr__(self):
|
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):
|
def __unicode__(self):
|
||||||
return unicode(self.number)
|
return unicode(self.number)
|
||||||
|
@ -103,7 +104,8 @@ class EmailAddress(Base):
|
||||||
__mapper_args__ = {'polymorphic_on': parent_type}
|
__mapper_args__ = {'polymorphic_on': parent_type}
|
||||||
|
|
||||||
def __repr__(self):
|
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):
|
def __unicode__(self):
|
||||||
return unicode(self.address)
|
return unicode(self.address)
|
||||||
|
@ -131,7 +133,7 @@ class Person(Base):
|
||||||
display_name = Column(String(100), default=get_person_display_name)
|
display_name = Column(String(100), default=get_person_display_name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Person: %s>" % self.display_name
|
return "Person(uuid={0})".format(repr(self.uuid))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return unicode(self.display_name or '')
|
return unicode(self.display_name or '')
|
||||||
|
|
|
@ -54,7 +54,7 @@ class ActiveExtension(Base):
|
||||||
name = Column(String(50), primary_key=True)
|
name = Column(String(50), primary_key=True)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<ActiveExtension: %s>" % self.name
|
return "ActiveExtension(name={0})".format(repr(self.name))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.name or '')
|
return str(self.name or '')
|
||||||
|
@ -71,4 +71,4 @@ class Setting(Base):
|
||||||
value = Column(Text)
|
value = Column(Text)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Setting: %s>" % self.name
|
return "Setting(name={0})".format(repr(self.name))
|
||||||
|
|
|
@ -28,11 +28,19 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
import pyinotify
|
|
||||||
import threading
|
import threading
|
||||||
import Queue
|
import Queue
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
try:
|
||||||
|
import pyinotify
|
||||||
|
except ImportError:
|
||||||
|
# Mock out for testing on Windows.
|
||||||
|
class Dummy(object):
|
||||||
|
pass
|
||||||
|
pyinotify = Dummy()
|
||||||
|
pyinotify.ProcessEvent = Dummy
|
||||||
|
|
||||||
import edbob
|
import edbob
|
||||||
from edbob import filemon
|
from edbob import filemon
|
||||||
from edbob.daemon import Daemon
|
from edbob.daemon import Daemon
|
||||||
|
|
|
@ -89,7 +89,8 @@ def init(appname='edbob', *args, **kwargs):
|
||||||
shell = kwargs.get('shell', False)
|
shell = kwargs.get('shell', False)
|
||||||
for paths in config_paths:
|
for paths in config_paths:
|
||||||
config.read(paths, recurse=not shell)
|
config.read(paths, recurse=not shell)
|
||||||
config.configure_logging()
|
if config.getboolean('edbob', 'configure_logging', default=True):
|
||||||
|
config.configure_logging()
|
||||||
|
|
||||||
default_modules = 'edbob.time'
|
default_modules = 'edbob.time'
|
||||||
modules = config.get('edbob', 'init', default=default_modules)
|
modules = config.get('edbob', 'init', default=default_modules)
|
||||||
|
|
|
@ -33,37 +33,38 @@ from sqlalchemy import and_
|
||||||
|
|
||||||
# from formalchemy import Field
|
# from formalchemy import Field
|
||||||
|
|
||||||
import edbob
|
|
||||||
# from edbob.pyramid import filters
|
# from edbob.pyramid import filters
|
||||||
# from edbob.pyramid import forms
|
# from edbob.pyramid import forms
|
||||||
# from edbob.pyramid import grids
|
# from edbob.pyramid import grids
|
||||||
# from edbob.pyramid import Session
|
# from edbob.pyramid import Session
|
||||||
from edbob.pyramid.views import SearchableAlchemyGridView, CrudView
|
from edbob.pyramid.views import SearchableAlchemyGridView, CrudView
|
||||||
|
from edbob.db.extensions.contact.model import (
|
||||||
|
Person, PersonEmailAddress, PersonPhoneNumber)
|
||||||
|
|
||||||
|
|
||||||
class PeopleGrid(SearchableAlchemyGridView):
|
class PeopleGrid(SearchableAlchemyGridView):
|
||||||
|
|
||||||
mapped_class = edbob.Person
|
mapped_class = Person
|
||||||
config_prefix = 'people'
|
config_prefix = 'people'
|
||||||
sort = 'first_name'
|
sort = 'first_name'
|
||||||
|
|
||||||
def join_map(self):
|
def join_map(self):
|
||||||
return {
|
return {
|
||||||
'email':
|
'email':
|
||||||
lambda q: q.outerjoin(edbob.PersonEmailAddress, and_(
|
lambda q: q.outerjoin(PersonEmailAddress, and_(
|
||||||
edbob.PersonEmailAddress.parent_uuid == edbob.Person.uuid,
|
PersonEmailAddress.parent_uuid == Person.uuid,
|
||||||
edbob.PersonEmailAddress.preference == 1)),
|
PersonEmailAddress.preference == 1)),
|
||||||
'phone':
|
'phone':
|
||||||
lambda q: q.outerjoin(edbob.PersonPhoneNumber, and_(
|
lambda q: q.outerjoin(PersonPhoneNumber, and_(
|
||||||
edbob.PersonPhoneNumber.parent_uuid == edbob.Person.uuid,
|
PersonPhoneNumber.parent_uuid == Person.uuid,
|
||||||
edbob.PersonPhoneNumber.preference == 1)),
|
PersonPhoneNumber.preference == 1)),
|
||||||
}
|
}
|
||||||
|
|
||||||
def filter_map(self):
|
def filter_map(self):
|
||||||
return self.make_filter_map(
|
return self.make_filter_map(
|
||||||
ilike=['first_name', 'last_name'],
|
ilike=['first_name', 'last_name'],
|
||||||
email=self.filter_ilike(edbob.PersonEmailAddress.address),
|
email=self.filter_ilike(PersonEmailAddress.address),
|
||||||
phone=self.filter_ilike(edbob.PersonPhoneNumber.number))
|
phone=self.filter_ilike(PersonPhoneNumber.number))
|
||||||
|
|
||||||
def filter_config(self):
|
def filter_config(self):
|
||||||
return self.make_filter_config(
|
return self.make_filter_config(
|
||||||
|
@ -77,8 +78,8 @@ class PeopleGrid(SearchableAlchemyGridView):
|
||||||
def sort_map(self):
|
def sort_map(self):
|
||||||
return self.make_sort_map(
|
return self.make_sort_map(
|
||||||
'first_name', 'last_name',
|
'first_name', 'last_name',
|
||||||
email=self.sorter(edbob.PersonEmailAddress.address),
|
email=self.sorter(PersonEmailAddress.address),
|
||||||
phone=self.sorter(edbob.PersonPhoneNumber.number))
|
phone=self.sorter(PersonPhoneNumber.number))
|
||||||
|
|
||||||
def grid(self):
|
def grid(self):
|
||||||
g = self.make_grid()
|
g = self.make_grid()
|
||||||
|
@ -97,7 +98,7 @@ class PeopleGrid(SearchableAlchemyGridView):
|
||||||
|
|
||||||
class PersonCrud(CrudView):
|
class PersonCrud(CrudView):
|
||||||
|
|
||||||
mapped_class = edbob.Person
|
mapped_class = Person
|
||||||
home_route = 'people'
|
home_route = 'people'
|
||||||
|
|
||||||
def fieldset(self, model):
|
def fieldset(self, model):
|
||||||
|
|
|
@ -32,10 +32,10 @@ import formalchemy
|
||||||
from webhelpers.html import tags
|
from webhelpers.html import tags
|
||||||
from webhelpers.html.builder import HTML
|
from webhelpers.html.builder import HTML
|
||||||
|
|
||||||
import edbob
|
|
||||||
from edbob.db import auth
|
from edbob.db import auth
|
||||||
from edbob.pyramid import Session
|
from edbob.pyramid import Session
|
||||||
from edbob.pyramid.views import SearchableAlchemyGridView, CrudView
|
from edbob.pyramid.views import SearchableAlchemyGridView, CrudView
|
||||||
|
from edbob.db.extensions.auth.model import Role
|
||||||
|
|
||||||
|
|
||||||
default_permissions = [
|
default_permissions = [
|
||||||
|
@ -68,7 +68,7 @@ default_permissions = [
|
||||||
|
|
||||||
class RolesGrid(SearchableAlchemyGridView):
|
class RolesGrid(SearchableAlchemyGridView):
|
||||||
|
|
||||||
mapped_class = edbob.Role
|
mapped_class = Role
|
||||||
config_prefix = 'roles'
|
config_prefix = 'roles'
|
||||||
sort = 'name'
|
sort = 'name'
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ def PermissionsFieldRenderer(permissions, *args, **kwargs):
|
||||||
|
|
||||||
class RoleCrud(CrudView):
|
class RoleCrud(CrudView):
|
||||||
|
|
||||||
mapped_class = edbob.Role
|
mapped_class = Role
|
||||||
home_route = 'roles'
|
home_route = 'roles'
|
||||||
permissions = default_permissions
|
permissions = default_permissions
|
||||||
|
|
||||||
|
|
|
@ -32,28 +32,29 @@ from webhelpers.html.builder import HTML
|
||||||
import formalchemy
|
import formalchemy
|
||||||
from formalchemy.fields import SelectFieldRenderer
|
from formalchemy.fields import SelectFieldRenderer
|
||||||
|
|
||||||
import edbob
|
|
||||||
from edbob.db import auth
|
from edbob.db import auth
|
||||||
from edbob.pyramid import Session
|
from edbob.pyramid import Session
|
||||||
from edbob.pyramid.views import SearchableAlchemyGridView, CrudView
|
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):
|
class UsersGrid(SearchableAlchemyGridView):
|
||||||
|
|
||||||
mapped_class = edbob.User
|
mapped_class = User
|
||||||
config_prefix = 'users'
|
config_prefix = 'users'
|
||||||
sort = 'username'
|
sort = 'username'
|
||||||
|
|
||||||
def join_map(self):
|
def join_map(self):
|
||||||
return {
|
return {
|
||||||
'person':
|
'person':
|
||||||
lambda q: q.outerjoin(edbob.Person),
|
lambda q: q.outerjoin(Person),
|
||||||
}
|
}
|
||||||
|
|
||||||
def filter_map(self):
|
def filter_map(self):
|
||||||
return self.make_filter_map(
|
return self.make_filter_map(
|
||||||
ilike=['username'],
|
ilike=['username'],
|
||||||
person=self.filter_ilike(edbob.Person.display_name))
|
person=self.filter_ilike(Person.display_name))
|
||||||
|
|
||||||
def filter_config(self):
|
def filter_config(self):
|
||||||
return self.make_filter_config(
|
return self.make_filter_config(
|
||||||
|
@ -65,7 +66,7 @@ class UsersGrid(SearchableAlchemyGridView):
|
||||||
def sort_map(self):
|
def sort_map(self):
|
||||||
return self.make_sort_map(
|
return self.make_sort_map(
|
||||||
'username',
|
'username',
|
||||||
person=self.sorter(edbob.Person.display_name))
|
person=self.sorter(Person.display_name))
|
||||||
|
|
||||||
def grid(self):
|
def grid(self):
|
||||||
g = self.make_grid()
|
g = self.make_grid()
|
||||||
|
@ -92,7 +93,7 @@ def RolesFieldRenderer(request):
|
||||||
class RolesFieldRenderer(SelectFieldRenderer):
|
class RolesFieldRenderer(SelectFieldRenderer):
|
||||||
|
|
||||||
def render_readonly(self, **kwargs):
|
def render_readonly(self, **kwargs):
|
||||||
roles = Session.query(edbob.Role)
|
roles = Session.query(Role)
|
||||||
html = ''
|
html = ''
|
||||||
for uuid in self.value:
|
for uuid in self.value:
|
||||||
role = roles.get(uuid)
|
role = roles.get(uuid)
|
||||||
|
@ -117,15 +118,15 @@ class RolesField(formalchemy.Field):
|
||||||
return [x.uuid for x in user.roles]
|
return [x.uuid for x in user.roles]
|
||||||
|
|
||||||
def get_options(self):
|
def get_options(self):
|
||||||
q = Session.query(edbob.Role.name, edbob.Role.uuid)
|
q = Session.query(Role.name, Role.uuid)
|
||||||
q = q.filter(edbob.Role.uuid != auth.guest_role(Session()).uuid)
|
q = q.filter(Role.uuid != auth.guest_role(Session()).uuid)
|
||||||
q = q.order_by(edbob.Role.name)
|
q = q.order_by(Role.name)
|
||||||
return q.all()
|
return q.all()
|
||||||
|
|
||||||
def sync(self):
|
def sync(self):
|
||||||
if not self.is_readonly():
|
if not self.is_readonly():
|
||||||
user = self.model
|
user = self.model
|
||||||
roles = Session.query(edbob.Role)
|
roles = Session.query(Role)
|
||||||
data = self.renderer.deserialize()
|
data = self.renderer.deserialize()
|
||||||
user.roles = [roles.get(x) for x in data]
|
user.roles = [roles.get(x) for x in data]
|
||||||
|
|
||||||
|
@ -140,7 +141,7 @@ class _ProtectedPersonRenderer(formalchemy.FieldRenderer):
|
||||||
|
|
||||||
|
|
||||||
def ProtectedPersonRenderer(uuid):
|
def ProtectedPersonRenderer(uuid):
|
||||||
person = Session.query(edbob.Person).get(uuid)
|
person = Session.query(Person).get(uuid)
|
||||||
assert person
|
assert person
|
||||||
return type('ProtectedPersonRenderer', (_ProtectedPersonRenderer,),
|
return type('ProtectedPersonRenderer', (_ProtectedPersonRenderer,),
|
||||||
{'person': person})
|
{'person': person})
|
||||||
|
@ -187,7 +188,7 @@ class PasswordField(formalchemy.Field):
|
||||||
|
|
||||||
class UserCrud(CrudView):
|
class UserCrud(CrudView):
|
||||||
|
|
||||||
mapped_class = edbob.User
|
mapped_class = User
|
||||||
home_route = 'users'
|
home_route = 'users'
|
||||||
|
|
||||||
def fieldset(self, user):
|
def fieldset(self, user):
|
||||||
|
@ -213,7 +214,7 @@ class UserCrud(CrudView):
|
||||||
del fs.confirm_password
|
del fs.confirm_password
|
||||||
|
|
||||||
# if fs.edit and user.person:
|
# 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,
|
fs.person.set(readonly=True,
|
||||||
renderer=LinkedPersonRenderer(self.request))
|
renderer=LinkedPersonRenderer(self.request))
|
||||||
|
|
||||||
|
|
19
edbob/tests/__init__.py
Normal file
19
edbob/tests/__init__.py
Normal 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)
|
|
@ -38,9 +38,17 @@ if sys.platform == 'win32': # docs should build for everyone
|
||||||
import win32file
|
import win32file
|
||||||
import win32print
|
import win32print
|
||||||
import win32service
|
import win32service
|
||||||
import win32serviceutil
|
|
||||||
import winerror
|
import winerror
|
||||||
|
|
||||||
|
try:
|
||||||
|
import win32serviceutil
|
||||||
|
except ImportError:
|
||||||
|
# Mock out for testing on Linux.
|
||||||
|
class Object(object):
|
||||||
|
pass
|
||||||
|
win32serviceutil = Object()
|
||||||
|
win32serviceutil.ServiceFramework = Object
|
||||||
|
|
||||||
import edbob
|
import edbob
|
||||||
|
|
||||||
|
|
||||||
|
|
16
fabfile.py
vendored
16
fabfile.py
vendored
|
@ -22,25 +22,15 @@
|
||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
import os.path
|
import shutil
|
||||||
|
|
||||||
from fabric.api import *
|
from fabric.api import *
|
||||||
|
|
||||||
|
|
||||||
execfile(os.path.join(os.path.dirname(__file__), 'edbob', '_version.py'))
|
|
||||||
|
|
||||||
|
|
||||||
@task
|
@task
|
||||||
def release():
|
def release():
|
||||||
"""
|
"""
|
||||||
Release a new version of 'edbob'.
|
Release a new version of 'edbob'.
|
||||||
"""
|
"""
|
||||||
|
shutil.rmtree('edbob.egg-info')
|
||||||
local("python setup.py egg_info --tag-build='' sdist --formats=gztar")
|
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')
|
|
||||||
|
|
7
setup.cfg
Normal file
7
setup.cfg
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[nosetests]
|
||||||
|
nocapture = 1
|
||||||
|
cover-package = edbob
|
||||||
|
cover-erase = 1
|
||||||
|
cover-inclusive = 1
|
||||||
|
cover-html = 1
|
||||||
|
cover-html-dir = htmlcov
|
7
setup.py
7
setup.py
|
@ -73,7 +73,10 @@ requires = [
|
||||||
'decorator', # 3.3.2
|
'decorator', # 3.3.2
|
||||||
'lockfile', # 0.9.1
|
'lockfile', # 0.9.1
|
||||||
'progressbar', # 2.3
|
'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):
|
if sys.version_info < (2, 7):
|
||||||
|
@ -209,6 +212,8 @@ setup(
|
||||||
|
|
||||||
install_requires = requires,
|
install_requires = requires,
|
||||||
extras_require = extras,
|
extras_require = extras,
|
||||||
|
tests_require = requires + ['nose'],
|
||||||
|
test_suite = 'nose.collector',
|
||||||
|
|
||||||
packages = find_packages(),
|
packages = find_packages(),
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue