Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderchang1 authored Dec 25, 2024
2 parents 33d2591 + 5654389 commit 222c101
Show file tree
Hide file tree
Showing 124 changed files with 3,284 additions and 1,845 deletions.
6 changes: 3 additions & 3 deletions .azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ jobs:
vmImage: 'ubuntu-22.04'
strategy:
matrix:
Python3.9:
python.version: '3.9'
Python3.10:
python.version: '3.10'
Python3.12: {}
minimal_dependencies:
TEST_EXTRA: 'test-min'
anndata_dev:
DEPENDENCIES_VERSION: "pre-release"
TEST_TYPE: "coverage"
minimum_versions:
python.version: '3.9'
python.version: '3.10'
DEPENDENCIES_VERSION: "minimum-version"
TEST_TYPE: "coverage"

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: Bug report
description: Scanpy doesn’t do what it should? Please help us fix it!
#title: ...
type: Bug
labels:
- Bug 🐛
- Triage 🩺
#assignees: []
body:
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
blank_issues_enabled: true
blank_issues_enabled: false
contact_links:
- name: Scanpy Community Forum
url: https://discourse.scverse.org/
Expand Down
3 changes: 2 additions & 1 deletion .github/ISSUE_TEMPLATE/enhancement-request.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: Enhancement request
description: Anything you’d like to see in scanpy?
#title: ...
type: Enhancement
labels:
- Enhancement ✨
- Triage 🩺
#assignees: []
body:
Expand All @@ -14,6 +14,7 @@ body:
- 'Additional function parameters / changed functionality / changed defaults?'
- 'New analysis tool: A simple analysis tool you have been using and are missing in `sc.tools`?'
- 'New plotting function: A kind of plot you would like to seein `sc.pl`?'
- 'Improved documentation or error message?'
- 'Other?'
validations:
required: true
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ jobs:
key: benchmark-state-${{ hashFiles('benchmarks/**') }}

- name: Install dependencies
# TODO: revert once this PR is merged: https://github.com/airspeed-velocity/asv/pull/1397
run: pip install 'asv @ git+https://github.com/ivirshup/asv@fix-conda-usage'
run: pip install 'asv>=0.6.4'

