A solution for slow database resets in the test system?

1251 views
Skip to first unread message

Adrian Holovaty

unread,
Jul 27, 2007, 6:47:11 PM7/27/07
to django-d...@googlegroups.com
Hi all (but mostly Russell, the Test Master General :) ),

I have a significantly large set of fixture data for Django unit tests
in a work project, and the time lag in clearing and reinserting the
data between each test is getting to be frustrating. However, at the
same time, it's clearly important that the data be reset for each
test, so as not to corrupt test results.

I propose that we enable test creators to explicitly specify that a
particular test method on a TestCase class does *not* change the data
in the database, and, therefore, that the database does not have to be
reset after it's done. For syntax, we could use a decorator or a
function attribute, like so:

class MyTestCase(TestCase):
def testSomething(self):
# ...
testSomething.alters_db = False

With this, the test runner would be smart enough to know *not* to
reset the database after this test.

I don't know for certain whether this is possible within the limits of
the unit-test infrastructure, but I think it would be a great addition
for those of us who don't like waiting 30 seconds for four tests to
run. Russell, is this (1) possible and (2) worth implementing?

Adrian

--
Adrian Holovaty
holovaty.com | djangoproject.com

Russell Keith-Magee

unread,
Jul 27, 2007, 11:51:01 PM7/27/07
to django-d...@googlegroups.com
On 7/28/07, Adrian Holovaty <holo...@gmail.com> wrote:
>
> class MyTestCase(TestCase):
> def testSomething(self):
> # ...
> testSomething.alters_db = False
>
> With this, the test runner would be smart enough to know *not* to
> reset the database after this test.
>
> I don't know for certain whether this is possible within the limits of
> the unit-test infrastructure, but I think it would be a great addition
> for those of us who don't like waiting 30 seconds for four tests to
> run. Russell, is this (1) possible and (2) worth implementing?

Possibly possible, but I'm not sure it's worth implementing (or at
least, not quite in the way you describe).

The database flush only happens at the start of each test if you use a
django.test.TestCase. If you use unittest.TestCase or a doctest, no
flush is applied.

If you have a class of tests that don't touch the database backend,
you are pretty much rejecting any need for the fixtures framework or
the test Client, in which case, there is no need to use
django.test.TestCase.

This still leaves the slowdown caused by the initial syncdb. At
present, a syncdb is executed at the start of every test run. This
syncdb is even slower than the flush, so one way to speed up the '4
tests that don't touch the database' case would be to add some test
instrumentation (much like we do for the templating and email
systems), so that the first call to connection.cursor() invokes a
syncdb, rather than syncdb being called automatically every time you
run the suite.

I heartily concur on the larger issue, though. The tests are too damn
slow, and slow tests are tests that don't get run. I've just opened
ticket #4998 to track the problem.

I've been ruminating on this recently; the only solution I have come
up with so far is to introduce a mock database backend for testing
purposes. During a mock run, the mock backend would provide responses
that were previously recorded from a live database backend.

This would allow the test suite to run much faster, but when you start
making changes that affect the calls to the database, keeping the mock
responses in sync could be a bit painful. I've been thinking about
some sort of cache-like system: when a test runs, the mock backend
checks to see if there are cached mock responses. If cached responses
exist, they are used. If the test fails as a result, the live database
is swapped in, and the test is re-run; if the test passes on the live
database, the new mock responses are stored in the cache.

I haven't actually sat down to write any code to do this as of yet, so
Beelzebub and all his mates are almost certainly having a garden party
in Detail Park. Does anyone have any comments on this hand-wavy
design? Any better ideas?

Yours,
Russ Magee %-)

Adrian Holovaty

unread,
Jul 28, 2007, 12:10:11 AM7/28/07
to django-d...@googlegroups.com
On 7/27/07, Russell Keith-Magee <freakb...@gmail.com> wrote:
> The database flush only happens at the start of each test if you use a
> django.test.TestCase. If you use unittest.TestCase or a doctest, no
> flush is applied.
>
> If you have a class of tests that don't touch the database backend,
> you are pretty much rejecting any need for the fixtures framework or
> the test Client, in which case, there is no need to use
> django.test.TestCase.

