Coconut Contributing Guidelines#
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.
Asking Questions#
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.
Good First Issues#
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.
Contribution Process#
Contributing to Coconut is as simple as
forking Coconut on GitHub,
making changes to the
developbranch, andproposing a pull request.
Note: Don’t forget to add yourself to the “Authors:” section in the moduledocs of any files you modify!
Testing New Changes#
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.
File Layout#
DOCS.mdMarkdown 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.mdMarkdown 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.mdMarkdown file containing Coconut’s tutorial. The tutorial should be a streamlined introduction to Coconut and all of its most important features.
MakefileContains targets for installing Coconut, building the documentation, checking for dependency updates, etc.
setup.pyUsing information from
requirements.pyandconstants.pyto install Coconut. Also readsREADME.rstto generate the PyPI description.
conf.pySphinx configuration file for Coconut’s documentation.
coconut
__coconut__.pyMimics the Coconut header by generating and executing it when imported. Used by the REPL.
__init__.pyIncludes the implementation of the
%coconutIPython magic.
__main__.pyImports and runs
mainfrommain.py.
constants.pyAll constants used across Coconut are defined here, including dependencies, magic numbers/strings, etc.
convenience.pyContains
cmd,version,setup, andparsefunctions as convenience utilities when using Coconut as a module. Documented inDOCS.md.
exceptions.pyAll of the exceptions raised by Coconut are defined here, both those shown to the user and those used only internally.
highlighter.pyContains Coconut’s Pygments syntax highlighter, as well as modified Python highlighters that don’t fail if they encounter unknown syntax.
main.pyContains
mainandmain_run, the entry points for thecoconutandcoconut-runcommands, respectively.
requirements.pyProcesses Coconut’s requirements from
constants.pyinto a formsetup.pycan use, as well as checks for updates to Coconut’s dependencies.
root.pyroot.pycreates 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.pyalso sets basic version-related constants.
terminal.pyContains utilities for displaying messages to the console, mainly
logger, which is Coconut’s primary method of logging a message from anywhere.
command
__init__.pyImports everything in
command.py.
cli.pyCreates the
ArgumentParserobject used to parse Coconut command-line arguments.
command.pyContains
Command, whosestartmethod is the main entry point for the Coconut command-line utility.
mypy.pyContains objects necessary for Coconut’s
--mypyflag.
util.pyContains utilities used by
command.py, includingPromptfor getting syntax-highlighted input, andRunnerfor executing compiled Python.
watch.pyContains objects necessary for Coconut’s
--watchflag.
compiler
__init__.pyImports everything in
compiler.py.
compiler.pyContains
Compiler, the class that actually compiles Coconut code.Compilerinherits fromGrammaringrammar.pyto 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).Compileralso does pre- and post-processing, including replacing strings with markers (pre-processing) and adding the header (post-processing).
grammar.pyContains
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.pycontains all basic (non-option-dependent) handlers.
header.pyContains
getheader, which generates the header at the top of all compiled Coconut files.
matching.pyContains
Matcher, which handles the compilation of all Coconut pattern-matching, includingmatchstatements, destructuring assignment, and pattern-matching functions.
util.pyContains utilities for working with PyParsing objects that are primarily used by
grammar.py.
templates
header.py_templateTemplate for the main body of Coconut’s header; use and formatting of this file is all in
header.py.
icoconut
__init__.pyImports everything from
icoconut/root.py.
__main__.pyContains the main entry point for Coconut’s Jupyter kernel.
root.pyContains the implementation of Coconut’s Jupyter kernel, made by subclassing the IPython kernel.
tests
__init__.pyImports everything in
main_test.py.
__main__.pyWhen run, compiles all of the test source code, but does not run any tests. To run the tests, the command
make test, or apytestcommand to run a specific test, is necessary.
main_test.pyContains
TestCasesubclasses that run all of the commands for testing the Coconut files insrc.
src
extras.cocoDirectly imports and calls functions in the Coconut package, including from
convenience.pyand icoconut.
runnable.cocoMakes sure the argument
--argwas passed when running the file.
runner.cocoRuns
mainfromcocotest/agnostic/main.py.
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__.cocoContains a docstring that
main.cocoasserts exists.
main.cocoContains the main test entry point as well as many simple, one-line tests.
specific.cocoTests to be run only on a specific Python version, but not necessarily only under a specific
--target.
suite.cocoTests objects defined in
util.coco.
tutorial.cocoTests all the examples in
TUTORIAL.md.
util.cocoContains objects used in
suite.coco.
python2
py2_test.cocoTests to be run only on Python 2 with
--target 2.
python3
py3_test.cocoTests to be run only on Python 3 with
--target 3.
python35
py35_test.cocoTests to be run only on Python 3.5 with
--target 3.5.
python36
py36_test.cocoTests to be run only on Python 3.6 with
--target 3.6.
coconut-stubs
__coconut__.pyiA MyPy stub file for specifying the type of all the objects defined in Coconut’s package header (which is saved as
__coconut__.py).
Release Process#
Preparation:
Run
make check-reqsand update dependencies as necessaryRun
sudo make formatRun manual tests:
Temporarily set
test_computation_graph_pickling = Trueinconstants.pyand runmake testRun
make docsand ensure local documentation looks goodEnsure that
coconut --watchcan successfully compile files when they’re modifiedMake sure
make test-pyrightandmake test-easter-eggsare passing
Check all the tooling:
Make sure
coconut-developpackage looks goodCheck changes in
compiled-cocotest,pyprover, andcoconut-prelude
Make sure all of the following are passing:
Make sure develop documentation looks good
Turn off
developinroot.pySet
root.pyto new version numberIf major release, set
root.pyto new version name
Pull Request:
Move unresolved issues to new milestone
Create a pull request to merge
developintomasterLink contributors on pull request
Wait until everything is passing
Release:
Release a new version of
sublime-coconutif applicableEdit the
package.jsonwith the new versionRun
make publish
Merge pull request and mark as resolved
Release
masteron GitHubgit fetch,git checkout master, andgit pullRun
sudo make uploadgit checkout develop,git rebase master, andgit pushTurn on
developinrootRun
sudo make devPush to
developWipe all updated versions on readthedocs
Build all updated versions on readthedocs
Copy PyPI keywords to readthedocs tags
Get SHA-256 hash from PyPI
.tar.gzfile and use that as well as the current version requirements inconstants.pyto update the local feedstockSubmit PR to update Coconut’s
conda-forgefeedstockUpdate website if it needs updating
Wait until feedstock PR is passing then merge it
Close release milestone