- name: Configure ASV
working-directory: ${{ env.ASV_DIR }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
# Python build files
__pycache__/
/src/scanpy/_version.py
/ci/scanpy-min-deps.txt
/dist/
/*-env/
/env-*/
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.8
rev: v0.8.2
hooks:
- id: ruff
types_or: [python, pyi, jupyter]
Expand All @@ -20,7 +20,7 @@ repos:
- --sort-by-bibkey
- --drop=abstract
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: trailing-whitespace
exclude: tests/_data
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/asv.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@

// The Pythons you'd like to test against. If not provided, defaults
// to the current version of Python used to run `asv`.
// "pythons": ["3.9", "3.12"],
// "pythons": ["3.10", "3.12"],

// The list of conda channel names to be searched for benchmark
// dependency packages in the specified order
Expand Down
7 changes: 4 additions & 3 deletions benchmarks/benchmarks/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@
import scanpy as sc

if TYPE_CHECKING:
from collections.abc import Callable, Sequence, Set
from collections.abc import Callable, Sequence
from collections.abc import Set as AbstractSet
from typing import Literal, Protocol, TypeVar

from anndata import AnnData

C = TypeVar("C", bound=Callable)

class ParamSkipper(Protocol):
def __call__(self, **skipped: Set) -> Callable[[C], C]: ...
def __call__(self, **skipped: AbstractSet) -> Callable[[C], C]: ...

Dataset = Literal["pbmc68k_reduced", "pbmc3k", "bmmc", "lung93k"]
KeyX = Literal[None, "off-axis"]
Expand Down Expand Up @@ -195,7 +196,7 @@ def param_skipper(
b 5
"""

def skip(**skipped: Set) -> Callable[[C], C]:
def skip(**skipped: AbstractSet) -> Callable[[C], C]:
skipped_combs = [
tuple(record.values())
for record in (
Expand Down
126 changes: 99 additions & 27 deletions ci/scripts/min-deps.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
#!/usr/bin/env python3
# /// script
# dependencies = [
# "tomli; python_version < '3.11'",
# "packaging",
# ]
# ///

from __future__ import annotations

import argparse
import sys
from collections import deque
from contextlib import ExitStack
from functools import cached_property
from pathlib import Path
from typing import TYPE_CHECKING

Expand All @@ -16,7 +25,9 @@
from packaging.version import Version

if TYPE_CHECKING:
from collections.abc import Generator, Iterable
from collections.abc import Generator, Iterable, Sequence
from collections.abc import Set as AbstractSet
from typing import Any, Self


def min_dep(req: Requirement) -> Requirement:
Expand All @@ -27,18 +38,21 @@ def min_dep(req: Requirement) -> Requirement:
-------
>>> min_dep(Requirement("numpy>=1.0"))
"numpy==1.0"
<Requirement('numpy==1.0.*')>
"""
req_name = req.name
if req.extras:
req_name = f"{req_name}[{','.join(req.extras)}]"

if not req.specifier:
filter_specs = [
spec for spec in req.specifier if spec.operator in {"==", "~=", ">=", ">"}
]
if not filter_specs:
return Requirement(req_name)

min_version = Version("0.0.0.a1")
for spec in req.specifier:
if spec.operator in [">", ">=", "~="]:
for spec in filter_specs:
if spec.operator in {">", ">=", "~="}:
min_version = max(min_version, Version(spec.version))
elif spec.operator == "==":
min_version = Version(spec.version)
Expand All @@ -65,34 +79,92 @@ def extract_min_deps(
yield min_dep(req)


def main():
parser = argparse.ArgumentParser(
prog="min-deps",
description="""Parse a pyproject.toml file and output a list of minimum dependencies.
Output is directly passable to `pip install`.""",
usage="pip install `python min-deps.py pyproject.toml`",
)
parser.add_argument(
"path", type=Path, help="pyproject.toml to parse minimum dependencies from"
)
parser.add_argument(
"--extras", type=str, nargs="*", default=(), help="extras to install"
)

args = parser.parse_args()

pyproject = tomllib.loads(args.path.read_text())
class Args(argparse.Namespace):
"""\
Parse a pyproject.toml file and output a list of minimum dependencies.
Output is optimized for `[uv] pip install` (see `-o`/`--output` for details).
"""

project_name = pyproject["project"]["name"]
_path: Path
output: Path | None
_extras: list[str]
_all_extras: bool

@classmethod
def parse(cls, argv: Sequence[str] | None = None) -> Self:
return cls.parser().parse_args(argv, cls())

@classmethod
def parser(cls) -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="min-deps",
description=cls.__doc__,
usage="pip install `python min-deps.py pyproject.toml`",
)
parser.add_argument(
"_path",
metavar="pyproject.toml",
type=Path,
help="Path to pyproject.toml to parse minimum dependencies from",
)
parser.add_argument(
"--extras",
dest="_extras",
metavar="EXTRA",
type=str,
nargs="*",
default=(),
help="extras to install",
)
parser.add_argument(
"--all-extras",
dest="_all_extras",
action="store_true",
help="get all extras",
)
parser.add_argument(
*("--output", "-o"),
metavar="FILE",
type=Path,
default=None,
help=(
"output file (default: stdout). "
"Without this option, output is space-separated for direct passing to `pip install`. "
"With this option, output written to a file newline-separated file usable as `requirements.txt` or `constraints.txt`."
),
)
return parser

@cached_property
def pyproject(self) -> dict[str, Any]:
return tomllib.loads(self._path.read_text())

@cached_property
def extras(self) -> AbstractSet[str]:
if self._extras:
if self._all_extras:
sys.exit("Cannot specify both --extras and --all-extras")
return dict.fromkeys(self._extras).keys()
if not self._all_extras:
return set()
return self.pyproject["project"]["optional-dependencies"].keys()


def main(argv: Sequence[str] | None = None) -> None:
args = Args.parse(argv)

project_name = args.pyproject["project"]["name"]
deps = [
*map(Requirement, pyproject["project"]["dependencies"]),
*map(Requirement, args.pyproject["project"]["dependencies"]),
*(Requirement(f"{project_name}[{extra}]") for extra in args.extras),
]

min_deps = extract_min_deps(deps, pyproject=pyproject)
min_deps = extract_min_deps(deps, pyproject=args.pyproject)

print(" ".join(map(str, min_deps)))
sep = "\n" if args.output else " "
with ExitStack() as stack:
f = stack.enter_context(args.output.open("w")) if args.output else sys.stdout
print(sep.join(map(str, min_deps)), file=f)


if __name__ == "__main__":
Expand Down
14 changes: 10 additions & 4 deletions ci/scripts/towncrier_automation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#!/usr/bin/env python3
# /// script
# dependencies = [ "towncrier", "packaging" ]
# ///

from __future__ import annotations

import argparse
Expand Down Expand Up @@ -62,9 +66,7 @@ def main(argv: Sequence[str] | None = None) -> None:
text=True,
check=True,
).stdout.strip()
pr_description = (
"" if base_branch == "main" else "@meeseeksmachine backport to main"
)
pr_description = "" if base_branch == "main" else "@meeseeksdev backport to main"
branch_name = f"release_notes_{args.version}"

# Create a new branch + commit
Expand All @@ -90,7 +92,11 @@ def main(argv: Sequence[str] | None = None) -> None:
f"--base={base_branch}",
f"--title={pr_title}",
f"--body={pr_description}",
*(["--label=no milestone"] if base_branch == "main" else []),
*(
["--label=no milestone", "--label=Development Process 🚀"]
if base_branch == "main"
else []
),
*(["--dry-run"] if args.dry_run else []),
],
check=True,
Expand Down
1 change: 1 addition & 0 deletions docs/api/deprecated.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
pp.filter_genes_dispersion
pp.normalize_per_cell
pp.subsample
```
2 changes: 1 addition & 1 deletion docs/api/preprocessing.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ For visual quality control, see {func}`~scanpy.pl.highest_expr_genes` and
pp.normalize_total
pp.regress_out
pp.scale
pp.subsample
pp.sample
pp.downsample_counts
```