In my case, I need django.test.TestCase because I'm using the fixtures
framework, but I don't want the database flushes because I'm only
using the database in a read-only fashion.

Specifically, I'm writing tests for a small series of Django ORM
extensions that are too application-specific to include in Django
proper. I've got sample data and just want to test that the extensions
work properly. Hope this makes sense...

I'd be happy to implement this -- just wanted to get your thoughts on
the feasibility.

> This still leaves the slowdown caused by the initial syncdb. At
> present, a syncdb is executed at the start of every test run. This
> syncdb is even slower than the flush, so one way to speed up the '4
> tests that don't touch the database' case would be to add some test
> instrumentation (much like we do for the templating and email
> systems), so that the first call to connection.cursor() invokes a
> syncdb, rather than syncdb being called automatically every time you
> run the suite.

That's not a bad idea. It wouldn't solve the particular problem I
brought up, but it would speed up tests for users whose unit tests
don't touch the database. This gets a +1 from me.

> I've been ruminating on this recently; the only solution I have come
> up with so far is to introduce a mock database backend for testing
> purposes. During a mock run, the mock backend would provide responses
> that were previously recorded from a live database backend.
>
> This would allow the test suite to run much faster, but when you start
> making changes that affect the calls to the database, keeping the mock
> responses in sync could be a bit painful. I've been thinking about
> some sort of cache-like system: when a test runs, the mock backend
> checks to see if there are cached mock responses. If cached responses
> exist, they are used. If the test fails as a result, the live database
> is swapped in, and the test is re-run; if the test passes on the live
> database, the new mock responses are stored in the cache.

Wow, this sounds complex -- I'd vote strongly against it.
Unfortunately, I don't have any better ideas, though. :-/

Russell Keith-Magee

unread,
Jul 28, 2007, 12:36:34 AM7/28/07
to django-d...@googlegroups.com
On 7/28/07, Adrian Holovaty <holo...@gmail.com> wrote:
>
> In my case, I need django.test.TestCase because I'm using the fixtures
> framework, but I don't want the database flushes because I'm only
> using the database in a read-only fashion.

If all you want is the fixtures, why not use a unittest.TestCase, and
put a call to management.load_data() in your TestCase.setUp() method?
This is effectively all that django.test.TestCase is doing anyway.
Given that what you are doing is a bit of an edge case, my gut
reaction is that it would be better to fix your problem by
implementing the test case you actually need, rather than modifying
the Django test case to support the edge case.

As a complete aside - looking at this from the implementation
perspective, it could be quite messy. Looking at the problem a little
closer, getting at a method attribute during a test run so as to
affect the call to setUp isn't that easy.

> Wow, this sounds complex -- I'd vote strongly against it.
> Unfortunately, I don't have any better ideas, though. :-/

Yeah. I didn't say it was a _good_ idea - just the only one I have
come up with that might be able to overcome the problem.

Russ %-)

Adrian Holovaty

unread,
Jul 28, 2007, 12:58:31 AM7/28/07
to django-d...@googlegroups.com
On 7/27/07, Russell Keith-Magee <freakb...@gmail.com> wrote:
> If all you want is the fixtures, why not use a unittest.TestCase, and
> put a call to management.load_data() in your TestCase.setUp() method?

I tried that and got the same problem. The setUp() method is called
before each test method of the TestCase class is called, not just once
before *all* tests for the class.

"""
from unittest import TestCase

class DatabaseTestCase(TestCase):
def setUp(self):
from django.core import management
print "Loading data!"
management.load_data(('my_data',), verbosity=0)

def testFoo(self):
# ...

def testBar(self):
# ...

def testBaz(self):
# ...
"""

