2014-06-30 18:42:27 -07:00
|
|
|
Contributing and feedback guidelines
|
2014-05-26 12:32:05 +02:00
|
|
|
####################################
|
2011-05-10 23:41:27 +01:00
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
There are many ways to contribute to Pelican. You can improve the
|
|
|
|
|
documentation, add missing features, and fix bugs (or just report them). You
|
|
|
|
|
can also help out by reviewing and commenting on
|
|
|
|
|
`existing issues <https://github.com/getpelican/pelican/issues>`_.
|
|
|
|
|
|
2014-05-26 12:32:05 +02:00
|
|
|
Don't hesitate to fork Pelican and submit an issue or pull request on GitHub.
|
|
|
|
|
When doing so, please adhere to the following guidelines.
|
2013-04-13 16:55:13 -07:00
|
|
|
|
|
|
|
|
.. include:: ../CONTRIBUTING.rst
|
2011-05-10 23:59:21 +01:00
|
|
|
|
2012-03-06 06:13:17 -08:00
|
|
|
Setting up the development environment
|
|
|
|
|
======================================
|
2011-05-10 23:59:21 +01:00
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
While there are many ways to set up one's development environment, following
|
|
|
|
|
is a method that uses `virtualenv <http://www.virtualenv.org/>`_. If you don't
|
|
|
|
|
have ``virtualenv`` installed, you can install it via::
|
2011-05-10 23:59:21 +01:00
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
$ pip install virtualenv
|
2011-05-10 23:59:21 +01:00
|
|
|
|
2012-03-06 06:13:17 -08:00
|
|
|
Virtual environments allow you to work on Python projects which are isolated
|
|
|
|
|
from one another so you can use different packages (and package versions) with
|
|
|
|
|
different projects.
|
2011-05-10 23:59:21 +01:00
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
To create and activate a virtual environment, use the following syntax::
|
2011-05-10 23:59:21 +01:00
|
|
|
|
2013-04-16 10:13:47 -07:00
|
|
|
$ virtualenv ~/virtualenvs/pelican
|
2013-04-13 16:55:13 -07:00
|
|
|
$ cd ~/virtualenvs/pelican
|
|
|
|
|
$ . bin/activate
|
2011-05-10 23:59:21 +01:00
|
|
|
|
2012-08-01 18:20:12 -07:00
|
|
|
To clone the Pelican source::
|
2011-05-10 23:59:21 +01:00
|
|
|
|
2012-08-01 18:20:12 -07:00
|
|
|
$ git clone https://github.com/getpelican/pelican.git src/pelican
|
|
|
|
|
|
|
|
|
|
To install the development dependencies::
|
|
|
|
|
|
|
|
|
|
$ cd src/pelican
|
2011-05-10 23:59:21 +01:00
|
|
|
$ pip install -r dev_requirements.txt
|
2012-08-01 18:20:12 -07:00
|
|
|
|
|
|
|
|
To install Pelican and its dependencies::
|
|
|
|
|
|
2012-02-20 17:58:23 +01:00
|
|
|
$ python setup.py develop
|
2011-05-10 23:41:27 +01:00
|
|
|
|
2013-05-26 12:44:32 +02:00
|
|
|
Or using ``pip``::
|
|
|
|
|
|
|
|
|
|
$ pip install -e .
|
|
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
Building the docs
|
|
|
|
|
=================
|
|
|
|
|
|
|
|
|
|
If you make changes to the documentation, you should preview your changes
|
|
|
|
|
before committing them::
|
|
|
|
|
|
|
|
|
|
$ pip install sphinx
|
|
|
|
|
$ cd src/pelican/docs
|
|
|
|
|
$ make html
|
|
|
|
|
|
|
|
|
|
Open ``_build/html/index.html`` in your browser to preview the documentation.
|
|
|
|
|
|
2011-05-10 23:41:27 +01:00
|
|
|
Running the test suite
|
2011-05-10 23:59:21 +01:00
|
|
|
======================
|
|
|
|
|
|
|
|
|
|
Each time you add a feature, there are two things to do regarding tests:
|
2013-04-13 16:55:13 -07:00
|
|
|
check that the existing tests pass, and add tests for the new feature
|
2012-08-01 18:20:12 -07:00
|
|
|
or bugfix.
|
2011-05-10 23:41:27 +01:00
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
The tests live in ``pelican/tests`` and you can run them using the
|
|
|
|
|
"discover" feature of ``unittest``::
|
2011-05-10 23:41:27 +01:00
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
$ python -m unittest discover
|
2012-03-09 16:27:23 +01:00
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
After making your changes and running the tests, you may see a test failure
|
|
|
|
|
mentioning that "some generated files differ from the expected functional tests
|
|
|
|
|
output." If you have made changes that affect the HTML output generated by
|
|
|
|
|
Pelican, and the changes to that output are expected and deemed correct given
|
|
|
|
|
the nature of your changes, then you should update the output used by the
|
|
|
|
|
functional tests. To do so, you can use the following two commands::
|
2012-04-04 23:18:11 +02:00
|
|
|
|
2013-08-05 19:18:43 +02:00
|
|
|
$ LC_ALL=en_US.utf8 pelican -o pelican/tests/output/custom/ \
|
|
|
|
|
-s samples/pelican.conf.py samples/content/
|
2014-04-27 10:25:57 +02:00
|
|
|
$ LC_ALL=fr_FR.utf8 pelican -o pelican/tests/output/custom_locale/ \
|
2014-06-26 00:51:45 -04:00
|
|
|
-s samples/pelican.conf_FR.py samples/content/
|
2013-08-05 19:18:43 +02:00
|
|
|
$ LC_ALL=en_US.utf8 pelican -o pelican/tests/output/basic/ \
|
2012-04-04 23:18:11 +02:00
|
|
|
samples/content/
|
|
|
|
|
|
2013-05-26 12:44:32 +02:00
|
|
|
Testing on Python 2 and 3
|
|
|
|
|
-------------------------
|
2013-01-11 03:21:06 +01:00
|
|
|
|
2013-05-26 12:44:32 +02:00
|
|
|
Testing on Python 3 currently requires some extra steps: installing
|
|
|
|
|
Python 3-compatible versions of dependent packages and plugins.
|
2013-01-11 03:21:06 +01:00
|
|
|
|
2013-05-26 12:44:32 +02:00
|
|
|
Tox_ is a useful tool to run tests on both versions. It will install the
|
|
|
|
|
Python 3-compatible version of dependent packages.
|
2013-01-11 03:21:06 +01:00
|
|
|
|
2013-05-26 12:44:32 +02:00
|
|
|
.. _Tox: http://testrun.org/tox/latest/
|
2012-03-09 16:27:23 +01:00
|
|
|
|
2013-05-26 12:44:32 +02:00
|
|
|
Python 3 development tips
|
|
|
|
|
=========================
|
2013-01-11 03:21:06 +01:00
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
Here are some tips that may be useful when doing some code for both Python 2.7
|
2013-05-26 12:44:32 +02:00
|
|
|
and Python 3 at the same time:
|
2013-01-11 03:21:06 +01:00
|
|
|
|
2013-04-13 16:55:13 -07:00
|
|
|
- Assume every string and literal is unicode (import unicode_literals):
|
2013-01-11 03:21:06 +01:00
|
|
|
|
|
|
|
|
- Do not use prefix ``u'``.
|
|
|
|
|
- Do not encode/decode strings in the middle of sth. Follow the code to the
|
|
|
|
|
source (or target) of a string and encode/decode at the first/last possible
|
|
|
|
|
point.
|
|
|
|
|
- In other words, write your functions to expect and to return unicode.
|
|
|
|
|
- Encode/decode strings if e.g. the source is a Python function that is known
|
|
|
|
|
to handle this badly, e.g. strftime() in Python 2.
|
|
|
|
|
|
|
|
|
|
- Use new syntax: print function, "except ... *as* e" (not comma) etc.
|
|
|
|
|
- Refactor method calls like ``dict.iteritems()``, ``xrange()`` etc. in a way
|
|
|
|
|
that runs without code change in both Python versions.
|
|
|
|
|
- Do not use magic method ``__unicode()__`` in new classes. Use only ``__str()__``
|
|
|
|
|
and decorate the class with ``@python_2_unicode_compatible``.
|
|
|
|
|
- Do not start int literals with a zero. This is a syntax error in Py3k.
|
|
|
|
|
- Unfortunately I did not find an octal notation that is valid in both
|
|
|
|
|
Pythons. Use decimal instead.
|
|
|
|
|
- use six, e.g.:
|
|
|
|
|
|
|
|
|
|
- ``isinstance(.., basestring) -> isinstance(.., six.string_types)``
|
|
|
|
|
- ``isinstance(.., unicode) -> isinstance(.., six.text_type)``
|
|
|
|
|
|
|
|
|
|
- ``setlocale()`` in Python 2 bails when we give the locale name as unicode,
|
|
|
|
|
and since we are using ``from __future__ import unicode_literals``, we do
|
|
|
|
|
that everywhere! As a workaround, I enclosed the localename with ``str()``;
|
|
|
|
|
in Python 2 this casts the name to a byte string, in Python 3 this should do
|
|
|
|
|
nothing, because the locale name already had been unicode.
|
|
|
|
|
|
|
|
|
|
- Kept range() almost everywhere as-is (2to3 suggests list(range())), just
|
|
|
|
|
changed it where I felt necessary.
|
|
|
|
|
|
|
|
|
|
- Changed xrange() back to range(), so it is valid in both Python versions.
|
2014-04-01 20:44:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Logging tips
|
|
|
|
|
============
|
|
|
|
|
|
|
|
|
|
Try to use logging with appropriate levels.
|
|
|
|
|
|
2014-07-22 11:48:15 -04:00
|
|
|
For logging messages that are not repeated, use the usual Python way::
|
2014-04-01 20:44:09 +02:00
|
|
|
|
|
|
|
|
# at top of file
|
|
|
|
|
import logging
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
# when needed
|
2014-07-22 11:48:15 -04:00
|
|
|
logger.warning("A warning with %s formatting", arg_to_be_formatted)
|
2014-04-01 20:44:09 +02:00
|
|
|
|
2014-07-22 11:48:15 -04:00
|
|
|
Do not format log messages yourself. Use ``%s`` formatting in messages and pass
|
|
|
|
|
arguments to logger. This is important, because Pelican logger will preprocess
|
|
|
|
|
some arguments (like Exceptions) for Py2/Py3 compatibility.
|
2014-04-01 20:44:09 +02:00
|
|
|
|
2014-07-22 11:48:15 -04:00
|
|
|
Limiting extraneous log messages
|
|
|
|
|
--------------------------------
|
2014-04-01 20:44:09 +02:00
|
|
|
|
2014-07-22 11:48:15 -04:00
|
|
|
If the log message can occur several times, you may want to limit the log to
|
|
|
|
|
prevent flooding. In order to do that, use the ``extra`` keyword argument for
|
|
|
|
|
the logging message in the following format::
|
|
|
|
|
|
|
|
|
|
logger.warning("A warning with %s formatting", arg_to_be_formatted,
|
|
|
|
|
extra={'limit_msg': 'A generic message for too many warnings'})
|
|
|
|
|
|
|
|
|
|
Optionally, you can also set ``'limit_args'`` as a tuple of arguments in
|
|
|
|
|
``extra`` dict if your generic message needs formatting.
|
|
|
|
|
|
|
|
|
|
Limit is set to ``5``, i.e, first four logs with the same ``'limit_msg'`` are
|
|
|
|
|
outputted normally but the fifth one will be logged using
|
|
|
|
|
``'limit_msg'`` (and ``'limit_args'`` if present). After the fifth,
|
|
|
|
|
corresponding log messages will be ignored.
|
|
|
|
|
|
|
|
|
|
For example, if you want to log missing resources, use the following code::
|
2014-04-01 20:44:09 +02:00
|
|
|
|
2014-04-14 16:18:07 -04:00
|
|
|
for resource in resources:
|
|
|
|
|
if resource.is_missing:
|
2014-07-22 11:48:15 -04:00
|
|
|
logger.warning(
|
|
|
|
|
'The resource %s is missing', resource.name,
|
|
|
|
|
extra={'limit_msg': 'Other resources were missing'})
|
2014-04-01 20:44:09 +02:00
|
|
|
|
2014-07-22 11:48:15 -04:00
|
|
|
The log messages will be displayed as follows::
|
2014-04-01 20:44:09 +02:00
|
|
|
|
|
|
|
|
WARNING: The resource prettiest_cat.jpg is missing
|
|
|
|
|
WARNING: The resource best_cat_ever.jpg is missing
|
|
|
|
|
WARNING: The resource cutest_cat.jpg is missing
|
|
|
|
|
WARNING: The resource lolcat.jpg is missing
|
|
|
|
|
WARNING: Other resources were missing
|
2014-07-22 11:48:15 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Outputting traceback in the logs
|
|
|
|
|
--------------------------------
|
|
|
|
|
|
|
|
|
|
If you're logging inside an ``except`` block, you may want to provide the
|
|
|
|
|
traceback information as well. You can do that by setting ``exc_info`` keyword
|
|
|
|
|
argument to ``True`` during logging. However, doing so by default can be
|
|
|
|
|
undesired because tracebacks are long and can be confusing to regular users.
|
|
|
|
|
Try to limit them to ``--debug`` mode like the following::
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
some_action()
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error('Exception occured: %s', e,
|
|
|
|
|
exc_info=settings.get('DEBUG', False))
|