From 495ce78e126dc961a3d712ad01edd4b5f8f5709c Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Sun, 2 Jul 2023 15:32:22 -1000 Subject: [PATCH] Add Policy on args/keywords Fixes #1389 --- CONTRIBUTING.md | 175 +--------- .../developerGuidelines.ipynb | 309 ++++++++++++++++++ .../source/developerReference/index.rst | 1 + music21/common/stringTools.py | 1 + music21/figuredBass/notation.py | 4 - 5 files changed, 313 insertions(+), 177 deletions(-) create mode 100644 documentation/source/developerReference/developerGuidelines.ipynb diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bd4557defd..7996de6143 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,184 +2,13 @@ documentation improvements. The [project repository](http://www.github.com/cuthbertLab/music21) is hosted at GitHub. -In the first few years of `music21`, major new areas of investigation (medieval -rhythm encoding, contour analysis, etc.) were routinely added to the system. Now -features that are unlikely to be of general use are encouraged to live in their -own projects that import and extend `music21`. - +Information that was formerly here is now in +[Developer Reference](https://web.mit.edu/music21/doc/developerReference/index.html) ## Resources ## [Module Documentation and User's Guide](https://web.mit.edu/music21/doc/index.html) -[Developer Reference](https://web.mit.edu/music21/doc/developerReference/index.html) - [Mailing List](https://groups.google.com/forum/#!forum/music21list) [Code of Conduct](README.md) - - -## Preparing to Contribute ## - -Be sure to install all of the requirements in `requirements_dev.txt` via: - -``` -pip3 install -r requirements_dev.txt -``` - -There are several tools needed for fully testing music21 that aren't included -in the standard `requirements.txt`. - -## Issue Tickets ## - -Please use the provided templates for bug reports or feature proposals. For issues -parsing file formats, (i.e. missing/buggy features not translated to or from that -format), please add to (or start) a general ticket for all support requests for that format. -(Some formats are no longer being actively maintained, such as MEI, LilyPond, and MuseData, -but well-tested patches can be merged.) - -Good bug reports clearly state the unexpected behavior and include a short set of -commands to reproduce the issue. If your example requires loading a file, a two-measure -file is appropriate; a symphony movement is not--that's a support request. GitHub -is not a support channel. - -Speaking of support, helpful people hang out on the -[mailing list](https://groups.google.com/forum/#!forum/music21list) -or Stack Overflow. - - -## Submitting Pull Requests ## - -Open an issue to propose a feature or report a bug before raising a pull request. -You can include a diff or link to your own repo if you've -already started some of the work. -(Changes where the motivation is self-evident, like handling exceptions or increasing -test coverage, don't need issue tickets.) - -If your PR fixes an existing issue, please use a GitHub keyword ("Fixes #NNNN") -in the body of the PR so that the issue will be closed on merge. - -You can run locally the same tests that GitHub Actions will run. Install `pylint` -and `flake8` and run them against the files you edited, and give the test suite a go, -also. (Quick start: run `python3 -m music21.test.multiprocessTest`.) -If you miss something and GitHub Actions pesters you with red "X"s, just -expand the details to get the line-by-line violations, and push another commit. - -Speaking of commits, use incremental commits with descriptive messages rather -than force-pushing, which prevents the reviewer from assessing what changed -between reviews. (Squashing commits will be handled by the merger.) - - -## Style Guide ## - -`Music21` began in Perl. Now it interfaces with the TypeScript package `music21j`. -Both of those languages use `camelCase` extensively. For these reasons, -as well as for backward compatibility, we adhere to `camelCase` -naming--rather than Python PEP8 `snake_case` naming--for public APIs such as method names, -arguments, and the like. - -That said, snake_case is acceptable (even encouraged!) in new contributions -for internal variables that are not exposed publicly. Screen readers can -pronounce these names better and make them more accessible. -However, all exposed methods and functions and their exposed arguments must -be in camelCase. - -Conventions: - - - **strings MUST be 'single-quoted', but "double quotes" are allowed internally** - - this rule applies to triple quotes and doc strings also, contrary to PEP 257. - - Docstrings must begin and end on their own lines. No one-line doc-strings or text - immediately following the triple quotes. - - when there is a hyphen or single quote in the string, double quotes should be used, - not escaping/backslashing. - - For long streams of TinyNotation or Lilypond code, which both use single quotes to indicate octave, - triple single quotes around the string are better than double quotes. Internal whitespace - rarely matters in those formats. - - Documentation should follow quoting in American English grammar when not - discussing code. So for instance, a quotation in documentation is in double quotes. - - variable names: - - need to be unambiguous, even if rather long. - - must begin with lowercase (or underscore + lowercase) unless they represent classes. - - snake_case is allowed/encouraged for private variables for accessibility. - - camelCase is required for public. - - line lengths are capped at 100, but if approaching this limit, look for ways to avoid one-lining. - - if it's easy to split your line into two which are both under 80 characters, do so. - - line continuation characters (`\`) are not allowed; use open parentheses. - - prefer f-strings to `.format()`. The `%` interpolation is no longer allowed. - - annotating types is required in new code, and encouraged to be added to older code. - - e.g. `self.counter: int = 0` or `def makeNoises() -> list['noise.Noise']:` - - The typing library should always be imported as `t`. - - Until `music21` no longer supports Python 3.9, use `t.Optional[x]` rather than `x|None`. - - prefer enums to string configurations - - in music21.common.enums, there is a StrEnum class for nearly-backwards compatible - replacement of a former string argument with an enum. - - new Enums do not need to inherit from StrEnum or IntEnum. - - Enum members should be in ALL_CAPS with underscores, unless there is a good reason (such - as case differentiation) to use CamelCase. I personally hate this convention--it looks - like shouting--and will revisit it if `music21` is ever ported to a language where - this is not the convention. Do not leave out underscores in the member names; it makes - it hard for people whose native language is not English to parse and impossible for - screen readers. - - methods: - - no more than three positional arguments (four, if the first is `self`) - - keyword arguments should be keyword-only by using `*` - to consume any other positional arguments: `def makeNoise(self, volume, *, color=noise.PINK):` - - avoid generic `**keywords`; make keywords explicit. - (This rule does not necessarily apply for subclass inheritance where you want to allow the superclass - to add more features later. But see the Liskov principle next.) - See also https://github.com/cuthbertLab/music21/issues/1389 - - prefer methods that by default do not alter the object passed in and instead return a new one. - It is permitted and encouraged to have an `inPlace: bool = False` argument that allows for - manipulation of the original object. When `inPlace` is True, nothing should be returned - (not true for `music21j` since passing through objects is so expected in JavaScript thanks - to JQuery and other libraries). Use the `@overload` decorator to show how this parameter - affects the return value. - - New classes should strongly endeavor to follow Liskov Substitution Principle. - - Exceptions may be granted if the class structures follow names that are in common musical use - but whose real world objects do not follow this principle. For instance, a `Manx` is a subclass - of `Cat` without `self.tail`. Sometimes, however, rewriting the superclass might be possible - (perhaps `self.tail: t.Optional[Tail]`). - - `Music21` was originally designed without this principle in mind, so you will find - parts of the system that do not follow LSP and for backwards compatibility never will. - I (Myke) have personally apologized to Barbara Liskov for my past ignorance. - - use [Sphinx formatting](https://web.mit.edu/music21/doc/developerReference/documenting.html#documenting-modules-and-classes) - to link to classes and methods in docstrings - - use descriptive pull request titles (rather than GitHub's default "Update pitch.py") - - do not have the PR title too long that it cannot be seen in one line. Simplify and - rewrite and go into more detail in the description. I depend on skimming PR titles - to prepare reports of changes. - - don't turn a PR into a general discussion of something not included in the PR. - Make an issue and link to the PR from there. - - Write the word `music21` in lowercase in the middle of a sentence and as `Music21` at - the beginning of a sentence. Avoid beginning a sentence with a module name, but if - it has to be done, write it in lowercase, obviously. In contexts where possible, - `music21` should be stylized in monospaced (with slab serifs, like old typewriters). - -## Testing ## - -We write doctests and unit tests, and we strive for the total -test coverage of the project to increase with every pull request. See the -[developer docs](https://web.mit.edu/music21/doc/developerReference/index.html) -to dig in to specific topics like adjusting doctests to prevent -actions we don't want executed when running the general test suite (such as opening -browser windows or playing music). - -Pull requests that increase or improve coverage of existing features are very welcome. -Coverage reports can be found at [Coveralls](https://coveralls.io/github/cuthbertLab/music21). -Pull requests that lower overall coverage are likely to be rejected (exception: replace -30 covered lines with 5 covered lines that do the same job more efficiently, and you've -lowered the overall coverage, but that's okay). - -For changes to file parsing, please test both import and export (when supported for -that format), and please increment the most minor version number in `music21.__version__` -so that cached files will be invalidated. When writing a PR that changes imports, feel -free to use `converter.parse(fp, forceSource=True)` so that tests have a chance -to fail locally, but in most cases we will ask you to remove this keyword -when polishing the patch. - - -## Finally ## - -If you're looking for ways to get started, browse the issues board, the Coveralls module -coverage, or the TODO stubs in an area of the code that interests you. -Thanks for your interest in contributing to `music21`. We look forward to seeing your work! diff --git a/documentation/source/developerReference/developerGuidelines.ipynb b/documentation/source/developerReference/developerGuidelines.ipynb new file mode 100644 index 0000000000..76cdff7943 --- /dev/null +++ b/documentation/source/developerReference/developerGuidelines.ipynb @@ -0,0 +1,309 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Developer Guidelines\n", + "\n", + "`Music21` welcomes contributions such as bug reports, new features, fixes, and\n", + "documentation improvements. The\n", + "[project repository](http://www.github.com/cuthbertLab/music21) is hosted at GitHub." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Resources ##\n", + "\n", + "Get to know this before contributing:\n", + "\n", + "[Module Documentation and User's Guide](https://web.mit.edu/music21/doc/index.html)\n", + "\n", + "[Mailing List](https://groups.google.com/forum/#!forum/music21list)\n", + "\n", + "[Code of Conduct](https://github.com/cuthbertLab/music21/blob/master/README.md#community-code-of-conduct)\n" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Project Scope ##\n", + "\n", + "Contributions to `music21` should fix bugs or add to coverage of corner cases\n", + "already part of the project and not add major new features without discussion.\n", + "\n", + "In the first few years of `music21`, major new areas of investigation (medieval\n", + "rhythm encoding, contour analysis, etc.) were routinely added to the system. Now\n", + "features that are unlikely to be of general use are encouraged to live in their\n", + "own projects that import and extend `music21`.\n", + "\n", + "It is easy to create your own project and have that import `music21` -- over time\n", + "the maintenance burden of \"drive-by-feature-addition\" has become substantial.\n" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Preparing to Contribute ##\n", + "\n", + "Be sure to install all requirements in `requirements_dev.txt` via:\n", + "\n", + "```\n", + "pip3 install -r requirements_dev.txt\n", + "```\n", + "\n", + "There are several tools needed for fully testing music21 that aren't included\n", + "in the standard `requirements.txt`." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Issue Tickets ##\n", + "\n", + "Please use the provided templates for bug reports or feature proposals. For issues\n", + "parsing file formats, (i.e. missing/buggy features not translated to or from that\n", + "format), please add to (or start) a general ticket for all support requests for that format.\n", + "(Some formats are no longer being actively maintained, such as MEI, LilyPond, and MuseData,\n", + "but well-tested patches can be merged.)\n", + "\n", + "Good bug reports clearly state the unexpected behavior and include a short set of\n", + "commands to reproduce the issue. If your example requires loading a file, a two-measure\n", + "file is appropriate; a symphony movement is not--that's a support request. GitHub\n", + "is not a support channel.\n", + "\n", + "Speaking of support, helpful people hang out on the\n", + "[mailing list](https://groups.google.com/forum/#!forum/music21list) or Stack Overflow." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Submitting Pull Requests ##\n", + "\n", + "Open an issue to propose a feature or report a bug before raising a pull request.\n", + "You can include a diff or link to your own repo if you've\n", + "already started some of the work.\n", + "(Changes where the motivation is self-evident, like handling exceptions or increasing\n", + "test coverage, don't need issue tickets.)\n", + "\n", + "If your PR fixes an existing issue, please use a GitHub keyword (\"Fixes #NNNN\")\n", + "in the body of the PR so that the issue will be closed on merge.\n", + "\n", + "You can run locally the same tests that GitHub Actions will run. Install `pylint`\n", + "and `flake8` and run them against the files you edited, and give the test suite a go,\n", + "also. (Quick start: run `python3 -m music21.test.multiprocessTest`.)\n", + "If you miss something and GitHub Actions pesters you with red \"X\"s, just\n", + "expand the details to get the line-by-line violations, and push another commit.\n", + "\n", + "Speaking of commits, use incremental commits with descriptive messages rather\n", + "than force-pushing, which prevents the reviewer from assessing what changed\n", + "between reviews. (Squashing commits will be handled by the merger.)\n", + "\n", + "Note that new contributions are generally expected to increase the test coverage\n", + "in coveralls.io -- when you submit a PR, you'll see a report of how much coverage\n", + "has changed by your contributions. Look over the lines that are uncovered and\n", + "make sure to write tests for them." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Style Guide ##\n", + "\n", + "`Music21` began in Perl. Now it interfaces with the TypeScript package `music21j`.\n", + "Both of those languages use `camelCase` extensively. For these reasons,\n", + "as well as for backward compatibility, we adhere to `camelCase`\n", + "naming--rather than Python PEP8 `snake_case` naming--for public APIs such as method names,\n", + "arguments, and the like.\n", + "\n", + "That said, snake_case is acceptable in new contributions\n", + "for *internal variables* that are not exposed publicly. Some screen readers can\n", + "pronounce these names better and make them more accessible (however, more modern\n", + "screen readers seem to do well with camelCase).\n", + "However, all exposed methods and functions and their exposed arguments **must**\n", + "be in camelCase.\n", + "\n", + "Conventions:\n", + "\n", + " - **Strings MUST be 'single-quoted', but \"double quotes\" are allowed internally**\n", + " - This rule applies to triple quotes and doc strings also, contrary to PEP 257.\n", + " - Docstrings must begin and end on their own lines. No one-line doc-strings or text\n", + " immediately following the triple quotes.\n", + " - When there is a hyphen or single quote in the string, double quotes should be used,\n", + " not escaping/backslashing.\n", + " - For long streams of TinyNotation or Lilypond code, which both use single quotes to indicate octave,\n", + " triple single quotes around the string are better than double quotes. Internal whitespace\n", + " rarely matters in those formats.\n", + " - Documentation should follow quoting in American English grammar when not\n", + " discussing code. So for instance, a quotation in documentation is in double quotes.\n", + " - Variable names:\n", + " - Need to be unambiguous, even if rather long.\n", + " - Must begin with lowercase (or underscore + lowercase) unless they represent classes.\n", + " - snake_case is allowed for private variables.\n", + " - camelCase is required for public.\n", + " - Line lengths are capped at 100, but if approaching this limit, look for ways to avoid one-lining.\n", + " - if it's easy to split your line into two which are both under 80 characters, do so.\n", + " - Line continuation characters (`\\`) are not allowed; use open parentheses.\n", + " - Prefer f-strings to `.format()`. The `%` interpolation is no longer allowed.\n", + " - Annotating types is **required** in new code, and encouraged to be added to older code.\n", + " - e.g. `self.counter: int = 0` or `def makeNoises() -> list['noise.Noise']:`\n", + " - The typing library should always be imported as `t`.\n", + " - Use `type | None` rather than `t.Optional[type]`.\n", + " - Prefer enums to string configurations\n", + " - In music21.common.enums, there is a StrEnum class for nearly-backwards compatible\n", + " replacement of a former string argument with an enum.\n", + " - New Enums do not need to inherit from StrEnum or IntEnum.\n", + " - Enum members should be in ALL_CAPS with underscores, unless there is a good reason (such\n", + " as case differentiation) to use CamelCase. I personally hate this convention--it looks\n", + " like shouting--and will revisit it if `music21` is ever ported to a language where\n", + " this is not the convention. Do not leave out underscores in the member names; it makes\n", + " it hard for people whose native language is not English to parse and impossible for\n", + " screen readers.\n", + " - New classes should strongly endeavor to follow Liskov Substitution Principle.\n", + " - Exceptions may be granted if the class structures follow names that are in common musical use\n", + " but whose real world objects do not follow this principle. For instance, a `Manx` is a subclass\n", + " of `Cat` without `self.tail`. Sometimes, however, rewriting the superclass might be possible\n", + " (perhaps `self.tail: t.Optional[Tail]`).\n", + " - `Music21` was originally designed without this principle in mind, so you will find\n", + " parts of the system that do not follow LSP and for backwards compatibility never will.\n", + " I (Myke) have personally apologized to Barbara Liskov for my past ignorance.\n", + " - Use [Sphinx formatting](https://web.mit.edu/music21/doc/developerReference/documenting.html#documenting-modules-and-classes)\n", + " to link to classes and methods in docstrings\n", + " - Prefer methods that by default do not alter the object passed in and instead return a new one.\n", + " It is permitted and encouraged to have an `inPlace: bool = False` argument that allows for\n", + " manipulation of the original object. When `inPlace` is True, nothing should be returned\n", + " (not true for `music21j` since passing through objects is so expected in JavaScript thanks\n", + " to JQuery and other libraries). Use the `@overload` decorator to show how this parameter\n", + " affects the return value -- Python makes this a bit hard, but see for instance, :meth:`~music21.stream.base.Stream.getElementsByClass` for an example of how to use this.\n", + " - Use descriptive pull request titles (rather than GitHub's default \"Update pitch.py\")\n", + " - Do not have a PR title so long that it cannot be seen in one line. Simplify and\n", + " rewrite and go into more detail in the description. I depend on skimming PR titles\n", + " to prepare reports of changes.\n", + " - Don't turn a PR into a general discussion of something not included in the PR.\n", + " Make an issue and link to the PR from there.\n", + " - Write the word `music21` in lowercase in the middle of a sentence and as `Music21` at\n", + " the beginning of a sentence. Avoid beginning a sentence with a module name, but if\n", + " it has to be done, write it in lowercase, obviously. In contexts where possible,\n", + " `music21` should be stylized in monospaced (with slab serifs, like old typewriters).\n" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Testing ##\n", + "\n", + "We write doctests and unit tests, and we strive for the total\n", + "test coverage of the project to increase with every pull request. See the\n", + "[developer docs](https://web.mit.edu/music21/doc/developerReference/index.html)\n", + "to dig in to specific topics like adjusting doctests to prevent\n", + "actions we don't want executed when running the general test suite (such as opening\n", + "browser windows or playing music).\n", + "\n", + "Pull requests that increase or improve coverage of existing features are very welcome.\n", + "Coverage reports can be found at [Coveralls](https://coveralls.io/github/cuthbertLab/music21).\n", + "Pull requests that lower overall coverage are likely to be rejected (exception: replace\n", + "30 covered lines with 5 covered lines that do the same job more efficiently, and you've\n", + "lowered the overall coverage, but that's okay).\n", + "\n", + "For changes to file parsing, please test both import and export (when supported for\n", + "that format), and please increment the most minor version number in `music21.__version__`\n", + "so that cached files will be invalidated. When writing a PR that changes imports, feel\n", + "free to use `converter.parse(fp, forceSource=True)` so that tests have a chance\n", + "to fail locally, but in most cases we will ask you to remove this keyword\n", + "when polishing the patch." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Arguments and Keywords in classes, methods, and functions\n", + "\n", + "These guidelines come from [GitHub issue 1389](https://github.com/cuthbertLab/music21/issues/1389); any further discussion should take place there.\n", + "\n", + "1. These guidelines have been in place since music21 v8 (Fall 2022). All older functions can continue as is, but should be updated when possible. The existence of older functions that violates these rules cannot be cited as precedent.\n", + "2. Functions can have no more than 3 positional arguments, and should only include ones used most often.\n", + " - Methods may have \"self\" + 3 positional arguments\n", + " - Any remaining arguments should be keyword only\n", + " - When adding new functionality to existing functions, nearly always, a keyword-only argument is the right choice.\n", + " - The order of arguments should make sense: numerator -> denominator, from -> to. If it's likely to be confused (especially if two variables are the same type), better to use keyword only.\n", + "3. For arbitrary positional and keyword arguments that are not parsed, the names are `*arguments, **keywords`. #1377 has made this rename for `**keywords` -- this change was easy since `**kwargs` is daunting to new users (I remember not knowing what it meant). The choice of `*args` vs `*arguments` was tough, since `*args` is more obvious what it means than `**kwargs`, and `*arguments` is longer; they are used about equally in existing code. The decision was based on `*arguments` being more explicit, AND being longer to type is a slight ADVANTAGE since this Issue discourages using it. And, this should be a moot issue in any case, because of rules below.\n", + "4. Functions should NOT look at `**keywords`. [See GitHub issue #839](https://github.com/cuthbertLab/music21/issues/839) -- any members that will be used in the function must be explicitly mentioned in the function signature.\n", + " - So instead of `if 'myOption' in keywords...` put `myOption: t.Optional[Something] = None` in the signature of the function.\n", + " - An exception is granted for multiple inheritance to examine the `**keywords` dict to split it for two different\n", + " constructors which use the same key to mean something different.\n", + " - Keyword arguments should be keyword-only by using `*`\n", + " to consume any other positional arguments: `def makeNoise(self, volume, *, color=noise.PINK):`\n", + "5. Methods can have a generic `**keywords` at the end of the constructor signature which is assumed to be passed up the inheritance chain to the superclass for its own keywords (or its superclass's own keywords, etc.). This is required for Music21Object subclasses. This way other Music21Objects don't have to deal with `duration`, `groups`, `style`, etc. and can pass it up the chain. It is especially important for `id` since this requires pylint exemptions, etc.\n", + "6. The only use of `(*arguments, **keywords)` is for a quick subclass that needs to keep track of something else along the way and we want to avoid the maintenance burden of, e.g., updating Marcato whenever the signature of Music21Object, Articulation, etc. changes. Core and often used subclasses should know what the signatures of their superclasses are and write their constructors accordingly. The use of common.types shortcuts, such as OffsetQL (for types that are allowed as offset or quarterLength values) should be used to avoid writing long and variable types over and over. Even here, don't use `*arguments` if the superclass does not have arguments currently.\n", + "7. Aside from the case above `*arguments` should only be used in cases where the number of arguments is actually unlimited, all have the same type as each other, and all have the same meaning. E.g., Chord, has an arbitrary number of Note, Pitch, or string arguments can be passed in separated by commas. Code should not have things like what Tuplet currently has, where `*arguments` can only have 2 or 3 entries and the first means `numNotesActual: int`, the second `numNotesNormal: int`, and the third `durationActual: str|DurationTuple`. These can be normal arguments which can be specified by position or keyword.\n", + "8. When `*arguments` are used properly (like in Chord) the variable name should reflect the type of thing expected, e.g., `*notes`. (Or in the case of Chord which can also take a list of notes, `(self, noteListOrFirstNote, *remainingNotes)` )\n", + "9. Use positional-only arguments only when there is a variable type argument like \"noteOrStringOrListOfNotes\" which you'd rather that users not specify by keyword, AND there are keyword alternates like `n=..., s=..., nList=...` so that people can specify what they are putting in. Interval() has been refactored to use positional-only arguments. In general, do not use positional-only arguments.\n", + "10. Document all arguments in the docstring. Arguments that become stored in attributes (not properties) should be documented and tested in `_DOC_ATTR = {}`. Those that are manipulated and not stored directly should be tested in the docstring or unittests.\n" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Finally ##\n", + "\n", + "If you're looking for ways to get started, browse the issues board, the Coveralls module\n", + "coverage, or the TODO stubs in an area of the code that interests you.\n", + "Thanks for your interest in contributing to `music21`. We look forward to seeing your work!\n", + "\n", + "(Note that Cuthbert, the principal maintainer of `music21` is on sabbatical from the project until at least January 2024 (but not longer than July 2024, and for the moment, new requests are not being actively reviewed).\n" + ], + "metadata": { + "collapsed": false + } + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/documentation/source/developerReference/index.rst b/documentation/source/developerReference/index.rst index 72d94644af..d2ced98987 100644 --- a/documentation/source/developerReference/index.rst +++ b/documentation/source/developerReference/index.rst @@ -4,6 +4,7 @@ Developer Reference .. toctree:: :maxdepth: 2 + developerGuidelines testing documenting buildingDocumentation diff --git a/music21/common/stringTools.py b/music21/common/stringTools.py index 8e18a12d3a..f32a0a341a 100644 --- a/music21/common/stringTools.py +++ b/music21/common/stringTools.py @@ -419,6 +419,7 @@ def parenthesesMatch( ValueError: Closing '")' without 'Pitch("' at index 59. So to do something like this, you might need to get creative: + >>> out = common.stringTools.parenthesesMatch(st, open='("', close='")') >>> out [ParenthesesMatch(start=8, end=10, text='C4', nested=[]), diff --git a/music21/figuredBass/notation.py b/music21/figuredBass/notation.py index 51fdb43dfd..2003a19403 100644 --- a/music21/figuredBass/notation.py +++ b/music21/figuredBass/notation.py @@ -509,10 +509,6 @@ class Figure(prebase.ProtoM21Object): A bool value that indicates whether an extender is part of the figure. It is set by a keyword argument. ''', - 'isPureExtender': ''' - A bool value that returns true if an extender is part of the figure but no number - is given. It is set on the fly by evaluating the number and extender arguments. - ''' } def __init__(