CONTRIBUTING.md 11.5 KB
Newer Older
1
2
3
4
5
6
7
# Contribution guide

This document will help you understand how `damned-lies` works and how to contribute and push code to it.

This document is organized as follows:

- [Introduction](#introduction)
8
9
    - [Responsibilities](#responsibilities)
    - [Your first contribution](#your-first-contribution)
10
- [Installation](#installation)
11
12
    - [Software requirements](#software-requirements)
    - [Python environment](#python-environment)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    - [System setup](#system-setup)
    - [Running tests](#running-tests)
    - [Translations](#translations)
- [Guidelines](#guidelines)
    - [Django coding style](#django-coding-style)
    - [Custom rules](#custom-rules)
    - [PEP8 advices](#pep-8-advices)

# Introduction

`damned-lies` is a Python 3 Web application written using the [Django framework](https://www.djangoproject.com/). It is
the GNOME application used to manage the GNOME translation process. A running instance is available
at [l10n.gnome.org](https://l10n.gnome.org).

`damned-lies` is part of the GNOME software environment. As of it, please first read
the [GNOME newcomers guide](https://wiki.gnome.org/Newcomers/). You can also join
the [GNOME i18n room on Matrix](https://gnome.element.io/#/room/#i18n:gnome.org) and say hello. This document inherits
from all the guidelines used by the GNOME community.

**Note:** if you wish to contribute as a translator in any team, please go to
the [`damned-lies`](https://l10n.gnome.org) instance instead.

35
## Responsibilities
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

- Assume people mean well: when you’re discussing or debating with others, please assume they mean well. We’re here to
  cooperate.
- Ensure your code respects the [Python PEP8 standards](https://www.python.org/dev/peps/pep-0008/) (a pipeline checks
  this). You can use the `prospector` tool to do so. Please read the [Guidelines](#guidelines) section.
- Ensure your strings are written in a proper English.
- Ensure the strings you changed are also present in
  the [`gettext`](https://www.gnu.org/software/gettext/manual/gettext.html#Why) PO files. Please, refer to
  the [Django documentation on internationalisation](https://docs.djangoproject.com/en/stable/topics/i18n/). `gettext`
  is the utility used in almost every Free Software development project and used to localise strings showed to the end
  users.
- If you wish to make major changes or enhancements, **open an issue** to discuss it. Discuss things transparently and
  get community feedback.
- Be welcoming to newcomers and encourage diverse new contributors from all backgrounds. See
  the [Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/).

52
53

## Your First Contribution
54
55
56
57
58
59
60
61
62
63
64
65
66
67

As part of your first contribution, there are a few things and skills you have to acquire or to already have:

- You are comfortable with HTML, Javascript and CSS languages and technologies.
- You are able to understand and write [Python](https://www.python.org/) code.
- You know what is Bootstrap and how to
  use [Bootstrap 4](https://getbootstrap.com/docs/4.0/getting-started/introduction/).
- You know what is a [web framework](https://en.wikipedia.org/wiki/Web_framework) and you understand its behaviour.
- `damned-lies` is written in **Python** and utilizes the **Django** web framework. It uses a **Bootstrap** custom theme
  as its CSS framework.

**Note:** If you are not already familiar with Django, we recommend you to go through
the [Django Tutorial](https://docs.djangoproject.com/en/stable/intro/tutorial01/).

68
69
70
71
72
73
74
75
### Git *hooks*

Some hooks are provided in this repository. They can perform some upstream checks. For instance, they can prevent from committing unwanted code or performing others checks. *hooks* are located in the `.githooks` directory. To use them, it is necessary to update the `hooksPath` property by calling:

```bash
git config core.hooksPath ./.githooks
```

76
77
# Installation

78
## Software requirements
79
80
81
82
83
84
85
86
87
88
89

To run properly on any system, `damned-lies` requires some libraries and software to be installed on your system.

- `gettext`: the tool used to handle software translations.
- [`intltool`](https://freedesktop.org/wiki/Software/intltool/): *set of tools to centralize translation of many file
  formats using GNU gettext-compatible PO files*.
- [`itstool`](http://itstool.org/): library that *allows you to translate your XML documents with PO files*.
- `yelp-tools`: *a collection of scripts and build utilities to help create, manage, and publish documentation* for
  GNOME applications.
- **MariaDB client library**: the underlying library that is used through Python to connect to a MySQL/MariaDB instance.
- **ICU library**:  internationalization libraries of the Unicode Consortium.
90
- **Development tools**: used to compile some other dependencies, just as `pillow` if you install it using `pip`.
91
92
93
94
95

You can install them on your operating system using the following command line examples:

* On **Debian** based systems:
  ```bash
96
  apt install gettext intltool itstool libmariadbclient-dev libicu-dev libxml2-dev python3-dev yelp-tools build-essential
97
98
99
  ```
* On **Fedora** based systems:
  ```
100
  dnf install gettext intltool itstool mariadb-devel libicu-devel libxml2-devel python-devel yelp-tools @development-tools
101
102
  ```

103
## Python environment
104
105

Once libraries are installed on your OS, the recommended method to run `damned-lies` is to use
106
107
108
109
110
a [virtual environment](https://docs.python.org/en/3/library/venv.html). Python dependencies are listed in the
`requirements.txt` file. If you did not install all dependencies on your host system (like `pyicu`, `pillow`, etc.)
you should install them manually. There are still listed in the `requirements.txt` file.

There are development specific dependencies in `requirements-dev.txt` you might also want to install.
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

### Optional requirements

You can install the [`django-debug-toolbar`](https://pypi.org/project/django-debug-toolbar/) which will give extra
information about the current Django development.

Once installed using `pip`, define `USE_DEBUG_TOOLBAR` to `True` in `damnedlies/local_settings.py` to use it.

## System setup

Once Python dependencies are installed, you will need some further steps in order to have a working environment.

1. Create a `damnedlies/local_settings.py` and overwrite settings to match your requirements and your configuration
   layouts. Typical settings to customize include: `DATABASES`, `SECRET_KEY`, `DEBUG`, `STATIC_SERVE`, `ADMINS`
   , `ADMIN_GROUP`, `SITE_DOMAIN`, `SCRATCHDIR`, and various `EMAIL` settings.

   Please refer to Database configuration below for more information.

   `SCRATCHDIR` should point to an existing directory, writable by the web application user.

   Create the `MEDIA_ROOT` directory, and the `upload` and `upload-backup` directories inside it, also writable by the
   web application user.

   Note also that if you don’t want to really send mail when testing the app, you can set the `EMAIL_BACKEND` setting as
   follows to redirect mail to the console:
   ```python
   EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
   ```

2. Run the following command to execute the database migrations:
   ```bash
   ./manage.py migrate
   ```

3. In production, you will have to run the following command:
   ```bash
   ./manage.py collectstatic
   ```

   Then configure your Web server to statically serve this directory. For example, with the HTTPd server (*aka* Apache
   HTTP Server), a simple alias directive is enough:

   ```apacheconf
   Alias /static /absolute/path/to/djamnedlies/static
   ```

   **Note**: to deploy `damned-lies` in a production environment, please refer to
   the [Django documentation dedicated to deployment](https://docs.djangoproject.com/en/stable/howto/deployment/).

4. **Optionally**, if you want to populate the database with sample data, run:
    ```bash
    ./manage.py loaddata sample_data
   ```

5. Additionally, you may want
   to [create a superuser](https://docs.djangoproject.com/en/stable/topics/auth/default/#creating-superusers), in order
   to access the Django admin backend.
    ```bash
169
   ./manage.py createsuperuser
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
   ```

6. You should now be able to launch the development server to check if all is running well:
   ```bash
    ./manage.py runserver
   ```

7. Configure Sites in admin interface (“View on site” link, site address in sent mail).

## Running tests

To execute the tests, you need to compile translations first, as some tests require translation. To do so run this command:
```bash
python manage.py compile-trans
```

Then, you can run the test suite with:

```bash
python3 manage.py test --settings=damnedlies.settings_tests
```

A good practice is to ensure your tests do not degrade the current code coverage. We use
the [`coverage`](https://coverage.readthedocs.io/en/coverage-5.5/) module to run tests and compute testing coverage.

```bash
coverage run manage.py test --settings=damnedlies.settings_tests
```

Read [the Django testing documentation](https://docs.djangoproject.com/en/stable/topics/testing/) for more details about
testing in Django projects.

## Translations

To be able to extract strings from various database fields, a wrapper script has been created around the standard
Django `makemessages` command. The script also copies po files to the `/po` directory.

Run `python manage.py update-trans` to update translations when there are string changes.

After translation files in po directory have been updated, there is another script to put back po files
in `locale/<ll>/LC_MESSAGES/django.po` and call Django’s compile_messages command.

Run `python manage.py compile-trans`.

# Guidelines

Below are listed the guidelines every contribution should follow to ensure style consistency. In case of conflict,
Django coding style has precedence over custom rules, which themselves have precedence over the PEP8 standard.

**Note:** to check the correctness of your code, you can use [`prospector`](http://prospector.landscape.io/en/master/)
and run it in the project root’s directory. We provide a custom profile called `.prospector.yml`.

## Django Coding Style

`damned-lies` is written following
225
the Django [Coding Style](https://docs.djangoproject.com/en/stable/internals/contributing/writing-code/coding-style/).
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
Ensure to respect these rules when committing files.

## Custom rules

### Do not expand unused arguments when overriding a parent method

Let’s assume a class B inherits from a class A. In B, you want to override a method with numerous named parameters that
come from A. If you know you will not use all or any named parameters, you should remove named parameters from the B
method signature and let other parameters live in `**kwargs`.

An example is shown below. We assume we wish to implement a new `ModelBackend` by inheriting from it and re-implementing
its `authenticate()` method. The method takes a required argument (`request`) and two optional named
parameters (`username` and `password`).

```python
from django.contrib.auth.backends import BaseBackend


class ModelBackend(BaseBackend):

    def authenticate(self, request, username=None, password=None, **kwargs):
        pass
```

In case your custom implementation does not use any of the optional parameters, they should be removed from the method
signature. In Python, these arguments will live in the `**kwargs` variable anyway.

```python
from django.contrib.auth.backends import ModelBackend


class TokenBackend(ModelBackend):
    def authenticate(self, request, **kwargs):
        pass
```

## PEP-8 advices

The eighth PEP (Python Enhancement Proposal) rules Python coding style. It’s well known as the “PEP8
265
standards”. [PEP-8 is a standard for coding in Python](https://www.python.org/dev/peps/pep-0008/).