$ django-admin.py test foo
Creating test database...
...
.Loading data =======================
.Loading data =======================
.Loading data =======================

I feel like I'm missing something fundamental here...

> As a complete aside - looking at this from the implementation
> perspective, it could be quite messy. Looking at the problem a little
> closer, getting at a method attribute during a test run so as to
> affect the call to setUp isn't that easy.

Yeah, I've been digging into the standard-library unittest.py module,
and it looks like this is a non-trivial fix. Grr!

Russell Keith-Magee

unread,
Jul 28, 2007, 3:40:01 AM7/28/07
to django-d...@googlegroups.com
On 7/28/07, Adrian Holovaty <holo...@gmail.com> wrote:
>
> On 7/27/07, Russell Keith-Magee <freakb...@gmail.com> wrote:
> > If all you want is the fixtures, why not use a unittest.TestCase, and
> > put a call to management.load_data() in your TestCase.setUp() method?
>
> I tried that and got the same problem. The setUp() method is called
> before each test method of the TestCase class is called, not just once
> before *all* tests for the class.

django.test.TestCase does the same thing, though. All the fixture
loading is effectively in setUp(), and setUp() always runs once per
test, not once per test case. So even with the change you are
proposing, you would be loading the test data multiple times (not that
this would make a huge difference - fixture loading is much faster
than a db-reset).

There isn't really any way to do a 'per TestCase' setup - at least,
not as part of the unittest framework. TestCases are designed to be
independent. The ability to put multiple tests in a single test class
is really just a convenience of construction.

Russ %-)

Russell Keith-Magee

unread,
Jul 28, 2007, 3:43:46 AM7/28/07
to django-d...@googlegroups.com
On 7/28/07, Adrian Holovaty <holo...@gmail.com> wrote:
>
> On 7/27/07, Russell Keith-Magee <freakb...@gmail.com> wrote:
>
> > This still leaves the slowdown caused by the initial syncdb. At
> > present, a syncdb is executed at the start of every test run. This
> > syncdb is even slower than the flush, so one way to speed up the '4
> > tests that don't touch the database' case would be to add some test
> > instrumentation (much like we do for the templating and email
> > systems), so that the first call to connection.cursor() invokes a
> > syncdb, rather than syncdb being called automatically every time you
> > run the suite.
>
> That's not a bad idea. It wouldn't solve the particular problem I
> brought up, but it would speed up tests for users whose unit tests
> don't touch the database. This gets a +1 from me.

<slaps forehead/>

I just knocked up a rough prototype around this idea... and it doesn't
make that much difference. I overlooked one important detail.

When you run a test suite that doesn't use the database, it means you
don't have any models, either - so syncdb is almost a no-op. For
example, the forms regression test takes about 5 seconds to run on my
machine - but only half a second of that is setting up the (empty)
database.

Yours,
Russ Magee %-)

Ivan Sagalaev

unread,
Jul 28, 2007, 4:37:51 AM7/28/07
to django-d...@googlegroups.com
Russell Keith-Magee wrote:
> If all you want is the fixtures, why not use a unittest.TestCase, and
> put a call to management.load_data() in your TestCase.setUp() method?

Speaking for myself I switched to Django's TestCase because it was just
more convenient: it has fixture loading and self.client. And both can be
used read-only. If I would have to fight slow testing by looking through
test code and replacing some test to use unittest.TestCase then it would
be a mess, honestly. And what if some particular test case will change
so it either starts or stops to need a write to a db? Changing it back
and forth to and from using Django's TestCase would be very boring and
error-prone.

Andrey Khavryuchenko

unread,
Jul 28, 2007, 12:28:12 PM7/28/07
to django-d...@googlegroups.com
Russell,

RK> I've been ruminating on this recently; the only solution I have come
RK> up with so far is to introduce a mock database backend for testing
RK> purposes. During a mock run, the mock backend would provide responses
RK> that were previously recorded from a live database backend.

