Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Matrix #75

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .github/workflows/docs-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,19 @@ jobs:
cache: "pip"
cache-dependency-path: |
pyproject.toml
requirements-dev.txt

- name: Install dependencies
- name: Install hatch
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
pip install hatch

- name: Test building documentation
run: |
make docs
hatch run docs:build

- name: Deploy docs to gh-pages
working-directory: docs
run: |
git fetch origin gh-pages --depth=1
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
mike deploy --push ~latest --title=latest
hatch run docs:mike deploy --push ~latest --title=latest
11 changes: 5 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,19 @@ jobs:
cache: "pip"
cache-dependency-path: |
pyproject.toml
requirements-dev.txt

- name: Install dependencies
- name: Install hatch
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
pip install hatch

- name: Check that versions match
id: version
run: |
echo "Release tag: [${{ github.event.release.tag_name }}]"
PACKAGE_VERSION=$(python -c "import reprexlite; print(reprexlite.__version__)")
PACKAGE_VERSION=$(hatch project metadata | jq -r .version)
echo "Package version: [$PACKAGE_VERSION]"
[ ${{ github.event.release.tag_name }} == "v$PACKAGE_VERSION" ] || { exit 1; }
echo "::set-output name=major_minor_version::v${PACKAGE_VERSION%.*}"
echo "major_minor_version=v${PACKAGE_VERSION%.*}" >> $GITHUB_OUTPUT

- name: Build package
run: |
Expand All @@ -61,6 +59,7 @@ jobs:
git fetch origin gh-pages --depth=1
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
hatch shell docs
# Rename old stable version
mike list -j | jq
OLD_STABLE=$(mike list -j | jq -r '.[] | select(.aliases | index("stable")) | .title' | awk '{print $1;}')
Expand Down
38 changes: 24 additions & 14 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,37 @@ jobs:
cache: "pip"
cache-dependency-path: |
pyproject.toml
requirements-dev.txt

- name: Install dependencies
- name: Install hatch
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
pip install hatch

- name: Lint package
run: |
make lint
make typecheck
hatch run lint:lint

tests:
name: "Tests (${{ matrix.os }}, Python ${{ matrix.python-version }})"
name: "Tests (${{ matrix.os }}, Python ${{ matrix.python-version }}, Extra ${{ matrix.extra }})"
needs: code-quality
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.7, 3.8, 3.9, "3.10", "3.11"]
extra: [""]
include:
- os: ubuntu-latest
python-version: "3.10"
extra: "-black"
- os: ubuntu-latest
python-version: "3.10"
extra: "-ipython"
- os: ubuntu-latest
python-version: "3.10"
extra: "-pygments"
- os: ubuntu-latest
python-version: "3.10"
extra: "-rich"

steps:
- uses: actions/checkout@v3
Expand All @@ -54,28 +65,27 @@ jobs:
cache: "pip"
cache-dependency-path: |
pyproject.toml
requirements-dev.txt

- name: Install dependencies
- name: Install hatch
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
pip install hatch

- name: Run tests
run: |
make test
hatch run tests.py${{ matrix.python-version }}${{ matrix.extra }}:run-cov

- name: Upload coverage to codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.xml
fail_ci_if_error: true
if: ${{ matrix.os == 'ubuntu-latest' }}

- name: Build distribution and test installation
shell: bash
run: |
make dist
hatch build
if [[ ${{ matrix.os }} == "windows-latest" ]]; then
PYTHON_BIN=Scripts/python
else
Expand All @@ -94,7 +104,7 @@ jobs:

- name: Test building documentation
run: |
make docs
hatch run docs:build
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10'

- name: Deploy site preview to Netlify
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ This release involves major changes to reprexlite. There is a significant refact
#### Changed

- Changed formatting abstractions in `reprexlite.formatting` module.
- Rather than `*Reprex` classes that encapsulate reprex data, we now have `*Formatter` classes and take a rendered reprex output string as input to a `format` class method that appropriately prepares the reprex output for a venue, such as adding venue-specific markup.
- Rather than `*Reprex` classes that encapsulate reprex data, we now have simple formatter callables that take a rendered reprex output string as input and appropriately prepares the reprex output for a venue, such as adding venue-specific markup.
- The `venues_dispatcher` dictionary in `reprexlite.formatting` is now a `formatter_registry` dictionary.
- Formatters are added to the registry using a `register_formatter` decorator instead of being hard-coded.

Expand Down
42 changes: 42 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Contributing to reprexlite

