mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-12 23:37:14 +03:00
707 lines
27 KiB
Markdown
707 lines
27 KiB
Markdown
<!--
|
|
vim: textwidth=79 wrapmargin=79
|
|
-->
|
|
# Guidelines for contributing to EDMC
|
|
|
|
## Work on Issues
|
|
|
|
If you are not part of the core development team then you should only be performing work that addresses an open issue.
|
|
|
|
So, if what you think needs doing isn't currently referred to in an
|
|
[open issue](https://github.com/EDCD/EDMarketConnector/issues),
|
|
then you should first [open an issue](https://github.com/EDCD/EDMarketConnector/issues/new/choose).
|
|
**Please use the correct template if applicable**.
|
|
|
|
## Check with us first
|
|
|
|
Whilst we welcome all efforts to improve the program it's best to ensure that you're not duplicating, or worse,
|
|
wasting effort.
|
|
|
|
There is sometimes a misconception that Open Source means that the primary project is obliged to accept Pull Requests.
|
|
That is not so. While you are 100% free to make changes in your own fork, we will only accept changes that are
|
|
consistent with our vision for EDMC. Fundamental changes in particular need to be agreed in advance.
|
|
|
|
---
|
|
|
|
## Text formatting
|
|
|
|
The project contains an `.editorconfig` file at its root. Please either ensure
|
|
your editor is taking note of those settings, or cross-check its contents
|
|
with the
|
|
[editorconfig documentation](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties)
|
|
, and ensure your editor/IDE's settings match.
|
|
|
|
---
|
|
|
|
## General workflow
|
|
|
|
1. You will need a GitHub account.
|
|
1. Fork the repository on GitHub into your account there (hereafter referred to as 'your fork').
|
|
1. In your local copy of *your* fork create an appropriate WIP branch.
|
|
1. Develop the changes, testing as you go (no we don't have any actual tests yet).
|
|
1. Be as sure as you can that the code works as you intend and hasn't introduced any other bugs or regressions.
|
|
1. Test the codebase as a whole against any unit tests that do exist, and add your own as you can.
|
|
1. Check your code against flake8 periodically.
|
|
1. When you're sure the work is final:
|
|
1. Push your WIP branch to your fork (you probably should have been doing this as you worked as a form of backup).
|
|
1. Access the WIP branch on your fork on GitHub and create a Pull Request. Mention any Issue number(s) that it
|
|
addresses.
|
|
1. Await feedback in the form of comments on the Pull Request.
|
|
|
|
**IMPORTANT**: Once you have created the Pull Request *any changes you make to that WIP branch and push to your fork
|
|
will be reflected in the Pull Request*. Ensure that *only* the changes for the issue(s) you are addressing are in
|
|
the WIP branch. Any other work should occur in its own separate WIP branch. If needs be make one branch to work in
|
|
and another for the Pull Request, merging or cherry-picking commits as needed.
|
|
|
|
---
|
|
|
|
## Git commit conventions
|
|
|
|
* Please use the standard Git convention of a short title in the first line and fuller body text in subsequent lines.
|
|
* Please reference issue numbers using the "hashtag" format #123 in your commit message wherever possible.
|
|
This lets GitHub create two-way hyperlinks between the issue report and the commit.
|
|
[Certain text](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)
|
|
in a PR that fixes an issue can auto-close the issue when the PR is merged.
|
|
Note the caveats about the extended forms being necessary in some situations.
|
|
* If in doubt, lean towards many small commits. This makes git bisect much more useful.
|
|
* Please try at all costs to avoid a "mixed-up" commit, i.e. one that addresses more than one issue at once.
|
|
One thing at a time is best.
|
|
|
|
---
|
|
|
|
## Git branch structure and tag conventions
|
|
|
|
Somewhat based on git-flow, but our particular take on it:
|
|
|
|
### Branches
|
|
|
|
#### `stable`
|
|
|
|
This will either have `HEAD` pointing to the latest stable release code *or* might have extra code merged in for a
|
|
hotfix that will shortly be in the next stable release. If you want the latest stable release code then use the
|
|
appropriate `Release/A.B.C` tag!
|
|
|
|
#### `beta`
|
|
|
|
If we run any pre-release betas *with actual builds released, not
|
|
just a branch to be run from source*, then this branch will contain that
|
|
code. As per `stable` above, this branch might be ahead of the latest
|
|
pre-release due to merging of hotfixes. Use the appropriate tag if you want
|
|
to be sure of the code you checkout.
|
|
*If there hasn't yet been a new beta version this could be far behind all
|
|
of: `main`, `develop`, `stable`.*
|
|
|
|
#### `develop`
|
|
|
|
This is the branch where all current development is integrated. No commits should be made directly
|
|
to this as the work should be done in a separate branch used in a Pull Request before being merged as part of
|
|
resolving that Pull Request.
|
|
|
|
#### `main`
|
|
|
|
Yes, we've renamed this from `master`. See
|
|
"[Using 'main' as the primary branch in Git](https://github.com/EDCD/EDMarketConnector/wiki/Git-Using-Main-Branch)"
|
|
for instructions on ensuring you're cleanly using it in any local clone.
|
|
|
|
This branch should contain anything from `develop` that is considered well
|
|
tested and ready for the next `stable` merge.
|
|
|
|
#### `master`
|
|
|
|
**This is no longer used. If the branch is even present then it's no longer updated. You should be using `main` instead.**
|
|
|
|
#### `releases`
|
|
|
|
Currently the version of the `edmarketconnector.xml` 'appcast' file in this branch is what live
|
|
clients check to be notified of new versions. This can potentially be replaced with the `stable` branch's version,
|
|
but some care will be necessary to ensure no users are left behind (their client checking the `releases` branch which
|
|
then no longer exists). For the time being this should always be kept in sync with `stable` as each new release is
|
|
made.
|
|
|
|
### Work in progress conventions
|
|
|
|
Remember, you should always be working versus a single issue, even if the work is part of a Milestone or Project.
|
|
There might be cases where issues aren't duplicates, but your work still addresses more than one. In that case
|
|
pick one for the naming scheme below, but mention all in commit messages and the Pull Request.
|
|
|
|
In all cases the branch should be named as per the scheme `<class>/<issue number>/<title>`:
|
|
|
|
* `<class>` - We have several classes of WIP branch:
|
|
* `fix` - For working on bug fixes, e.g. `fix/184/crash-in-startup`
|
|
* `enhancement` - For enhancing an *existing* feature, e.g. `enhancement/192/add-thing-to-wotsit`
|
|
* `feature` - For working on *new* features, e.g. `feature/284/allow-users-to-frob`
|
|
|
|
* `<issue-number>` is for easy reference when citing the issue number in commit messages. If you're somehow doing
|
|
work that's not versus an issue then don't put the `<issue number>-` part in.
|
|
* `<title>` is intended to allow anyone to quickly know what the branch is addressing. Try to choose something
|
|
succinct for `<title>`, it's just there for easy reference, it doesn't need to be the entire title of
|
|
the appropriate issue.
|
|
|
|
The branch you base your work on will depend on which class of WIP it is. If you're fixing a bug in the latest
|
|
`stable` then it's best to base your branch on its HEAD. If it's a fix for a beta release then base off of `beta`'s
|
|
HEAD. If you're working on a new feature then you'd want to base the work on `develop`'s HEAD.
|
|
|
|
**Important**: Please *under no circumstance* merge *from* the source branch after you have started work in
|
|
your WIP branch. If there are any non-trivial conflicts when we merge your Pull Request then we might ask you
|
|
to *rebase* your WIP branch on the latest version of the source branch. Otherwise, we'll work out how to best
|
|
merge your changes via comments in the Pull Request.
|
|
|
|
### Tags
|
|
|
|
#### Stable Releases
|
|
|
|
All stable releases **MUST** have a tag of the form `Release/Major.Minor.Patch`
|
|
on the commit that was `HEAD` when the installer for it was built.
|
|
|
|
#### Pre-Releases
|
|
|
|
Tags for pre-releases should be of one of two forms, following [Version
|
|
Strings](docs/Releasing.md#version-strings) conventions.
|
|
|
|
* Initial beta releases should have versions of the form:
|
|
|
|
`Major.Minor.Patch-beta<serial>`
|
|
|
|
with the `<serial>` starting with `1` and incrementing with each new beta
|
|
pre-release.
|
|
|
|
* Release candidates should have versions of the form:
|
|
|
|
`Major.Minor.Patch-rc<serial>`
|
|
|
|
with the `<serial>` starting with `1` and incrementing with each new
|
|
release candidate.
|
|
|
|
The tag should thus be `Release/Major.Minor.Patch-(beta|rc)<serial>`.
|
|
|
|
The Semantic Versioning `+<build metadata>` should never be a part of the tag.
|
|
|
|
---
|
|
|
|
## Version conventions
|
|
|
|
Please see [Version Strings](docs/Releasing.md#version-strings)
|
|
for a description of the currently used version strings.
|
|
|
|
Historically a `A.BC` form was used, based on an internal `A.B.C.D` version
|
|
string. This was changed to simply `A.B.C.D` throughout for `4.0.0.0`,
|
|
`4.0.1.0` and `4.0.2.0`. It would also continue for any other increment of
|
|
only the 'C' (Patch) component.
|
|
|
|
Going forwards we will always use the full [Semantic Version](https://semver.org/#semantic-versioning-specification-semver)
|
|
and 'folder style' tag names, e.g. `Release/Major.Minor.Patch`.
|
|
|
|
Currently, the only file that defines the version code-wise is
|
|
`config/__init__.py`. `Changelog.md` and `edmarketconnector.xml` are another
|
|
matter handled as part of
|
|
[the release process](docs/Releasing.md#distribution).
|
|
|
|
---
|
|
## Python Environment
|
|
Whilst you can use whatever IDE/development environment best suits you, much
|
|
of the setup in this project has only been tested against PyCharm or VSCode,
|
|
along with 'git bash' command-line.
|
|
|
|
### Use the version denoted by `.python-version`
|
|
We only test, and build with, the python version as defined in the file
|
|
`.python-version`. Trying to use any other version might mean things just
|
|
don't run at all, or don't work as expected.
|
|
|
|
### Use a Python virtual environment
|
|
Always use a Python virtual environment specific to working on this project.
|
|
|
|
An example, when using Python 3.11.x would be:
|
|
```bash
|
|
python -m venv ../edmc-venv-3.11
|
|
```
|
|
Note how the 'venv' is placed in a sub-directory *of the parent directory* of
|
|
the project. This avoids any issues with scripts working recursively picking
|
|
up your 'venv' files.
|
|
|
|
If you have good reason to put the 'venv' inside the project directory then
|
|
you **MUST** use either `venv` or `.venv`, else you'll run into all sorts of
|
|
problems with pre-commit checks.
|
|
|
|
### Install the development requirements
|
|
Whilst simply running the project only requires
|
|
`pip install -r requirements.txt`-provided modules, development work will
|
|
instead require:
|
|
```bash
|
|
pip install -r requirements-dev.txt
|
|
```
|
|
NB: This itself will also take note of `requirements.txt`.
|
|
|
|
This will ensure you have all the necessary tools to hand for the pre-commit
|
|
checks.
|
|
|
|
### Set up `pre-commit`
|
|
In order to have any submitted PR be in the least-worse shape when first opened
|
|
you **MUST** run the checks as specified in `.pre-commit-config.yaml`.
|
|
```bash
|
|
pre-commit install --install-hooks
|
|
```
|
|
Now whenever you `git commit` the various checks will be run to ensure your
|
|
code is compliant with our requirements. If you have a *temporary* need to
|
|
bypass this (e.g. wanting to commit one change and fix a non-compliant file
|
|
later) you can add `-n` to the `git commit` arguments.
|
|
|
|
**NB: There is [a problem](https://github.com/microsoft/vscode-python/issues/10165)
|
|
with pre-commit if using VSCode.** There's a workaround in
|
|
[one of the comments](https://github.com/microsoft/vscode-python/issues/10165#issuecomment-1277237676).
|
|
|
|
### Consider running `pytest` before any `git push`
|
|
The GitHub workflows for PRs and pushes will run `pytest` and flag an error
|
|
if the tests don't pass, so it's in your interests to ensure you've not broken
|
|
any tests.
|
|
|
|
You could endeavour to remember to run `pytest` manually, or you could add
|
|
this git hook:
|
|
|
|
`.git/hooks/pre-push`
|
|
```bash
|
|
#!/bin/sh
|
|
|
|
# If this script exits with a non-zero status nothing will be pushed.
|
|
#
|
|
# This hook is called with the following parameters:
|
|
#
|
|
# $1 -- Name of the remote to which the push is being done
|
|
# $2 -- URL to which the push is being done
|
|
#
|
|
# If pushing without using a named remote those arguments will be equal.
|
|
#
|
|
# Information about the commits which are being pushed is supplied as lines to
|
|
# the standard input in the form:
|
|
#
|
|
# <local ref> <local sha1> <remote ref> <remote sha1>
|
|
|
|
remote="$1"
|
|
url="$2"
|
|
|
|
echo "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
|
|
echo " Running pytest..."
|
|
pytest || exit 1
|
|
echo " All tests passed, proceeding..."
|
|
echo "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
|
|
|
|
exit 0
|
|
```
|
|
It's probably overkill, and will become painful if enough tests are added, to
|
|
run `pytest` in a `pre-commit` hook.
|
|
|
|
---
|
|
|
|
## Linting
|
|
|
|
We use flake8 for linting all python source.
|
|
|
|
While working on your changes, please ensure that they pass a check from `flake8` using our configuration and plugins.
|
|
If you installed `requirements-dev.txt` with pip, you should simply be able to run `flake8 your_files_here` to lint
|
|
your files.
|
|
|
|
Note that if your PR does not cleanly (or mostly cleanly) pass a linting scan, your PR may be put on hold pending fixes.
|
|
|
|
## Unit testing
|
|
|
|
Where possible please write unit tests for your PRs, especially in the case of
|
|
bug fixes, having regression tests help ensure that we don't accidentally
|
|
re-introduce a bug down the line.
|
|
|
|
We use the [`pytest`](https://docs.pytest.org/en/stable/) for unit testing.
|
|
|
|
The files for a test should go in a sub-directory of `tests/` named after the
|
|
(principal) file or directory that contains the code they are testing.
|
|
For example:
|
|
|
|
- Tests for `journal_lock.py` are in
|
|
`tests/journal_lock.py/test_journal_lock.py`. The `test_` prefix on
|
|
`test_journal_lock.py` is necessary in order for `pytest` to recognise the
|
|
file as containing tests to be run.
|
|
- Tests for `config/` code are located in `tests/config/test_config.py`, not
|
|
`tests/config.py/test_config.py`
|
|
|
|
The sub-directory avoids having a mess of files in `tests`, particularly when
|
|
there might be supporting files, e.g. `tests/config/_old_config.py` or files
|
|
containing test data.
|
|
|
|
Invoking just a bare `pytest` command will run all tests.
|
|
|
|
To run only a sub-set of tests you can use, e.g. `pytest -k journal_lock`. You
|
|
might want to use `pytest -rA -k journal_lock` if you have any debug `print()`
|
|
statements within the test code itself, so you can see the output even when the
|
|
tests all succeed.
|
|
|
|
Adding `--trace` to a `pytest` invocation causes it to drop into a
|
|
[`pdb`](https://docs.python.org/3/library/pdb.html) prompt for each test,
|
|
handy if you want to step through the testing code to be sure of anything.
|
|
|
|
Otherwise, see the [pytest documentation](https://docs.pytest.org/en/stable/contents.html).
|
|
|
|
### Test Coverage
|
|
As we work towards actually having tests for as much of the code as possible
|
|
it is useful to monitor the current test coverage.
|
|
|
|
Running `pytest` will also produce the overall coverage report, see the
|
|
configured options in `pyproject.toml`.
|
|
|
|
One issue you might run into is where there is code that only runs on one
|
|
platform. By default `pytest-cov`/`coverage` will count this code as not
|
|
tested when run on a different platform. We utilise the
|
|
`coverage-conditional-plugin` module so that `#pragma` comments can be used
|
|
to give hints to coverage about this.
|
|
|
|
The pragmas are defined in the
|
|
`tool.coverage.coverage_conditional_plugin.rules` section of `pyproject.toml`,
|
|
e.g.
|
|
|
|
```toml
|
|
[tool.coverage.coverage_conditional_plugin.rules]
|
|
sys-platform-win32 = "sys_platform != 'win32'"
|
|
...
|
|
```
|
|
And are used as in:
|
|
```python
|
|
import sys
|
|
|
|
if sys.platform == 'win32': # pragma: sys-platform-win32
|
|
...
|
|
else: # pragma: sys-platform-not-win32
|
|
...
|
|
```
|
|
Note the inverted sense of the pragma definitions, as the comments cause
|
|
`coverage` to *not* consider that code block on this platform.
|
|
|
|
As of 2022-10-02 and `coverage-conditional-plugin==0.7.0` there is no way to
|
|
signal that an entire file should be excluded from coverage reporting on the
|
|
current platform. See
|
|
[this GitHub issue comment](https://github.com/wemake-services/coverage-conditional-plugin/issues/2#issuecomment-1263918296)
|
|
.
|
|
|
|
---
|
|
|
|
## Imports used only in core plugins
|
|
|
|
Because the 'core' plugins, as with any EDMarketConnector plugin, are only ever
|
|
loaded dynamically, not through an explicit `import` statement, there is no
|
|
way for `py2exe` to know about them when building the contents of the
|
|
`dist.win32` directory. See [docs/Releasing.md](docs/Releasing.md) for more
|
|
information about this build process.
|
|
|
|
Thus, you **MUST** check if any imports you add in `plugins/*.py` files are only
|
|
referenced in that file (or also only in any other core plugin), and if so
|
|
**YOU MUST ENSURE THAT PERTINENT ADJUSTMENTS ARE MADE IN `build.py`
|
|
IN ORDER TO ENSURE THE FILES ARE ACTUALLY PRESENT IN AN END-USER
|
|
INSTALLATION ON WINDOWS.**
|
|
|
|
An exmaple is that as of 2022-02-01 it was noticed that `plugins/eddn.py` now
|
|
uses `util/text.py`, and is the only code to do so. `py2exe` does not detect
|
|
this and thus the resulting `dist.win32/library.zip` does not contain the
|
|
`util/` directory, let alone the `util/text.py` file. The fix was to update
|
|
the appropriate `packages` definition to:
|
|
|
|
```python
|
|
'packages': [
|
|
'sqlite3', # Included for plugins
|
|
'util', # 2022-02-01 only imported in plugins/eddn.py
|
|
],
|
|
```
|
|
|
|
Note that in this case it's in `packages` because we want the whole directory
|
|
adding. For a single file an extra item in `includes` would suffice.
|
|
|
|
Such additions to `build.py` should not cause any issues if
|
|
subsequent project changes cause `py2exe` to automatically pick up the same
|
|
file(s).
|
|
|
|
---
|
|
|
|
## Debugging network sends
|
|
|
|
Rather than risk sending bad data to a remote service, even if only through
|
|
repeatedly sending the same data you can cause such code to instead send
|
|
through a local web server and thence to a log file.
|
|
|
|
1. This utilises the `--debug-sender ...` command-line argument. The argument
|
|
to this is free-form, so there's nothing to edit in EDMarketConnector.py
|
|
in order to support a new target for this.
|
|
2. The debug web server is set up globally in EDMarketConnector.py.
|
|
3. In code where you want to utilise this you will need at least something
|
|
like this (taken from some plugins/edsm.py code):
|
|
|
|
```python
|
|
from config import debug_senders
|
|
from edmc_data import DEBUG_WEBSERVER_HOST, DEBUG_WEBSERVER_PORT
|
|
|
|
TARGET_URL = 'https://www.edsm.net/api-journal-v1'
|
|
if 'edsm' in debug_senders:
|
|
TARGET_URL = f'http://{DEBUG_WEBSERVER_HOST}:{DEBUG_WEBSERVER_PORT}/edsm'
|
|
|
|
...
|
|
r = this.requests_session.post(TARGET_URL, data=data, timeout=_TIMEOUT)
|
|
```
|
|
|
|
Be sure to set a URL path in the `TARGET_URL` that denotes where the data
|
|
would normally be sent to.
|
|
4. The output will go into a file in `%TEMP%\EDMarketConnector\http_debug`
|
|
whose name is based on the path component of the URL. In the code example
|
|
above it will come out as `edsm.log` due to how `TARGET_URL` is set.
|
|
|
|
---
|
|
|
|
## Coding Conventions
|
|
|
|
In general, please follow [PEP8](https://www.python.org/dev/peps/pep-0008/)
|
|
|
|
Adhere to the spelling conventions of the libraries and modules used in the
|
|
project.
|
|
|
|
Yes, this means using 'color' rather than 'colour', and in general will mean
|
|
US, not British, spellings.
|
|
|
|
---
|
|
|
|
## Control flow
|
|
|
|
Never oneline any control flow (`if`, `else`, `for`), as it makes spotting what happens next difficult.
|
|
|
|
Yes:
|
|
|
|
```python
|
|
if something_true:
|
|
one_thing_we_do()
|
|
```
|
|
|
|
No:
|
|
|
|
```python
|
|
if something_true: one_thing_we_do()
|
|
```
|
|
|
|
Yes, some existing code still flouts this rule.
|
|
|
|
### Scope changes
|
|
|
|
**Always** use Line breaks after scope changes. It makes seeing where scope has changed far easier on a quick skim
|
|
|
|
Yes:
|
|
|
|
```python
|
|
if True:
|
|
do_something()
|
|
|
|
else:
|
|
raise UniverseBrokenException()
|
|
|
|
return
|
|
```
|
|
|
|
No:
|
|
|
|
```python
|
|
if True:
|
|
do_something()
|
|
else:
|
|
raise UniverseBrokenException()
|
|
return
|
|
```
|
|
|
|
---
|
|
|
|
## Use Type hints
|
|
|
|
Please do place [type hints](https://docs.python.org/3/library/typing.html) on the declarations of your functions,
|
|
both their arguments and return types.
|
|
|
|
---
|
|
|
|
## Use `logging` not `print()`, and definitely not `sys.stdout.write()`
|
|
|
|
`EDMarketConnector.py` sets up a `logging.Logger` for this under the
|
|
`appname`, so:
|
|
|
|
```python
|
|
import logging
|
|
from config import appname
|
|
logger = logging.getLogger(appname)
|
|
|
|
logger.info(f'Some message with a {variable}')
|
|
|
|
try:
|
|
something
|
|
except Exception as e: # Try to be more specific
|
|
logger.error(f'Error in ... with ...', exc_info=e)
|
|
```
|
|
|
|
**DO NOT** use the following, as you might cause a circular import:
|
|
|
|
```python
|
|
from EDMarketConnector import logger
|
|
```
|
|
|
|
Setting up [logging in plugins](./PLUGINS.md#logging) is slightly different.
|
|
|
|
We have implemented a `logging.Filter` that adds support for the following
|
|
in `logging.Formatter()` strings:
|
|
|
|
1. `%(qualname)s` which gets the full `<module>.ClassA(.ClassB...).func`
|
|
of the calling function.
|
|
1. `%(class)s` which gets just the enclosing class name(s) of the calling
|
|
function.
|
|
|
|
If you want to see how we did this, check `EDMCLogging.py`.
|
|
|
|
So don't worry about adding anything about the class or function you're
|
|
logging from, it's taken care of.
|
|
|
|
*Do use a pertinent message, even when using `exc_info=...` to log an
|
|
exception*. e.g. Logging will know you were in your `get_foo()` function
|
|
but you should still tell it what actually (failed to have) happened
|
|
in there.
|
|
|
|
### Use the appropriate logging level
|
|
You must ensure necessary information is always in the log files, but
|
|
not so much that it becomes more difficult to discern important information
|
|
when diagnosing an issue.
|
|
|
|
`logging`, and thus our `logger` instances provide functions of the
|
|
following names:
|
|
|
|
- `info` - For general messages that don't occur too often outside of startup
|
|
and shutdown.
|
|
- `warning` - An error has been detected, but it doesn't impact continuing
|
|
functionality. In particular **use this when logging errors from
|
|
external services**. This would include where we detected a known issue
|
|
with Frontier-supplied data. A currently unknown issue *may* end up
|
|
triggering logging at `error` level or above.
|
|
- `error` - An error **in our code** has occurred. The application might be
|
|
able to continue, but we want to make it obvious there's a bug that we
|
|
need to fix.
|
|
- `critical` - An error has occurred **in our code** that impacts the
|
|
continuation of the current process.
|
|
- `debug` - Information about code flow and data that is occurs too often
|
|
to be at `info` level. Keep in mind our *default* logging level is DEBUG,
|
|
but users can change it for the
|
|
[plain log file](https://github.com/EDCD/EDMarketConnector/wiki/Troubleshooting#plain-log-file),
|
|
but the
|
|
[debug log giles](https://github.com/EDCD/EDMarketConnector/wiki/Troubleshooting#debug-log-files)
|
|
are always at least at DEBUG level.
|
|
|
|
In addition to that we utilise one of the user-defined levels as:
|
|
|
|
- `trace` - This is a custom log level intended for debug messages which
|
|
occur even more often and would cause too much log output for even
|
|
'normal' debug use.
|
|
In general only developers will set this log level, but we do supply a
|
|
command-line argument and `.bat` file for users to enable it. It cannot be
|
|
selected from Settings in the UI.
|
|
|
|
**Do not use a bare `logger.trace(...)` call** unless you're 100% certain
|
|
it's only temporary **and will be removed before any code merge**. In
|
|
that case you would utilise `EDMarketConnector.py --trace` to see the output.
|
|
|
|
Instead, you should gate any TRACE logging using the `trace_if()` helper
|
|
method provided on `logger`:
|
|
|
|
```python
|
|
logger.trace_if('journal.event.scan', 'my-log-message')
|
|
```
|
|
|
|
The string used to identify this tracing should be related to the
|
|
**function of the code**, not the particular file, or class, that it is in.
|
|
This is so that the same string can be used to trace code that spans more
|
|
than one file, class, or other scope.
|
|
|
|
This would then be triggered by running EDMarketConnector with the
|
|
appropriate command-line arguments:
|
|
|
|
EDMarketConnector.py --trace-on journal.event.scan
|
|
|
|
Note that you do **not** also need to specify `--trace`, that's implied.
|
|
|
|
This way you can set up TRACE logging that won't spam just because `--trace`
|
|
is used.
|
|
|
|
---
|
|
|
|
## Use fstrings, not modulo-formatting or .format
|
|
|
|
[fstrings](https://www.python.org/dev/peps/pep-0498/) are new in python 3.6,
|
|
and allow for string interpolation rather than more opaque formatting calls.
|
|
|
|
As part of our flake8 linting setup we have included a linter that warns when
|
|
you use `%` on string literals.
|
|
|
|
`.format()` won't throw flake8 errors, **but only because it's still the
|
|
best way to handle [untranslated words](./docs/Translations.md#call-_)
|
|
in otherwise translated phrases**. Thus, we allow this, and only this, use of
|
|
`.format()` for strings.
|
|
|
|
---
|
|
|
|
## Docstrings
|
|
|
|
Doc strings are preferred on all new modules, functions, classes, and methods, as they help others understand your code.
|
|
We use the `sphinx` formatting style, which for pycharm users is the default.
|
|
|
|
Lack of docstrings, or them not passing some checks, *will* cause a flake8
|
|
failure in our setup.
|
|
|
|
---
|
|
|
|
## Comments
|
|
|
|
### LANG comments for translations
|
|
|
|
When adding translations you *must*
|
|
[add a LANG comment](./docs/Translations.md#add-a-lang-comment).
|
|
|
|
### Mark hacks and workarounds with a specific comment
|
|
|
|
We often write hacks or workarounds to make EDMC work on a given version or around a specific bug.
|
|
Please mark all hacks, workarounds, magic with one of the following comments, where applicable:
|
|
|
|
```py
|
|
# HACK $elite-version-number | $date: $description
|
|
# MAGIC $elite-version-number | $date: $description
|
|
# WORKAROUND $elite-version-number | $date: $description
|
|
```
|
|
|
|
The description should cover exactly why the hack is needed, what it does, what is required / expected for it to be removed.
|
|
Please be verbose here, more info about weird choices is always prefered over magic that we struggle to understand in six months.
|
|
|
|
Additionally, if your hack is over around 5 lines, please include a `# HACK END` or similar comment to indicate the end of the hack.
|
|
|
|
# Use `sys.platform` for platform guards
|
|
|
|
`mypy` (and `pylance`) understand platform guards and will show unreachable code / resolve imports correctly
|
|
for platform specific things. However, this only works if you directly reference `sys.platform`, importantly
|
|
the following does not work:
|
|
|
|
```py
|
|
from sys import platform
|
|
if platform == 'win32':
|
|
...
|
|
```
|
|
|
|
It **MUST** be `if sys.platform`.
|
|
|
|
---
|
|
|
|
## Build process
|
|
|
|
See [Releasing.md](docs/Releasing.md) for the environment and procedure necessary for building the application into
|
|
a .exe and Windows installer file.
|
|
|
|
---
|
|
|
|
## Translations
|
|
|
|
See [Translations.md](docs/Translations.md) for how to ensure any new phrases your code adds can be easily
|
|
translated.
|
|
|
|
---
|
|
|
|
## Acknowledgement
|
|
|
|
The overall structure, and some of the contents, of this document were taken from the [EDDI Contributing.md](https://github.com/EDCD/EDDI/blob/develop/docs/Contributing.md).
|