That was the exact reason for me to create DbMock announced yesterday on
django-users. Mysql -> in-memory sqllite with some mysql compatability
hooks gave me enough speedup.

--
Andrey V Khavryuchenko
Django NewGate - http://www.kds.com.ua/djiggit/
Development - http://www.kds.com.ua
Call akhavr1975 on www.gizmoproject.com

Russell Keith-Magee

unread,
Jul 29, 2007, 1:32:05 AM7/29/07
to django-d...@googlegroups.com
On 7/29/07, Andrey Khavryuchenko <akh...@gmail.com> wrote:
>
> Russell,
>
> RK> I've been ruminating on this recently; the only solution I have come
> RK> up with so far is to introduce a mock database backend for testing
> RK> purposes. During a mock run, the mock backend would provide responses
> RK> that were previously recorded from a live database backend.
>
> That was the exact reason for me to create DbMock announced yesterday on
> django-users. Mysql -> in-memory sqllite with some mysql compatability
> hooks gave me enough speedup.

In-memory sqlite testing and mocking are not the same thing. Like I
said in my reply yesterday, you can already do in-memory SQLite tests
with the existing test framework. In fact, _all_ tests that run with
SQLite are run with an in-memory database. No external tools or tricks
are required to do this. Mocking is running the tests without any
database at all, sqlite or otherwise.

Yours,
Russ Magee %-)

Andy Gayton

unread,
Aug 4, 2007, 12:39:26 PM8/4/07
to django-d...@googlegroups.com
Adrian Holovaty wrote:
> Hi all (but mostly Russell, the Test Master General :) ),
>
> I have a significantly large set of fixture data for Django unit tests
> in a work project, and the time lag in clearing and reinserting the
> data between each test is getting to be frustrating. However, at the
> same time, it's clearly important that the data be reset for each
> test, so as not to corrupt test results.

I'm worried about the emphasis in Django tests to share enormous fixture
datasets. Some rules of thumbs I've drifted towards after ending up
with unruly test suites a couple of times are:

* explicitly create just enough data needed for each test case

* this keeps test understandable, you can see at a glance the data a
test is working with

* it cuts down on unexpected side effects

* reduces maintenance - if new tests require additional shared
fixture data, this could unexpectedly change the results of existing tests

* encourages TDD. with a tightly defined dataset, the result of a
function is more obvious, and you can assert that before writing the
function. which large datasets, its often easier to write the function,
see the result, do some manual verification its right, and then assert that.

* test run fast! :)

* each test should, as much as possible, test just one thing

* with huge fixtures, you're encouraged to make a test do a lot of
work to save on test load time

* only test things once

> I propose that we enable test creators to explicitly specify that a
> particular test method on a TestCase class does *not* change the data
> in the database, and, therefore, that the database does not have to be
> reset after it's done.

This would further encourage large shared fixtures - making the problem
worse.

cheers,
Andy.

Russell Keith-Magee

unread,
Aug 4, 2007, 8:22:11 PM8/4/07
to django-d...@googlegroups.com
On 8/5/07, Andy Gayton <andy....@gmail.com> wrote:

>
> Adrian Holovaty wrote:
> I'm worried about the emphasis in Django tests to share enormous fixture
> datasets. Some rules of thumbs I've drifted towards after ending up
> with unruly test suites a couple of times are:

I'm not sure I understand what you see as the problem. Django allows
you to define as many test fixtures as you require; then you define
test cases that use the fixtures. Sure, you _could_ define a single
huge test fixture, but you also _could_ put all your Python code into
a single file rather than splitting into modules.

Unless I'm missing something, there is nothing in the test system or
documentation that requires or places emphasis on having a single
large test fixture. The Django system tests have a large number of
fixtures - all of which are quite small, and only loaded into tests as
required.

> * test run fast! :)

If you profile test running, you will find that loading the dataset is
generally not the slow part. The slow part is the reset - regardless
of how much data is in the fixture.

Yours,
Russ Magee %-)