[![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch)
[![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v0.json)](https://github.com/charliermarsh/ruff)
[![code style - black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![types - mypy](https://img.shields.io/badge/types-mypy-blue.svg)](https://github.com/python/mypy)

## Report a bug or request a feature

Please file an issue in the [issue tracker](https://github.com/jayqi/reprexlite/issues).

## Standalone tests

To run tests in your current environment, you should install from source with the `tests` extra to additionally install test dependencies. Then, use pytest to run the tests.

```bash
# Install with test dependencies
pip install .[tests]
# Run tests
pytest tests.py
```

## Developers guide

This project uses [Hatch](https://github.com/pypa/hatch) as its project management tool. The default environment includes dependencies for linting as well as all extra dependencies.

### Linting

To run linting or typechecking from the default environment:

```bash
hatch run lint
hatch run typecheck
```

### Tests

To run tests on the full test matrix, use the Hatch command:

```bash
hatch run tests:run
```
94 changes: 90 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "reprexlite"
Expand Down Expand Up @@ -31,8 +31,10 @@ dependencies = [

[project.optional-dependencies]
black = ["black"]
pygments = ["Pygments"]
ipython = ["ipython"]
pygments = ["Pygments"]
rich = ["rich"]
tests = ["pytest"]

[project.scripts]
reprex = "reprexlite.cli:app"
Expand All @@ -43,6 +45,91 @@ reprex = "reprexlite.cli:app"
"Bug Tracker" = "https://github.com/jayqi/reprexlite/issues"
"Changelog" = "https://jayqi.github.io/reprexlite/stable/changelog/"

[tool.hatch.build]
exclude = ["docs/"]

## DEFAULT ENVIRONMENT ##

[tool.hatch.envs.default]
features = ["black", "pygments", "ipython", "rich", "tests"]
dependencies = [
"tqdm", # For script to regenerate test assets
]
path = ".venv"
template = "lint"

## LINTING ENVIRONMENT ##
[tool.hatch.envs.lint]
dependencies = ["black", "mypy", "ruff"]
python = "3.10"
detached = true

[tool.hatch.envs.lint.scripts]
lint = ["black --check reprexlite tests", "ruff check reprexlite tests"]
typecheck = ["mypy reprexlite --install-types --non-interactive"]

## TESTS ENVIRONMENTS ##

[tool.hatch.envs.tests]
features = ["tests"]
dependencies = ["coverage", "pytest-cov"]
template = "tests"

[[tool.hatch.envs.tests.matrix]]
python = ["3.7", "3.8", "3.9", "3.10", "3.11"]

[[tool.hatch.envs.tests.matrix]]
python = ["3.10"]
extras = ["black", "ipython", "pygments", "rich"]

[tool.hatch.envs.tests.overrides]
matrix.extras.features = [
{ value = "black", if = [
"black",
] },
{ value = "ipython", if = [
"ipython",
] },
{ value = "pygments", if = [
"pygments",
] },
{ value = "rich", if = [
"rich",
] },
]

[tool.hatch.envs.tests.scripts]
run = "pytest tests"
run-cov = "run --cov=reprexlite --cov-report=term --cov-report=html --cov-report=xml"
run-debug = "run --pdb"


## DOCS ENVIRONMENT ##

[tool.hatch.envs.docs]
dependencies = [
"mkdocs",
"mkdocs-jupyter",
"mkdocs-macros-plugin",
"mkdocs-material",
"mike",
"mkdocstrings[python]",
"mdx-truly-sane-lists",
"py-markdown-table==0.3.3",
"typenames",
]
template = "docs"

[tool.hatch.envs.docs.scripts]
build = [
"rm -rf docs/site/",
"cp README.md docs/docs/index.md",
"cp CHANGELOG.md docs/docs/changelog.md",
"cd docs && mkdocs build",
]


## TOOLS ##

[tool.black]
line-length = 99
Expand Down Expand Up @@ -81,7 +168,6 @@ ignore_missing_imports = true

[tool.pytest.ini_options]
minversion = "6.0"
addopts = "--cov=reprexlite --cov-report=term --cov-report=html --cov-report=xml"
testpaths = ["tests"]

[tool.coverage.run]
Expand Down
16 changes: 14 additions & 2 deletions reprexlite/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@

import typer

try:
from rich.console import Console

console = Console(soft_wrap=True)
print = console.print
except ModuleNotFoundError as e:
if e.name == "rich":
pass
else:
raise # pragma: no cover


from reprexlite.config import ParsingMethod, ReprexConfig
from reprexlite.exceptions import InputSyntaxError, IPythonNotFoundError
from reprexlite.formatting import formatter_registry
Expand Down Expand Up @@ -172,10 +184,10 @@ def main(

if outfile:
with outfile.open("w") as fp:
fp.write(r.format(terminal=False))
fp.write(r.format())
print(f"Wrote rendered reprex to {outfile}")
else:
print(r.format(terminal=True), end="")
r.print(end="")

return r

Expand Down
9 changes: 9 additions & 0 deletions reprexlite/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ class ReprexConfig:
formatting.
"""

# Editor
editor: Optional[str] = field(default=None, metadata={"help": "..."})
no_color: bool = field(
default=False,
metadata={
"help": ("If True, will disable the colored text output when printing to stdout.")
},
)

# Formatting
venue: str = field(
default="gh",
Expand Down
12 changes: 4 additions & 8 deletions reprexlite/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,10 @@ class IPythonNotFoundError(ModuleNotFoundError, ReprexliteException):
"""Raised when ipython cannot be found when using an IPython-dependent feature."""


class MissingDependencyError(ImportError, ReprexliteException):
pass


class NoPrefixMatchError(ValueError, ReprexliteException):
pass


class NotAFormatterError(TypeError, ReprexliteException):
"""Raised when registering a formatter that is not a subclass of the Formatter base class."""


class PromptLengthMismatchError(ReprexliteException):
pass

Expand All @@ -46,6 +38,10 @@ class PygmentsNotFoundError(ModuleNotFoundError, ReprexliteException):
"""Raised when pygments cannot be found when using a pygments-dependent feature."""


class RichNotFoundError(ModuleNotFoundError, ReprexliteException):
"""Raised when rich cannot be found when using a rich-dependent feature."""


class UnexpectedError(ReprexliteException):
"""Raised when an unexpected case happens."""

Expand Down
Loading