forked from github/pelican
Drop duplicates logs. Allow for logs to be grouped, enforcing a maximum number of logs per group. Add the LOG_FILTER setting to ask from the configuration file to ignore some logs (of level up to warning).
183 lines
6.4 KiB
ReStructuredText
183 lines
6.4 KiB
ReStructuredText
How to contribute
|
|
#################
|
|
|
|
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>`_.
|
|
|
|
Don't hesitate to fork Pelican and submit a pull request on GitHub. When doing
|
|
so, please adhere to the following guidelines.
|
|
|
|
.. include:: ../CONTRIBUTING.rst
|
|
|
|
Setting up the development environment
|
|
======================================
|
|
|
|
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::
|
|
|
|
$ pip install virtualenv
|
|
|
|
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.
|
|
|
|
To create and activate a virtual environment, use the following syntax::
|
|
|
|
$ virtualenv ~/virtualenvs/pelican
|
|
$ cd ~/virtualenvs/pelican
|
|
$ . bin/activate
|
|
|
|
To clone the Pelican source::
|
|
|
|
$ git clone https://github.com/getpelican/pelican.git src/pelican
|
|
|
|
To install the development dependencies::
|
|
|
|
$ cd src/pelican
|
|
$ pip install -r dev_requirements.txt
|
|
|
|
To install Pelican and its dependencies::
|
|
|
|
$ python setup.py develop
|
|
|
|
Or using ``pip``::
|
|
|
|
$ pip install -e .
|
|
|
|
Coding standards
|
|
================
|
|
|
|
Try to respect what is described in the `PEP8 specification
|
|
<http://www.python.org/dev/peps/pep-0008/>`_ when making contributions. This
|
|
can be eased via the `pep8 <http://pypi.python.org/pypi/pep8>`_ or `flake8
|
|
<http://pypi.python.org/pypi/flake8/>`_ tools, the latter of which in
|
|
particular will give you some useful hints about ways in which the
|
|
code/formatting can be improved.
|
|
|
|
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.
|
|
|
|
Running the test suite
|
|
======================
|
|
|
|
Each time you add a feature, there are two things to do regarding tests:
|
|
check that the existing tests pass, and add tests for the new feature
|
|
or bugfix.
|
|
|
|
The tests live in ``pelican/tests`` and you can run them using the
|
|
"discover" feature of ``unittest``::
|
|
|
|
$ python -m unittest discover
|
|
|
|
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::
|
|
|
|
$ LC_ALL=en_US.utf8 pelican -o pelican/tests/output/custom/ \
|
|
-s samples/pelican.conf.py samples/content/
|
|
$ LC_ALL=en_US.utf8 pelican -o pelican/tests/output/basic/ \
|
|
samples/content/
|
|
|
|
Testing on Python 2 and 3
|
|
-------------------------
|
|
|
|
Testing on Python 3 currently requires some extra steps: installing
|
|
Python 3-compatible versions of dependent packages and plugins.
|
|
|
|
Tox_ is a useful tool to run tests on both versions. It will install the
|
|
Python 3-compatible version of dependent packages.
|
|
|
|
.. _Tox: http://testrun.org/tox/latest/
|
|
|
|
Python 3 development tips
|
|
=========================
|
|
|
|
Here are some tips that may be useful when doing some code for both Python 2.7
|
|
and Python 3 at the same time:
|
|
|
|
- Assume every string and literal is unicode (import unicode_literals):
|
|
|
|
- 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.
|
|
|
|
|
|
Logging tips
|
|
============
|
|
|
|
Try to use logging with appropriate levels.
|
|
|
|
For logging messages that are not repeated, use the usual Python way:
|
|
|
|
# at top of file
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# when needed
|
|
logger.warning('A warning that could occur only once")
|
|
|
|
However, if you want to log messages that may occur several times, instead of
|
|
a string, gives a tuple to the logging method, with two arguments:
|
|
|
|
1. The message to log for this very execution
|
|
2. A generic message that will appear if the previous one would occur to many
|
|
times.
|
|
|
|
For example, if you want to log missing resources, use the following code:
|
|
|
|
for ressource in ressources:
|
|
if ressource.is_missing:
|
|
logger.warning((
|
|
'The resource {r} is missing'.format(r=ressource.name),
|
|
'Other resources were missing'))
|
|
|
|
The logs will be displayed as follows:
|
|
|
|
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
|