Andy Gayton

unread,
Aug 5, 2007, 2:44:52 PM8/5/07
to django-d...@googlegroups.com
Russell Keith-Magee wrote:
> On 8/5/07, Andy Gayton <andy....@gmail.com> wrote:
>> Adrian Holovaty wrote:
>> I'm worried about the emphasis in Django tests to share enormous fixture
>> datasets. Some rules of thumbs I've drifted towards after ending up
>> with unruly test suites a couple of times are:
>>
>> * explicitly create just enough data needed for each test case

> I'm not sure I understand what you see as the problem. Django allows


> you to define as many test fixtures as you require; then you define
> test cases that use the fixtures.

Sorry I'm mixing up my terminology. My experience has found that its
best to define just the data required for each individual test, so each
test_*. If all tests in a TestCase share a couple of common records -
these can be created sparingly in your setUp - but since it should just
be a couple of records - you could have the data in the TestCase, so it
obvious what data is being used:

...
def setUp(self):
self.loadFixture([
{
"pk": "1",
"model": "auth.user",
"fields": {
"username": "testclient",
"first_name": "Test",
"last_name": "Client",
"is_active": true,
"is_superuser": false,
"is_staff": false,
"last_login": "2006-12-17 07:03:31",
"groups": [],
"user_permissions": [],
"password":
"sha1$6efc0$f93efe9fd7542f25a7be94871ea45aa95de57161",
"email": "testc...@example.com",
"date_joined": "2006-12-17 07:03:31"
}
},
{
"pk": "2",
"model": "auth.user",
"fields": {
"username": "inactive",
"first_name": "Inactive",
"last_name": "User",
"is_active": false,
"is_superuser": false,
"is_staff": false,
"last_login": "2006-12-17 07:03:31",
"groups": [],
"user_permissions": [],
"password":
"sha1$6efc0$f93efe9fd7542f25a7be94871ea45aa95de57161",
"email": "testc...@example.com",
"date_joined": "2006-12-17 07:03:31"
}
}
])


Or you could define conveniences to make it more concise:

...
def test_inactive_not_allowed(self):
self._createUser('testuser')
self._createUser('inactive', is_active=False)
....

This allows you to focus on the data that's relevant to the individual
test. If a test is asserting that inactive users can't get access to a
particular resource - populating their first and last name, say, is not
needed and distracts from the tests purpose.

If its easy enough to do, the temptation to create common data for the
entire TestCase is reduced. I don't think Django should provide
conveniences to this level - they're easy enough to define for your app.

> Unless I'm missing something, there is nothing in the test system or
> documentation that requires or places emphasis on having a single
> large test fixture.

The fixture loading conveniences are for a TestCase.

class AnimalTestCase(TestCase):
fixtures = ['mammals.json', 'birds']

I've found this was enticing me to have one TestCase for my model. Its
really easy using the admin tool to populate your entire model with a
base set of sample data. You can use manage.py dumpdata to dump this
out - and then using the above snippet can be reloading a pretty large
dataset for every test, most of which isn't needed for each given test.

> The Django system tests have a large number of
> fixtures - all of which are quite small, and only loaded into tests as
> required.

Right, I'm impressed the fixtures for the core library are just 1 or at
most 2 records. Apologies if I'm reading into this wrong. There's no
reason with the current conveniences why you can't have a bunch of
TestCases for your model, each with a fixture which loads only a small
dataset relevant for that group of tests.

>> * test run fast! :)
>
> If you profile test running, you will find that loading the dataset is
> generally not the slow part. The slow part is the reset - regardless
> of how much data is in the fixture.

That's interesting. Although, Adrian, how large is the fixture set you
are working with - that mentioned when raising this thread?

cheers,
Andy.

Russell Keith-Magee

