By contributing to Coconut, you agree to your contribution being released under Coconut's Apache 2.0 license.
Anyone is welcome to submit an issue or pull request! The purpose of this document is simply to explain the contribution process and the internals of how Coconut works to make contributing easier.
If you are considering contributing to Coconut, you'll be doing so on the develop
branch, which means you should be viewing the develop
version of the Contributing Guidelines, if you aren't doing so already.
If you are thinking about contributing to Coconut, please don't hesitate to ask questions at Coconut's Gitter! That includes any questions at all about contributing, including understanding the source code, figuring out how to implement a specific change, or just trying to figure out what needs to be done.
Want to help out, but don't know what to work on? Head over to Coconut's open issues and look for ones labeled "good first issue." These issues are those that require less intimate knowledge of Coconut's inner workings, and are thus possible for new contributors to work on.
Contributing to Coconut is as simple as
- forking Coconut on GitHub,
- making changes to the
develop
branch, and - proposing a pull request.
Note: Don't forget to add yourself to the "Authors:" section in the moduledocs of any files you modify!
First, you'll want to set up a local copy of Coconut's recommended development environment. For that, just run git checkout develop
, make sure your default python
installation is some variant of Python 3, and run make dev
. That should switch you to the develop
branch, install all possible dependencies, bind the coconut
command to your local copy, and set up pre-commit, which will check your code for errors for you whenever you git commit
.
Then, you should be able to use the Coconut command-line for trying out simple things, and to run a paired-down version of the test suite locally, just make test-univ
.
After you've tested your changes locally, you'll want to add more permanent tests to Coconut's test suite. Coconut's test suite is primarily written in Coconut itself, so testing new features just means using them inside of one of Coconut's .coco
test files, with some assert
statements to check validity.
DOCS.md
- Markdown file containing detailed documentation on every Coconut feature. If you are adding a new feature, you should also add documentation on it to this file.
FAQ.md
- Markdown file containing frequently asked questions and their answers. If you had a question you wished was answered earlier when learning Coconut, you should add it to this file.
HELP.md
- Markdown file containing Coconut's tutorial. The tutorial should be a streamlined introduction to Coconut and all of its most important features.
Makefile
- Contains targets for installing Coconut, building the documentation, checking for dependency updates, etc.
setup.py
- Using information from
requirements.py
andconstants.py
to install Coconut. Also readsREADME.rst
to generate the PyPI description.
- Using information from
conf.py
- Sphinx configuration file for Coconut's documentation.
- coconut
__coconut__.py
- Mimics the Coconut header by generating and executing it when imported. Used by the REPL.
__init__.py
- Includes the implementation of the
%coconut
IPython magic.
- Includes the implementation of the
__main__.py
- Imports and runs
main
frommain.py
.
- Imports and runs
constants.py
- All constants used across Coconut are defined here, including dependencies, magic numbers/strings, etc.
convenience.py
- Contains
cmd
,version
,setup
, andparse
functions as convenience utilities when using Coconut as a module. Documented inDOCS.md
.
- Contains
exceptions.py
- All of the exceptions raised by Coconut are defined here, both those shown to the user and those used only internally.
highlighter.py
- Contains Coconut's Pygments syntax highlighter, as well as modified Python highlighters that don't fail if they encounter unknown syntax.
main.py
- Contains
main
andmain_run
, the entry points for thecoconut
andcoconut-run
commands, respectively.
- Contains
requirements.py
- Processes Coconut's requirements from
constants.py
into a formsetup.py
can use, as well as checks for updates to Coconut's dependencies.
- Processes Coconut's requirements from
root.py
root.py
creates and executes the part of Coconut's header that normalizes Python built-ins across versions. Whenever you are writing a new file, you should always addfrom coconut.root import *
to ensure compatibility with different Python versions.root.py
also sets basic version-related constants.
terminal.py
- Contains utilities for displaying messages to the console, mainly
logger
, which is Coconut's primary method of logging a message from anywhere.
- Contains utilities for displaying messages to the console, mainly
- command
__init__.py
- Imports everything in
command.py
.
- Imports everything in
cli.py
- Creates the
ArgumentParser
object used to parse Coconut command-line arguments.
- Creates the
command.py
- Contains
Command
, whosestart
method is the main entry point for the Coconut command-line utility.
- Contains
mypy.py
- Contains objects necessary for Coconut's
--mypy
flag.
- Contains objects necessary for Coconut's
util.py
- Contains utilities used by
command.py
, includingPrompt
for getting syntax-highlighted input, andRunner
for executing compiled Python.
- Contains utilities used by
watch.py
- Contains objects necessary for Coconut's
--watch
flag.
- Contains objects necessary for Coconut's
- compiler
__init__.py
- Imports everything in
compiler.py
.
- Imports everything in
compiler.py
- Contains
Compiler
, the class that actually compiles Coconut code.Compiler
inherits fromGrammar
ingrammar.py
to get all of the basic grammatical definitions, then extends them with all of the handlers that depend on the compiler's options (e.g. the current--target
).Compiler
also does pre- and post-processing, including replacing strings with markers (pre-processing) and adding the header (post-processing).
- Contains
grammar.py
- Contains
Grammar
, the class that specifies Coconut's grammar in PyParsing. Coconut performs one-pass compilation by attaching "handlers" to specific grammar objects to transform them into compiled Python.grammar.py
contains all basic (non-option-dependent) handlers.
- Contains
header.py
- Contains
getheader
, which generates the header at the top of all compiled Coconut files.
- Contains
matching.py
- Contains
Matcher
, which handles the compilation of all Coconut pattern-matching, includingmatch
statements, destructuring assignment, and pattern-matching functions.
- Contains
util.py
- Contains utilities for working with PyParsing objects that are primarily used by
grammar.py
.
- Contains utilities for working with PyParsing objects that are primarily used by
- templates
header.py_template
- Template for the main body of Coconut's header; use and formatting of this file is all in
header.py
.
- Template for the main body of Coconut's header; use and formatting of this file is all in
- icoconut
__init__.py
- Imports everything from
icoconut/root.py
.
- Imports everything from
__main__.py
- Contains the main entry point for Coconut's Jupyter kernel.
root.py
- Contains the implementation of Coconut's Jupyter kernel, made by subclassing the IPython kernel.
- tests
__init__.py
- Imports everything in
main_test.py
.
- Imports everything in
__main__.py
- When run, compiles all of the test source code, but does not run any tests. To run the tests, the command
make test
, or apytest
command to run a specific test, is necessary.
- When run, compiles all of the test source code, but does not run any tests. To run the tests, the command
main_test.py
- Contains
TestCase
subclasses that run all of the commands for testing the Coconut files insrc
.
- Contains
- src
extras.coco
- Directly imports and calls functions in the Coconut package, including from
convenience.py
and icoconut.
- Directly imports and calls functions in the Coconut package, including from
runnable.coco
- Makes sure the argument
--arg
was passed when running the file.
- Makes sure the argument
runner.coco
- Runs
main
fromcocotest/agnostic/main.py
.
- Runs
- cocotest
- Note: Files in the folders below all get compiled into the top-level cocotest directory. The folders are only for differentiating what files to compile on what Python version.
- agnostic
__init__.coco
- Contains a docstring that
main.coco
asserts exists.
- Contains a docstring that
main.coco
- Contains the main test entry point as well as many simple, one-line tests.
specific.coco
- Tests to be run only on a specific Python version, but not necessarily only under a specific
--target
.
- Tests to be run only on a specific Python version, but not necessarily only under a specific
suite.coco
- Tests objects defined in
util.coco
.
- Tests objects defined in
tutorial.coco
- Tests all the examples in
TUTORIAL.md
.
- Tests all the examples in
util.coco
- Contains objects used in
suite.coco
.
- Contains objects used in
- python2
py2_test.coco
- Tests to be run only on Python 2 with
--target 2
.
- Tests to be run only on Python 2 with
- python3
py3_test.coco
- Tests to be run only on Python 3 with
--target 3
.
- Tests to be run only on Python 3 with
- python35
py35_test.coco
- Tests to be run only on Python 3.5 with
--target 3.5
.
- Tests to be run only on Python 3.5 with
- python36
py36_test.coco
- Tests to be run only on Python 3.6 with
--target 3.6
.
- Tests to be run only on Python 3.6 with
- coconut-stubs
__coconut__.pyi
- A MyPy stub file for specifying the type of all the objects defined in Coconut's package header (which is saved as
__coconut__.py
).
- A MyPy stub file for specifying the type of all the objects defined in Coconut's package header (which is saved as
-
Preparation:
- Run
make check-reqs
and update dependencies as necessary - Run
sudo make format
- Make sure
make test
,make test-pyright
, andmake test-easter-eggs
are passing - Ensure that
coconut --watch
can successfully compile files when they're modified - Check changes in
compiled-cocotest
,pyprover
, andcoconut-prelude
- Check Codebeat and LGTM for
coconut
andcompiled-cocotest
- Make sure
coconut-develop
package looks good - Run
make docs
and ensure local documentation looks good - Make sure all of the following are passing:
- Make sure develop documentation looks good
- Turn off
develop
inroot.py
- Set
root.py
to new version number - If major release, set
root.py
to new version name
- Run
-
Pull Request:
- Move unresolved issues to new milestone
- Create a pull request to merge
develop
intomaster
- Link contributors on pull request
- Wait until everything is passing
-
Release:
- Release a new version of
sublime-coconut
if applicable- Edit the
package.json
with the new version - Run
make publish
- Release a new version on GitHub
- Edit the
- Merge pull request and mark as resolved
- Release
master
on GitHub git fetch
,git checkout master
, andgit pull
- Run
sudo make upload
git checkout develop
,git rebase master
, andgit push
- Turn on
develop
inroot
- Run
sudo make dev
- Push to
develop
- Wipe all updated versions on readthedocs
- Build all updated versions on readthedocs
- Copy PyPI keywords to readthedocs tags
- Get SHA-256 hash from PyPI
.tar.gz
file and use that as well as the current version requirements inconstants.py
to update the local feedstock - Submit PR to update Coconut's
conda-forge
feedstock - Update website if it needs updating
- Wait until feedstock PR is passing then merge it
- Close release milestone
- Release a new version of