Skip to content

Commit

Permalink
feat: simplify how the BedReader and BedWriter work
Browse files Browse the repository at this point in the history
  • Loading branch information
clintval committed Nov 6, 2024
1 parent 80fafdc commit 767833b
Show file tree
Hide file tree
Showing 17 changed files with 1,009 additions and 1,071 deletions.
23 changes: 9 additions & 14 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: tests
name: Code checks

on:
push:
Expand All @@ -9,15 +9,14 @@ on:
workflow_call:

env:
POETRY_VERSION: 1.6
POETRY_VERSION: 1.8

jobs:
unit-tests:
Tests:
runs-on: ubuntu-latest
strategy:
matrix:
PYTHON_VERSION: ["3.12"]

steps:
- uses: actions/checkout@v4
with:
Expand All @@ -35,12 +34,8 @@ jobs:

- name: Install poetry
run: |
python -m pip install --upgrade pip
python -m pip install poetry==${{env.POETRY_VERSION}}
- name: Configure poetry
shell: bash
run: poetry config virtualenvs.in-project true
python -m pip install --upgrade pipx
pipx install poetry==${{env.POETRY_VERSION}}
- name: Set up cache
uses: actions/cache@v4
Expand All @@ -54,11 +49,11 @@ jobs:
shell: bash
run: poetry run pip --version >/dev/null 2>&1 || rm -rf .venv

- name: Test the lock file is up to date
run: python -m poetry check --lock

- name: Install the library
run: poetry install -v

- name: Install the task runner poethepoet
run: poetry self add 'poethepoet[poetry_plugin]'

- name: Test the library
run: poetry run pytest
run: poetry task check-all
89 changes: 72 additions & 17 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,94 @@
# Development and Testing

## Local Installation
## Primary Development Commands

First install the Python packaging and dependency management tool [`poetry`](https://python-poetry.org/docs/#installation).
You must have Python 3.12 or greater available on your system path, which could be managed by [`pyenv`](https://github.com/pyenv/pyenv) or another package manager.
Finally, install the dependencies of the project with:
To check and resolve linting issues in the codebase, run:

```console
poetry install
poetry run ruff check --fix
```

## Running Tests
To check and resolve formatting issues in the codebase, run:

To test the codebase, run the following command:
```console
poetry run ruff format
```

To check the unit tests in the codebase, run:

```console
poetry run pytest
```

The command will:
To check the typing in the codebase, run:

- Execute unit tests with [`pytest`](https://docs.pytest.org/)
- Test the language typing with [`mypy`](https://mypy-lang.org/)
- Test for linting and styling errors with [`ruff`](https://docs.astral.sh/ruff/)
- Emit a testing coverage report with [`coverage`](https://coverage.readthedocs.io/)
```console
poetry run mypy
```

To format the code in the library, run the following commands:
To generate a code coverage report after testing locally, run:

```console
poetry run ruff check --select I --fix
poetry run ruff format bedspec tests
poetry run coverage html
```

To generate a code coverage report locally, run the following command:
To check the lock file is up to date:

```console
poetry run coverage html
poetry check --lock
```

## Shortcut Task Commands

To be able to run shortcut task commands, first install the Poetry plugin [`poethepoet`](https://poethepoet.natn.io/index.html):

```console
poetry self add 'poethepoet[poetry_plugin]'
```

> [!NOTE]
> Upon the release of Poetry [v2.0.0](https://github.com/orgs/python-poetry/discussions/9793#discussioncomment-11043205), Poetry will automatically support bootstrap installation of [project-specific plugins](https://github.com/python-poetry/poetry/pull/9547) and installation of the task runner will become automatic for this project.
> The `pyproject.toml` syntax will be:
>
> ```toml
> [tool.poetry]
> requires-poetry = ">=2.0"
>
> [tool.poetry.requires-plugins]
> poethepoet = ">=0.29"
> ```
###### For Running Individual Checks
```console
poetry task check-lock
poetry task check-format
poetry task check-lint
poetry task check-tests
poetry task check-typing
```
###### For Running All Checks

```console
poetry task check-all
```

###### For Running Individual Fixes

```console
poetry task fix-format
poetry task fix-lint
```

###### For Running All Fixes

```console
poetry task fix-all
```

###### For Running All Fixes and Checks

```console
poetry task fix-and-check-all
```
43 changes: 29 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,31 @@ pip install bedspec

## Quickstart

```python
from bedspec import Bed3
bed = Bed3("chr1", start=2, end=8)
```

### Writing

```python
from bedspec import Bed3, BedWriter
from bedspec import BedWriter

with BedWriter[Bed3].from_path("test.bed") as writer:
writer.write(Bed3("chr1", start=2, end=8))
with BedWriter.from_path("test.bed") as writer:
writer.write(bed)
```

### Reading

```python
from bedspec import Bed3, BedReader
from bedspec import BedReader

with BedReader[Bed3].from_path("test.bed") as reader:
print(list(reader))
with BedReader.from_path("test.bed", Bed3) as reader:
for bed in reader:
print(bed)
```
```console
[Bed3(contig="chr1", start=2, start=8)]
Bed3(refname="chr1", start=2, start=8)
```

### BED Types
Expand All @@ -62,14 +68,23 @@ Use a fast overlap detector for any collection of interval types, including thir
from bedspec import Bed3, Bed4
from bedspec.overlap import OverlapDetector

bed1: Bed4 = Bed4(contig="chr1", start=1, end=4, name="bed1")
bed2: Bed4 = Bed4(contig="chr1", start=5, end=9, name="bed2")
bed1: Bed4 = Bed4("chr1", start=1, end=4, name="bed1")
bed2: Bed4 = Bed4("chr1", start=5, end=9, name="bed2")

detector: OverlapDetector[Bed4] = OverlapDetector([bed1, bed2])
detector = OverlapDetector[Bed4]([bed1, bed2])

assert detector.get_overlapping(Bed3(contig="chr1", start=2, 3)) == bed1
to_test: Bed3 = Bed3("chr1", start=2, end=3)

assert detector.overlaps_any(to_test) is True
```

The overlap detector supports the following operations:

- `overlapping`: return all overlapping features
- `overlaps_any`: test if any overlapping features exist
- `those_enclosed_by`: return those enclosed by the input feature
- `those_enclosing`: return those enclosing the input feature

### Create Custom BED Types

To create a custom BED record, inherit from the relevant BED-type (`PointBed`, `SimpleBed`, `PairBed`).
Expand All @@ -82,11 +97,11 @@ from dataclasses import dataclass
from bedspec import SimpleBed

@dataclass(eq=True, frozen=True)
class MyCustomBed(SimpleBed):
contig: str
class Bed3Plus1(SimpleBed):
refname: str
start: int
end: int
my_custom_field: float
my_custom_field: float | None
```

## Development and Testing
Expand Down
11 changes: 7 additions & 4 deletions bedspec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@
from ._bedspec import Bed4
from ._bedspec import Bed5
from ._bedspec import Bed6
from ._bedspec import Bed12
from ._bedspec import BedColor
from ._bedspec import BedGraph
from ._bedspec import BedLike
from ._bedspec import BedPE
from ._bedspec import BedStrand
from ._bedspec import BedType
from ._bedspec import GenomicSpan
from ._bedspec import Named
from ._bedspec import PairBed
from ._bedspec import PointBed
from ._bedspec import SimpleBed
from ._bedspec import Stranded
from ._bedspec import header
from ._bedspec import types
from ._io import BedReader
from ._io import BedWriter
from ._types import GenomicSpan
from ._types import Named
from ._types import Stranded
Loading

0 comments on commit 767833b

Please sign in to comment.