unread,
Aug 5, 2007, 8:18:08 PM8/5/07
to django-d...@googlegroups.com
On 8/6/07, Andy Gayton <andy....@gmail.com> wrote:
>
> def test_inactive_not_allowed(self):
> self._createUser('testuser')
> self._createUser('inactive', is_active=False)
> ....
>
> This allows you to focus on the data that's relevant to the individual
> test. If a test is asserting that inactive users can't get access to a
> particular resource - populating their first and last name, say, is not
> needed and distracts from the tests purpose.

I agree with your premise - that testing dataset for each test should
be minimal - but might I suggest that the problem here is that your
tests need to be refactored. You have essentially defined:

class MyTest(TestCase):
fixture = ['testuser','inactive']
test_inactive_not_allowed(self):
...
test_active_allowed(self):
...

When what you should have is two tests:

class ActiveUserTests
fixtures = ['testuser']
test_allowed(self):
...

class InactiveUserTests(TestCase):
fixtures = ['inactive']
test_not_allowed(self):
...

So - not only do you write lots of small fixture files - you write
lots of small test cases, and each test case requires a very specific
set of test conditions.

> > Unless I'm missing something, there is nothing in the test system or
> > documentation that requires or places emphasis on having a single
> > large test fixture.
>
> The fixture loading conveniences are for a TestCase.
>
> class AnimalTestCase(TestCase):
> fixtures = ['mammals.json', 'birds']
>
> I've found this was enticing me to have one TestCase for my model. Its
> really easy using the admin tool to populate your entire model with a
> base set of sample data. You can use manage.py dumpdata to dump this
> out - and then using the above snippet can be reloading a pretty large
> dataset for every test, most of which isn't needed for each given test.

Ok; this one is a documentation issue. Any specific suggestions on
ways to improve the documentation are welcome.

However, we're torn between a need to tell people that it is possible
to define multiple fixtures, and inadvertantly establishing best
practice by way of example. This is a difficult problem; if we make
the example complex enough to warrant defining multiple fixtures, the
example ceases to be a good demonstration of the simple case.

We also should be trying to avoid teaching people about testing. Many
other people have written volumes on how to test. IMHO, Django's
documentation should be about explaining the facilities that Django
provides, not teaching testing best practice from first principles.

Yours,
Russ Magee %-)

Alex Nikolaenkov

unread,
Aug 6, 2007, 2:10:19 AM8/6/07
to django-d...@googlegroups.com

ME:
>> * What do you think about including Web Typography support as a
>> built-in django feature?

Jacob:
> I think it's a great idea. We currently don't have a process by which
> apps are added to contrib, and that's the only thing holding us back.
> I'm working on proposing such a process, and once the development
> community has had a chance to tell me where I got it wrong, typography
> is one of the first things I'd like to propose for addition to
> contrib.

Web typography is a feature which will put Django 10 steps ahead many
other CMS, most of which were written not for making high-valued
super-fast web sites, but for the purpose of money by the bunch
of people not understanding WHAT THE WEB REALLY IS.

Can you publish your plan concerning contributing applications? The first
thing I'll do in django & python will be typography support.

From my point of view every application should be at least:
* stable enough to be included into the Django package.
The OK level of quality should be defined.

IMO TDD is a very good practice. So unit-tests for applications to be
included into the standard django package are the must. Are there
tools for python showing "unit test coverage" for the module
(Something like Jester for Java)?

* Have bugtracker for user support
* Comprehensive free documentation.

* Compatible license
Are commercial modules are allowed? I think this is a big yes-yes
to include commercial modules support to django. Someone will be
able to build business writing good applications for YOUR system ;)
Eh... what do u think?


--
Best regards,
Alex mailto:nikol...@actimind.com

James Bennett

unread,
Aug 6, 2007, 3:52:56 AM8/6/07
to django-d...@googlegroups.com
On 8/6/07, Alex Nikolaenkov <nikol...@actimind.com> wrote:
> Can you publish your plan concerning contributing applications? The first
> thing I'll do in django & python will be typography support.

You might want to have a look at this before starting your own project:

