+++++++++++++++++++++++++ SQLObject Developer Guide +++++++++++++++++++++++++ .. contents:: :backlinks: none .. _start: These are some notes on developing SQLObject. I'll try to expand them as things come up. If you are committing to the SQLObject repository, please also read ``/using-this-repository.txt``, which is just about file layout and repository cooperation. -- Ian Bicking Development Installation ======================== First install `FormEncode `_:: $ svn co http://svn.colorstudy.com/FormEncode/trunk FormEncode $ cd FormEncode $ sudo python setup.py develop Then do the same for SQLObject:: $ svn co http://svn.colorstudy.com/SQLObject/trunk SQLObject $ cd SQLObject $ sudo python setup.py develop Voila! The packages are globally installed, but the files from the checkout were not copied into ``site-packages``. See `setuptools `_ for more. Style Guide =========== Generally you should follow the recommendations in `PEP 8`_, the Python Style Guide. Some things to take particular note of: .. _PEP 8: http://www.python.org/peps/pep-0008.html * **No tabs**. Not anywhere. Always indent with 4 spaces. * I don't stress too much on line length. But try to break lines up by grouping with parenthesis instead of with backslashes (if you can). Do asserts like:: assert some_condition(a, b), ( "Some condition failed, %r isn't right!" % a) * But if you are having problems with line length, maybe you should just break the expression up into multiple statements. * Blank lines between methods, unless they are very small and closely bound to each other. * *Never* use the form ``condition and trueValue or falseValue``. Break it out and use a variable. * Careful of namespace pollution. SQLObject does allow for ``from sqlobject import *`` so names should be fairly distinct, or they shouldn't be exported in ``sqlobject.__init__``. * I'm very picky about whitespace. There's one and only one right way to do it. Good examples:: short = 3 longerVar = 4 if x == 4: do stuff func(arg1='a', arg2='b') func((a + b)*10) **Bad** examples:: short =3 longerVar=4 if x==4: do stuff func(arg1 = 'a', arg2 = 'b') func(a,b) func( a, b ) [ 1, 2, 3 ] To me, the poor use of whitespace seems lazy. I'll think less of your code (justified or not) for this very trivial reason. I will fix all your code for you if you don't do it yourself, because I can't bear to look at sloppy whitespace. * Use ``@@`` to mark something that is suboptimal, or where you have a concern that it's not right. Try to also date it and put your username there. * Docstrings are good. They should look like:: class AClass(object): """ doc string... """ Don't use single quotes ('''). Don't bother trying make the string less vertically compact. * Comments go right before the thing they are commenting on. * Methods never, ever, ever start with capital letters. Generally only classes are capitalized. But definitely never methods. * mixedCase is preferred. * Use ``cls`` to refer to a class. Use ``meta`` to refer to a metaclass (which also happens to be a class, but calling a metaclass ``cls`` will be confusing). * Use ``isinstance`` instead of comparing types. E.g.:: if isinstance(var, str): ... # Bad: if type(var) is StringType: ... * Never, ever use two leading underscores. This is annoyingly private. If name clashes are a concern, use name mangling instead (e.g., ``_SO_blahblah``). This is essentially the same thing as double-underscore, only it's transparent where double underscore obscures. * Module names should be unique in the package. Subpackages shouldn't share module names with sibling or parent packages. Sadly this isn't possible for ``__init__``, but it's otherwise easy enough. * Module names should be all lower case, and probably have no underscores (smushedwords). Testing ======= Tests are important. Tests keep everything from falling apart. All new additions should have tests. Testing uses `py.test`__, an alternative to ``unittest``. It is available via subversion at http://codespeak.net/svn/py/dist. Read its `getting started`_ document for more. .. __: http://codespeak.net/py/current/doc/test.html .. _getting started: http://codespeak.net/py/dist/test.html#starting-point-py-test-command-line-tool To actually run the test, you have to give it a database to connect to. You do this with the ``TESTDB`` environmental variable (right now py.test doesn't have a better way to add custom options). You can give the complete URI to access your test database, or you can give it a shortcut like ``mysql`` (these shortcuts are defined in the top of ``tests/dbtest.py``. All the tests are modules in ``sqlobject/tests``. Each module tests one kind of feature, more or less. If you are testing a module, call the test module ``tests/test_modulename.py`` -- only modules that start with ``test_`` will be picked up by py.test. The "framework" for testing is in ``tests/dbtest``. There's a couple of important functions: ``setupClass(soClass)`` creates the tables for the class. It tries to avoid recreating tables if not necessary. ``supports(featureName)`` checks if the database backend supports the named feature. What backends support what is defined at the top of ``dbtest``. If you ``import *`` you'll also get py.test's version of raises_, an ``inserts`` function that can create instances for you, and a couple miscellaneous functions. .. _raises: http://codespeak.net/py/current/doc/test.html#id4 If you submit a patch or implement a feature without a test, I'll be forced to write the test. That's no fun for me, to just be writing tests. So please, write tests; everything at least needs to be exercised, even if the tests are absolutely complete. Documentation ============= Please write documentation. Documentation should live in the docs/ directory. Pudge converts documentation from Restructured Text to HTML. It presently requires kid 0.9.3, which must be obtained separately (for instance, from http://cheeseshop.python.org/pypi/kid/0.9.3) .. image:: http://sourceforge.net/sflogo.php?group_id=74338&type=4 :height: 37 :width: 125 :alt: Hosted by SourceForge :target: http://sourceforge.net/