Expand Down
2 changes: 2 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@
rapids_singlecell=("https://rapids-singlecell.readthedocs.io/en/latest/", None),
scipy=("https://docs.scipy.org/doc/scipy/", None),
seaborn=("https://seaborn.pydata.org/", None),
session_info2=("https://session-info2.readthedocs.io/en/stable/", None),
squidpy=("https://squidpy.readthedocs.io/en/stable/", None),
sklearn=("https://scikit-learn.org/stable/", None),
)

Expand Down
17 changes: 17 additions & 0 deletions docs/release-notes/1.10.4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
(v1.10.4)=
### 1.10.4 {small}`2024-11-12`

### Breaking changes

- Remove Python 3.9 support {smaller}`P Angerer` ({pr}`3283`)

### Bug fixes

- Fix {meth}`scanpy.pl.DotPlot.style`, {meth}`scanpy.pl.MatrixPlot.style`, and {meth}`scanpy.pl.StackedViolin.style` resetting all non-specified parameters {smaller}`P Angerer` ({pr}`3206`)
- Accept `'group'` instead of `'obs'` for `standard_scale` parameter in {func}`~scanpy.pl.stacked_violin` {smaller}`P Angerer` ({pr}`3243`)
- Use `density_norm` instead of of `scale` (cont. from {pr}`2844`) in {func}`~scanpy.pl.violin` and {func}`~scanpy.pl.stacked_violin` {smaller}`P Angerer` ({pr}`3244`)
- Switched all compatibility adapters for positional parameters to {exc}`FutureWarning` {smaller}`P Angerer` ({pr}`3264`)
- Catch `PerfectSeparationWarning` during {func}`~scanpy.pp.regress_out` {smaller}`J Wagner` ({pr}`3275`)
- Fix {func}`scanpy.pp.highly_variable_genes` for batches of size 1 {smaller}`P Angerer` ({pr}`3286`)
- Fix {func}`scanpy.pl.scatter`’s `color` parameter to take collections as advertised {smaller}`P Angerer` ({pr}`3299`)
- Fix {func}`scanpy.pl.highest_expr_genes` when used with a categorical gene symbol column {smaller}`P Angerer` ({pr}`3302`)
Loading

0 comments on commit 222c101

Please sign in to comment.