http://code.google.com/p/typogrify/

--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."

Alex Nikolaenkov

unread,
Aug 6, 2007, 4:09:17 AM8/6/07
to James Bennett
Hi James!

> You might want to have a look at this before starting your own project:
> http://code.google.com/p/typogrify/

Thank you for your link. I saw. It implements only a small piece of typography.

There are a lot more features to do, including
* comprehensive documentation with examples
* unit tests
* Multi-language support
* Correct white-space handling.
.... a lot more about typography itself.

Emanuele Pucciarelli

unread,
Aug 6, 2007, 5:17:51 AM8/6/07
to django-d...@googlegroups.com
Il giorno 06/ago/07, alle ore 08:10, Alex Nikolaenkov ha scritto:

> IMO TDD is a very good practice. So unit-tests for applications to be
> included into the standard django package are the must. Are there
> tools for python showing "unit test coverage" for the module
> (Something like Jester for Java)?

There's Ned Batchelder's coverage.py: http://nedbatchelder.com/code/
modules/coverage.html . Haven't tried it myself, but I have to
suppose that it's Django-friendly. :)

Regards,

--
Emanuele

Brett Hoerner

unread,
Aug 6, 2007, 9:28:57 AM8/6/07
to django-d...@googlegroups.com
On 8/6/07, Emanuele Pucciarelli <e...@acm.org> wrote:
> There's Ned Batchelder's coverage.py: http://nedbatchelder.com/code/
> modules/coverage.html . Haven't tried it myself, but I have to
> suppose that it's Django-friendly. :)

http://siddhi.blogspot.com/2007/04/code-coverage-for-your-django-code.html
http://eddymulyono.livejournal.com/62101.html

Brett

Jacob Kaplan-Moss

unread,
Aug 6, 2007, 10:54:36 AM8/6/07
to django-d...@googlegroups.com
On 8/6/07, Emanuele Pucciarelli <e...@acm.org> wrote:
> There's Ned Batchelder's coverage.py: http://nedbatchelder.com/code/
> modules/coverage.html . Haven't tried it myself, but I have to
> suppose that it's Django-friendly. :)

