diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..9f0fffcd --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,164 @@ +# Contributing Guide + +This document supplements the [Exercism contributing guide]; all contributors should read that document before proceeding. + +## Table of Contents + +- [Contributing Guide](#contributing-guide) + * [Architecture](#architecture) + * [Implementing an exercise](#implementing-an-exercise) + + [Exercise structure](#exercise-structure) + + [Generating Exercise READMEs](#generating-exercise-readmes) + - [Requirements](#requirements) + - [Generating all READMEs](#generating-all-readmes) + - [Generating a single README](#generating-a-single-readme) + + [Implementing tests](#implementing-tests) + + [Example solutions](#example-solutions) + + [config.json](#configjson) + * [Implementing Track-specific Exercises](#implementing-track-specific-exercises) + * [Pull Request Tips](#pull-request-tips) + + +## Architecture + +Exercism tracks inherit exercise definitions from the [problem-specifications] repository in the form of description files +(from which exercise READMEs are [generated](#generating-exercise-readmes)) + + +## Implementing an exercise + +### Exercise structure + +```Bash +exercises/[EXERCISE]/ +├── [EXERCISE].py +├── [EXERCISE]_test.py +├── example.py +├── .meta +│ ├── template.j2 +│ ├── additional_tests.json +│ └── hints.md +└── README.md +``` + +Files: + +| File | Description | Source | +|:--- |:--- |:--- | +| [[EXERCISE].py](exercises/two-fer/two_fer.py) | Solution stub | Manually created by the implementer | +| [[EXERCISE]_test.py](exercises/two-fer/two_fer_test.py) | Exercise test suite | Automatically generated if `.meta/template.j2` is present, otherwise manually created by the implementer | +| [example.py](exercises/two-fer/example.py) | Example solution used to automatically verify the `[EXERCISE]_test.py` suite | Manually created by the implementer | +| [.meta/template.j2](exercises/two-fer/.meta/template.j2) | Test generation template; if present used to automatically generate `[EXERCISE]_test.py` (See [generator documentation](docs/GENERATOR.md)) | Manually created by implementer | +| [.meta/additional_tests.json](exercises/word-count/.meta/additional_tests.json) | Defines additional track-specific test cases; if `.meta/template.j2` is also present these test will be incorporated into the automatically generated `[EXERCISE]_test.py` | Manually created by the implementer | +| [.meta/hints.md](exercises/high-scores/.meta/hints.md) | Contains track-specific hints that are automatically included in the generated `README.md` file | Manually created by the implementer | +| [README.md](exercises/two-fer/README.md) | Exercise README | [Generated by `configlet` tool](#generating-exercise-readmes) | + +### Generating Exercise READMEs + +#### Requirements +- A local clone of the [problem-specifications] repository. +- [configlet]: may be obtained either by + - (**Recommended**) Following installation instructions at the above link + - Running `bin/fetch-configlet` (`configlet` binary will be downloaded to the repository `bin/`) + +#### Generating all READMEs + +``` +configlet generate --spec-path path/to/problem/specifications +``` + +#### Generating a single README + +``` +configlet generate --spec-path path/to/problem/specifications --only example-exercise +``` + +### Implementing tests + +If an unimplemented exercise has a `canonical-data.json` file in the [problem-specifications] repository, a generation template must be created. See the [test generator documentation](docs/GENERATOR.md) for more information. + +If an unimplemented exercise does not have a `canonical-data.json` file, the test file must be written manually (use existing test files for examples). + +### Example solutions + +Example solution files serve two purposes: + +1. Verification of the tests +2. Example implementation for mentor/student reference + +### config.json + +[`config.json`](config.json) is used by the website to determine which exercises to load an in what order. It also contains some exercise metadata, such as difficulty, labels, and if the exercise is a core exercise. New entries should be places just before the first exercise that is marked `"deprecated": true`: + +```JSON + { + "slug": "current-exercise", + "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", + "core": false, + "unlocked_by": null, + "difficulty": 1, + "topics": [ + "strings" + ] + }, + <<< HERE + { + "slug": "old-exercise", + "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", + "core": false, + "unlocked_by": null, + "difficulty": 2, + "topics": null, + "status": "deprecated" + }, +``` + +Fields + + + + + + + + + + + + + + + + + + + + + + + + + +
slugHyphenated lowercase exercise name
uuidGenerate using configlet uuid
coreSet to false; core exercises are decided by track maintainers
unlocked_bySlug for the core exercise that unlocks the new one
difficulty1 through 10. Discuss with reviewer if uncertain.
topicsArray of relevant topics from the topics list
+ + +## Implementing Track-specific Exercises + +Similar to implementing a canonical exercise that has no `canonical-data.json`, but the exercise README will also need to be written manually. Carefully follow the structure of generated exercise READMEs. + + +## Pull Request Tips + +Before committing: +- Run `configlet fmt` and `configlet lint` before committing if [`config.json`](config.json) has been modified +- Run [flake8] to ensure all Python code conforms to style standards +- Run `test/check-exercises.py [EXERCISE]` to check if your test changes function correctly +- If you modified or created a `hints.md` file, [regenerate the README](#generating-exercise-readmes) +- If your changes affect multiple exercises, try to break them up into a separate PR for each exercise. + + +[configlet]: https://github.com/exercism/configlet +[Exercism contributing guide]: https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md +[problem-specifications]: https://github.com/exercism/problem-specifications +[topics list]: https://github.com/exercism/problem-specifications/blob/master/TOPICS.txt +[flake8]: http://flake8.pycqa.org/