> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/nvaccess/nvda/llms.txt
> Use this file to discover all available pages before exploring further.

# Code Standards

> Coding style guidelines and standards for NVDA development

NVDA follows specific coding standards to ensure consistency and maintainability across the codebase. Authors should do their best to adhere to these standards to have the best chance of their contribution being accepted.

<Note>
  In limited circumstances, NV Access may accept contributions that do not follow these coding standards. If you're unable to follow these standards, please make note of this when opening your PR.
</Note>

## General Guidelines

In general, Python contributions to NVDA should follow the [PEP 8 style guide](https://peps.python.org/pep-0008/), except where it contradicts the specific guidance below.

Python code style is enforced with the Ruff linter. See [linting your changes](/development/testing#linting-your-changes) for more information.

## Encoding

* **Python files** should be encoded in UTF-8
* **Text files** should be committed with `LF` line endings
* Files can be checked out locally using CRLF if needed for Windows development using [git's core.autocrlf setting](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_core_autocrlf)

## Indentation

<Warning>
  Indentation must be done with tabs (one per level), not spaces.
</Warning>

* When splitting a single statement over multiple lines, just indent one or more additional levels
* Don't use vertical alignment (lining up with the bracket on the previous line)
* This requires a new-line after an opening parenthesis/bracket/brace if you intend to split the statement over multiple lines

## Identifier Names

### Use Descriptive Names

* Name constants to avoid "magic numbers" and hint at intent or origin of the value
* Consider: what does this represent?

### Functions, Variables, Properties

Use mixed case to separate words, starting with a lower case letter:

```python theme={null}
speakText
brailleHandler
currentFocusObject
```

### Boolean Functions or Variables

* Use the positive form of the language (avoid double negatives like `shouldNotDoSomething = False`)
* Start with a "question word" to hint at their boolean nature

```python theme={null}
shouldSpeak
isEnabled
hasChildren
```

### Classes

Use mixed case to separate words, starting with an upper case letter:

```python theme={null}
BrailleHandler
TextInfo
NVDAObject
```

### Constants

All upper case, separating words with underscores:

```python theme={null}
LANGS_WITH_CONJUNCT_CHARS
MAX_BUFFER_SIZE
DEFAULT_TIMEOUT
```

### Scripts

Scripts (the targets of gestures) are prefixed with `script_`, with subsequent words in camel case:

```python theme={null}
script_cycleAudioDuckingMode
script_reportCurrentLine
```

### Event Handlers

Prefixed with `event_`, with subsequent words in camel case. Note that `object` and `action` are separated by underscores:

```python theme={null}
event_gainFocus
event_caret
event_appModule_gainFocus
```

Where `object` refers to the class type that the `action` refers to.

### Extension Points

**Action:**

* Prefixed with `pre_` or `post_` to specify that handlers are notified before/after the action

**Decider:**

* Prefixed with `should_` to turn them into a question
* Example: `should_doSomething`

**Filter:**

* Prefixed with `filter_`
* Should describe the filtering action and the data being returned
* Should communicate if filtering happens before or after some action
* Example: `filter_displaySize_preRefresh`

### Enums

Formatted using the expected mix of the above:

```python theme={null}
class ExampleGroupOfData(Enum):
    CONSTANT_VALUE_MEMBER = auto()
    
    @property
    def _formatMember(self):
        pass
```

## Translatable Strings

All strings that could be presented to the user should be marked as translatable using the `_()` function:

```python theme={null}
# Translators: The name of a category of NVDA commands.
SCRCAT_TEXTREVIEW = _("Text review")
```

<Warning>
  All translatable strings must have a preceding translators comment describing the purpose of the string.
</Warning>

### Multi-line Translatable Strings

Lengthy strings can be split across multiple lines using Python's implicit line joining inside parentheses:

```python theme={null}
self.copySettingsButton = wx.Button(
    self,
    label=_(
        # Translators: The label for a button in general settings to copy
        # current user settings to system settings (to allow current
        # settings to be used in secure screens such as User Account
        # Control (UAC) dialog).
        "Use currently saved settings during sign-in and on secure screens"
        " (requires administrator privileges)"
    )
)
```

## Imports

* Unused imports should be removed where possible
* Anything imported into a (sub)module can also be imported from that submodule
* Removing unused imports may break compatibility and should be done in compatibility breaking releases

### Handling Unused Import Warnings

Unused imports will give a lint warning. Handle them in these ways:

1. **If imports are intended for re-export:** Include them in `__all__` definition
   ```python theme={null}
   __all__ = ["SomeClass", "someFunction"]
   ```

2. **Otherwise:** Add a comment like `# noqa: <explanation>`

## Considering Future Backwards Compatibility

When writing new code, consider how it can be moved in future while retaining backwards compatibility. See [deprecations documentation](https://github.com/nvaccess/nvda/blob/master/projectDocs/dev/deprecations.md) for limitations.

<Tip>
  **Summary:**

  * Avoid module level global variables
  * Any module level variables should be prefixed with underscore and encapsulated via getters/setters
  * Avoid code which executes at import time - use initializer functions instead
</Tip>

## Docstrings

Docstrings should use [Sphinx format without types](https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html) and follow [PEP 257 conventions](https://peps.python.org/pep-0257/).

### When to Use Docstrings

* **All** public functions, classes, and methods should have docstrings
* **Most** internal functions, classes and methods should have docstrings, except where their purpose is clear from their name or code
* A function of more than a few lines of code is most likely not self-explanatory

### Guidelines

* Providing type information in docstrings is discouraged - use [type annotations](#type-hints) instead
* Class-level and module-level docstrings should contain:
  * High-level overview
  * Optionally: usage examples and references to commonly used methods/functions and attributes
* Document class constructors in `__init__`, not at the top of the class
* Document class attributes and non-obvious public variables in a docstring immediately below the attribute

<Note>
  NVDA formerly used [epytext](https://epydoc.sourceforge.net/manual-epytext.html) syntax for docstrings, which means there is inconsistent syntax in the codebase. [Issue #12971](https://github.com/nvaccess/nvda/issues/12971) tracks converting epytext docstrings to Sphinx.
</Note>

### Learning Resources

* [reStructuredText Primer from Sphinx docs](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html)
* [reStructuredText markup from Python Developer's Guide](https://devguide.python.org/documentation/markup/)
* [Sphinx's custom reStructuredText Directives](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html)
* [Sphinx's Python Domain](https://www.sphinx-doc.org/en/master/usage/domains/python.html)

## Type Hints

<Warning>
  All new code contributions to NVDA should use [PEP 484-style type hints](https://peps.python.org/pep-0484/).
</Warning>

Type hints make reasoning about code much easier and allow static analysis tools to catch common errors.

### Requirements

* All variables, attributes, properties, and function/method arguments and returns should have type hints
* No need to provide type hints for `self` or `cls` arguments to object/class methods
* Prefer union shorthand (`X | Y`) over explicitly using `typing.Union`
* Corollary: prefer `T | None` over `typing.Optional[T]`

### Example

```python theme={null}
def speakText(
    text: str,
    priority: SpeechPriority = SpeechPriority.NORMAL,
    symbolLevel: int | None = None
) -> None:
    """Speak the given text with specified priority."""
    pass
```

## Calling Non-Python Code

When using parts of the Windows API or parts of NVDA implemented in C++, use the [ctypes](https://docs.python.org/3/library/ctypes.html) library.

### Naming Conventions

<Tip>
  When providing ctypes type information for foreign functions, structures and data types, prefer to use the same name as used in the external library.
</Tip>

* Example: `GetModuleFileName` not `getModuleFileName`
* Pythonic names should be reserved for wrappers that provide more pythonic access to functions

### Organization

* **Windows API functions:** Define in the `winBindings` package in modules named according to the DLL
  * Example: `winBindings.kernel32`
* **nvdaHelper ctypes code:** Define in the `NVDAHelper.localLib` module

## Language Choices

The NVDA community is large and diverse. We have a responsibility to make everyone feel welcome. As our [contributor code of conduct](https://github.com/nvaccess/nvda/blob/master/CODE_OF_CONDUCT.md) states:

> Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.

<Warning>
  The wording choices we make have power. Avoid language that negatively impacts others.
</Warning>

### Guidelines

* Avoid metaphors, euphemisms or other language with layers of meaning or negative history
* Avoid generalisations about people, cultures or countries
* Avoid ableist language
* Use gender-inclusive terminology

### Examples of Preferred Terms

| Instead of                  | Use                              |
| --------------------------- | -------------------------------- |
| master/slave                | leader/follower, primary/replica |
| blacklist/whitelist         | blocklist/allowlist              |
| sanity check                | confidence check                 |
| dummy (value)               | placeholder                      |
| he/him/his (unknown gender) | they/them/theirs                 |

## Running Code Style Checks

To check your code against these standards:

```bash theme={null}
# Run linting checks
runlint.bat

# Check translatable strings
runcheckpot.bat

# Check licenses
runlicensecheck.bat
```

Integrate Ruff and pyright with your IDE to catch issues faster during development.