A while back I started experimenting with coverage using figleaf
(Titus Brown's next-gen spinoff of coverage.py). I particularly liked
figleaf's HTML output; far easier to read than a whole honking mess of
console text.

I keep meaning to dust it off and finish it up, but haven't had the
chance. Coverage support would be *great* to have in Django-proper,
though, so if anyone wants to experiment with figleaf, coverage, or
anything else I'd *love* to review some patches.

Jacob

Malcolm Tredinnick

unread,
Aug 7, 2007, 8:35:17 PM8/7/07
to django-d...@googlegroups.com
I'll address the logistical part of your questions, since they don't
seem to have been answered yet.

On Mon, 2007-08-06 at 10:10 +0400, Alex Nikolaenkov wrote:
[...]

> Can you publish your plan concerning contributing applications? The first
> thing I'll do in django & python will be typography support.

Since contributed applications are just Python packages, they do not
need to be part of Django at all. A nice consequence is that we
encourage people to first build something as a separate application that
simply lives somewhere on the user's Python path when they want to use
it (so they can import it). After all, that's all anything in
django.contrib is doing.

At a later date, if any isolated project is considered useful enough to
include in Django, it should be just a matter of moving it inside
django/contrib/. However, initially, you should not require it to be
installed there (so that people can keep their source pristine and still
use your application).


>
> From my point of view every application should be at least:
> * stable enough to be included into the Django package.
> The OK level of quality should be defined.
>
> IMO TDD is a very good practice. So unit-tests for applications to be
> included into the standard django package are the must. Are there
> tools for python showing "unit test coverage" for the module
> (Something like Jester for Java)?
>
> * Have bugtracker for user support

The standard way to do this for third-party apps at the moment, if you
don't want to set anything up, is to use Google Code hosting.

> * Comprehensive free documentation.
>
> * Compatible license
> Are commercial modules are allowed? I think this is a big yes-yes
> to include commercial modules support to django.

What does "commercial" mean here? It's not a very well-defined term --
there are many Open Source licenses that permit commercialisation of the
end-product in different ways -- so think about it more in terms of
license compatibility. For a third-party application, you can use
whatever you like, however if it requires an end-user license that is
not compatible with existing OSI-approved licenses, you are going to
harm your adoption rate. Django itself is under the new-style BSD
license (the same as Python). That is a good compatibility point to aim
for, since it makes it a lot easier for end-users auditing their license
compliance. However, other things are possible, too. Just be very clear
in the README file what the restrictions for the various requirements
are.

Regards,
Malcolm

--
Quantum mechanics: the dreams stuff is made of.
http://www.pointy-stick.com/blog/

Todd O'Bryan

unread,
Aug 7, 2007, 9:34:59 PM8/7/07
to django-d...@googlegroups.com
On Wed, 2007-08-08 at 10:35 +1000, Malcolm Tredinnick wrote:
> Since contributed applications are just Python packages, they do not
> need to be part of Django at all. A nice consequence is that we
> encourage people to first build something as a separate application that
> simply lives somewhere on the user's Python path when they want to use
> it (so they can import it). After all, that's all anything in
> django.contrib is doing.
>
> At a later date, if any isolated project is considered useful enough to
> include in Django, it should be just a matter of moving it inside
> django/contrib/. However, initially, you should not require it to be
> installed there (so that people can keep their source pristine and still
> use your application).

The dbmigration package that several people are using is currently
distributed as a patch for Django, but as I'm trying to set up 30 high
school students to work on a Django project for a class I'm teaching, I
realize I don't want to deal with the vagaries of adding patches and
appreciate what Malcolm says about keeping one's source pristine.

The tough thing is that the dbmigration code modifies the behavior of
syncdb. Now whether one should do that or not is debatable (I suppose
you could do './manage.py migratedb' instead), but shouldn't there be
some way for third-party code to add features to manage.py in a clean
way so that you can both keep the Django source pristine and still
provide extra functionality for the manage.py script? Is there currently
a way to do that or does anybody have any ideas how to do it cleanly?

Malcolm Tredinnick

unread,
Aug 7, 2007, 9:48:06 PM8/7/07
to django-d...@googlegroups.com
On Tue, 2007-08-07 at 21:34 -0400, Todd O'Bryan wrote:
[...]

> The tough thing is that the dbmigration code modifies the behavior of
> syncdb. Now whether one should do that or not is debatable (I suppose
> you could do './manage.py migratedb' instead), but shouldn't there be
> some way for third-party code to add features to manage.py in a clean
> way so that you can both keep the Django source pristine and still
> provide extra functionality for the manage.py script? Is there currently
> a way to do that or does anybody have any ideas how to do it cleanly?

If something has to patch core, then it has to patch core. It should
still try to work with as little patching as possible, though, I would
think. The way we are managing the Summer of Code students' work this
year is asking them to have a minimal patch against core for anything
like that. The constraints project has such a patch for example. That
way, the impact on Django itself is minimal (most of the stuff is just a
third-party package).

There isn't a generic way to do this (add manage.py commands) at the
moment. We could potentially allow them to add hooks via the
management.py file that can exist in any application (it's a way to do
post-syncdb handling currently). So django.core.management would suck in
any extra commands from installed apps that way. That might not be too
difficult to implement, thinking about it. Once you have a settings
file, you have access to installed apps and their import incantations.

Modifying existing behaviour -- and I haven't thought enough about
dbmigration to have an opinion on whether its approach works well or not
-- is always going to require a core patch. I don't think we would want
third-party apps able to hijack standard commands.

Regards,
Malcolm

--
The hardness of butter is directly proportional to the softness of the
bread.
http://www.pointy-stick.com/blog/

Reply all
Reply to author
Forward
0 new messages