How To Contribute¶
Setting things up¶
Fork the
AkaNamen-Bot
repository to your GitHub account.Clone your forked repository of
AkaNamen-Bot
to your computer:$ git clone https://github.com/<your username>/AkaNamen-Bot --recursive $ cd AkaNamen-Bot
Add a track to the original repository:
$ git remote add upstream https://github.com/AkaBlas/AkaNamen-Bot
Install dependencies:
$ pip install -r requirements.txt -r requirements-dev.txt
Install pre-commit hooks:
$ pre-commit install
Finding something to do¶
If you already know what you’d like to work on, you can skip this section.
If you have an idea for something to do, first check if it’s already been filed on the issue tracker. If so, add a comment to the issue saying you’d like to work on it, and we’ll help you get started! Otherwise, please file a new issue and assign yourself to it.
Instructions for making a code change¶
The central development branch is master
, which should be clean and ready for release at any time. In general, all changes should be done as feature branches based off of master
.
Here’s how to make a one-off code change.
Choose a descriptive branch name. It should be lowercase, hyphen-separated, and a noun describing the change (so,
fuzzy-rules
, but notimplement-fuzzy-rules
). Also, it shouldn’t start withhotfix
orrelease
.Create a new branch with this name, starting from
master
. In other words, run:$ git fetch upstream $ git checkout master $ git merge upstream/master $ git checkout -b your-branch-name
Make a commit to your feature branch. Each commit should be self-contained and have a descriptive commit message that helps other developers understand why the changes were made.
You can refer to relevant issues in the commit message by writing, e.g., “#105”.
Your code should adhere to the PEP 8 Style Guide, with the exception that we have a maximum line length of 99.
Provide static typing with signature annotations. The documentation of MyPy will be a good start, the cheat sheet is here.
Document your code. This project uses sphinx to generate static HTML docs. To build them, first make sure you have the required dependencies:
$ pip install -r docs/requirements-docs.txt
then run the following from the AkaNamen-Bot root directory:
$ make -C docs html
or, if you don’t have
make
available (e.g. on Windows):$ sphinx-build docs/source docs/build/html
Once the process terminates, you can view the built documentation by opening
docs/build/html/index.html
with a browser.For consistency, please conform to Google Python Style Guide and Google Python Style Docstrings. In addition, code should be formatted consistently with other code around it.
The following exceptions to the above (Google’s) style guides applies:
Documenting types of global variables and complex types of class members can be done using the Sphinx docstring convention.
Please ensure that the code you write is well-tested.
Don’t break backward compatibility.
Before making a commit ensure that all automated tests still pass:
$ make test
If you don’t have
make
, do:$ pytest -v
To actually make the commit (this will trigger tests for yapf, lint, pep8 and mypy automatically):
$ git add your-file-changed.py
Finally, push it to your GitHub fork, run:
$ git push origin your-branch-name
When your feature is ready to merge, create a pull request.
Go to your fork on GitHub, select your branch from the dropdown menu, and click “New merge request”.
Add a descriptive comment explaining the purpose of the branch. This will tell the reviewer what the purpose of the branch is.
Click “Create merge request”
Address review comments until all reviewers give LGTM (‘looks good to me’).
When your reviewer has reviewed the code, you’ll get an email. You’ll need to respond in two ways:
Make a new commit addressing the comments you agree with, and push it to the same branch. Ideally, the commit message would explain what the commit does (e.g. “Fix lint error”), but if there are lots of disparate review comments, it’s fine to refer to the original commit message and add something like “(address review comments)”.
In addition, please reply to each comment. Each reply should be either “Done” or a response explaining why the corresponding suggestion wasn’t implemented. All comments must be resolved before LGTM can be given.
Resolve any merge conflicts that arise. To resolve conflicts between ‘your-branch-name’ (in your fork) and ‘master’ (in the
AkaNamen-Bot
repository), run:$ git checkout your-branch-name $ git fetch upstream $ git merge upstream/master $ ...[fix the conflicts]... $ ...[make sure the tests pass before committing]... $ git commit -a $ git push origin your-branch-name
At the end, the reviewer will merge the pull request.
Tidy up! Delete the feature branch from both your local clone and the GitHub repository:
$ git branch -D your-branch-name $ git push origin --delete your-branch-name
Celebrate. Congratulations, you have contributed to
AkaNamen-Bot
!
Style commandments¶
Specific commandments¶
Avoid using “double quotes” where you can reasonably use ‘single quotes’.
Assert comparison order¶
assert statements should compare in actual == expected order.
For example (assuming test_call
is the thing being tested):
# GOOD
assert test_call() == 5
# BAD
assert 5 == test_call()
Properly calling callables¶
Methods, functions and classes can specify optional parameters (with default values) using Python’s keyword arg syntax. When providing a value to such a callable we prefer that the call also uses keyword arg syntax. For example:
# GOOD
f(0, optional=True)
# BAD
f(0, True)
This gives us the flexibility to re-order arguments and more importantly to add new required arguments. It’s also more explicit and easier to read.
Properly defining optional arguments¶
It’s always good to not initialize optional arguments at class creation,
instead use **kwargs
to get them. It’s well known Telegram API can
change without notice, in that case if a new argument is added it won’t
break the API classes. For example:
# GOOD
def __init__(self, id, name, last_name=None, **kwargs):
self.last_name = last_name
# BAD
def __init__(self, id, name, last_name=None):
self.last_name = last_name