Skip to content

Commit

Permalink
Merge pull request #33 from sigma-py/up
Browse files Browse the repository at this point in the history
some updates
  • Loading branch information
nschloe authored Feb 1, 2024
2 parents 34f66c6 + f8eef40 commit ae37687
Show file tree
Hide file tree
Showing 18 changed files with 163 additions and 97 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Release

on:
release:
types: [released]

jobs:
build-upload:
name: Build and upload to PyPI
runs-on: ubuntu-latest
permissions:
id-token: write # required for pypi upload
contents: read # required for checkout

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Build stubs
run: |
pip install mypy
stubgen --include-docstrings src/ -o src/
- name: Build wheels
run: |
pip install build
python3 -m build --wheel
- name: Upload to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
18 changes: 10 additions & 8 deletions .github/workflows/ci.yml → .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,28 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/checkout@v4
- name: Run pre-commit
uses: pre-commit/action@v2.0.3
uses: pre-commit/action@v3.0.0

build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.12"]
steps:
- uses: actions/setup-python@v2
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- uses: actions/checkout@v2
allow-prereleases: true

- uses: actions/checkout@v4

- name: Test with tox
run: |
pip install tox
tox -- --cov npx --cov-report xml --cov-report term
- name: Submit to codecov
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v4
if: ${{ matrix.python-version == '3.9' }}
27 changes: 17 additions & 10 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
repos:
- repo: https://github.com/PyCQA/isort
rev: 5.10.1
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.1.15
hooks:
- id: isort
- id: ruff

- repo: https://github.com/psf/black
rev: 22.1.0
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0
hooks:
- id: black
language_version: python3
- id: prettier

- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
hooks:
- id: flake8
- id: codespell
# args: ["-L", "sur,nd"]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
files: src
args: ["--install-types", "--non-interactive"]
21 changes: 10 additions & 11 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ appearance, race, religion, or sexual identity and orientation.
Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
- Other conduct which could reasonably be considered inappropriate in a
professional setting

## Our Responsibilities
Expand Down Expand Up @@ -74,4 +74,3 @@ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct/

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq/

2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# npx contributing guidelines

The npx community appreciates your contributions via issues and
pull requests. Note that the [code of conduct](CODE_OF_CONDUCT.md)
pull requests. Note that the [code of conduct](CODE_OF_CONDUCT.md)
applies to all interactions with the npx project, including
issues and pull requests.

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2021-2022 Nico Schlömer
Copyright 2021-present Nico Schlömer

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
[![PyPI pyversions](https://img.shields.io/pypi/pyversions/npx.svg?style=flat-square)](https://pypi.org/project/npx/)
[![GitHub stars](https://img.shields.io/github/stars/nschloe/npx.svg?style=flat-square&logo=github&label=Stars&logoColor=white)](https://github.com/nschloe/npx)
[![Downloads](https://pepy.tech/badge/npx/month?style=flat-square)](https://pepy.tech/project/npx)

<!--[![PyPi downloads](https://img.shields.io/pypi/dm/npx.svg?style=flat-square)](https://pypistats.org/packages/npx)-->

[![gh-actions](https://img.shields.io/github/workflow/status/nschloe/npx/ci?style=flat-square)](https://github.com/nschloe/npx/actions?query=workflow%3Aci)
[![codecov](https://img.shields.io/codecov/c/github/nschloe/npx.svg?style=flat-square)](https://app.codecov.io/gh/nschloe/npx)
[![LGTM](https://img.shields.io/lgtm/grade/python/github/nschloe/npx.svg?style=flat-square)](https://lgtm.com/projects/g/nschloe/npx)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black)

[NumPy](https://numpy.org/) is a large library used everywhere in scientific computing.
Expand Down Expand Up @@ -57,7 +57,7 @@ Solves a linear equation system with a matrix of shape `(n, n)` and an array of

#### `sum_at`/`add_at`

<!--pytest-codeblocks:skip-->
<!--pytest.mark.skip-->

```python
npx.sum_at(a, idx, minlength=0)
Expand All @@ -78,7 +78,6 @@ Relevant issue reports:
- [ufunc.at (and possibly other methods)
slow](https://github.com/numpy/numpy/issues/11156)


#### `unique`

```python
Expand All @@ -95,8 +94,8 @@ npx's `unique()` works just like NumPy's, except that it provides a parameter
is essentially partitioned into bins of size `tol` and at most one
representative of each bin is returned.


#### `unique_rows`

```python
import npx
import numpy as np
Expand Down
12 changes: 5 additions & 7 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
version := `python3 -c "from src.npx.__about__ import __version__; print(__version__)"`
version := `python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])"`

default:
@echo "\"just publish\"?"

publish:
@if [ "$(git rev-parse --abbrev-ref HEAD)" != "main" ]; then exit 1; fi
gh release create "v{{version}}"
flit publish

clean:
@find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
@rm -rf src/*.egg-info/ build/ dist/ .tox/
@rm -rf src/*.egg-info/ build/ dist/ .tox/ .mypy_cache/

format:
isort .
black .
ruff --fix src/ tests/
black src/ tests/
blacken-docs README.md

lint:
black --check .
flake8 .
pre-commit run --all
35 changes: 25 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"

[tool.isort]
profile = "black"
requires = ["setuptools>=61"]
build-backend = "setuptools.build_meta"

[project]
name = "npx"
version = "0.1.2"
authors = [{name = "Nico Schlömer", email = "nico.schloemer@gmail.com"}]
description = "Some useful extensions for NumPy"
readme = "README.md"
Expand All @@ -22,14 +20,31 @@ classifiers = [
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering",
"Topic :: Utilities",
]
dynamic = ["version"]
requires-python = ">=3.7"
dependencies = ["numpy >= 1.20.0"]
dependencies = [
"numpy >= 1.20.0",
# "scipy >= 1.8",
]

[project.urls]
Code = "https://github.com/nschloe/npx"
Issues = "https://github.com/nschloe/npx/issues"
Funding = "https://github.com/sponsors/nschloe"
Code = "https://github.com/sigma-py/npx"
Issues = "https://github.com/sigma-py/npx/issues"

[tool.ruff]
src = ["src", "tests"]
line-length = 88
select = ["ALL"]
ignore = [
"ANN", "S101", "D", "T201", "ERA", "N803", "PLR2004"
# "ANN", "C901", "D", "E741", "ERA", "FBT", "INP001",
# "N", "PLR", "S101", "T201", "TID252", "TD", "FIX002"
]
target-version = "py38"

[tool.mypy]
ignore_missing_imports = true
1 change: 0 additions & 1 deletion src/npx/__about__.py

This file was deleted.

2 changes: 0 additions & 2 deletions src/npx/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
from .__about__ import __version__
from ._isin import isin_rows
from ._main import add_at, dot, outer, solve, subtract_at, sum_at
from ._mean import mean
from ._unique import unique, unique_rows

__all__ = [
"__version__",
"dot",
"outer",
"solve",
Expand Down
10 changes: 6 additions & 4 deletions src/npx/_isin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ def isin_rows(a: ArrayLike, b: ArrayLike) -> np.ndarray:
a = np.asarray(a)
b = np.asarray(b)
if not np.issubdtype(a.dtype, np.integer):
raise ValueError(f"Input array must be integer type, got {a.dtype}.")
msg = f"Input array must be integer type, got {a.dtype}."
raise ValueError(msg)
if not np.issubdtype(b.dtype, np.integer):
raise ValueError(f"Input array must be integer type, got {b.dtype}.")
msg = f"Input array must be integer type, got {b.dtype}."
raise ValueError(msg)

a = a.reshape(a.shape[0], np.prod(a.shape[1:], dtype=int))
b = b.reshape(b.shape[0], np.prod(b.shape[1:], dtype=int))

a_view = np.ascontiguousarray(a).view(
np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
np.dtype((np.void, a.dtype.itemsize * a.shape[1])),
)
b_view = np.ascontiguousarray(b).view(
np.dtype((np.void, b.dtype.itemsize * b.shape[1]))
np.dtype((np.void, b.dtype.itemsize * b.shape[1])),
)

out = np.isin(a_view, b_view)
Expand Down
21 changes: 11 additions & 10 deletions src/npx/_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ def _prod(a):
return reduce(mul, a, 1)


def dot(a: np.ndarray, b: np.ndarray) -> np.ndarray:
"""Take arrays `a` and `b` and form the dot product between the last axis of `a` and
the first of `b`.
def dot(a: ArrayLike, b: np.ndarray) -> np.ndarray:
"""Take arrays `a` and `b` and form the dot product between the last axis
of `a` and the first of `b`.
"""
return np.tensordot(a, b, 1)

Expand All @@ -37,26 +37,27 @@ def solve(A: np.ndarray, x: np.ndarray) -> np.ndarray:


def sum_at(a: ArrayLike, indices: ArrayLike, minlength: int):
"""Sums up values `a` with `indices` into an output array of at least length
`minlength` while treating dimensionality correctly. It's a lot faster than numpy's
own np.add.at (see
"""Sums up values `a` with `indices` into an output array of at least
length `minlength` while treating dimensionality correctly. It's a lot
faster than numpy's own np.add.at (see
https://github.com/numpy/numpy/issues/5922#issuecomment-511477435).
Typically, `indices` will be a one-dimensional array; `a` can have any
dimensionality. In this case, the output array will have shape (minlength,
a.shape[1:]).
`indices` may have arbitrary shape, too, but then `a` has to start out the same.
(Those dimensions are flattened out in the computation.)
`indices` may have arbitrary shape, too, but then `a` has to start out the
same. (Those dimensions are flattened out in the computation.)
"""
a = np.asarray(a)
indices = np.asarray(indices)

if len(a.shape) < len(indices.shape):
raise RuntimeError(
msg = (
f"a.shape = {a.shape}, indices.shape = {indices.shape}, "
"but len(a.shape) >= len(indices.shape) is required."
)
raise RuntimeError(msg)

m = len(indices.shape)
assert indices.shape == a.shape[:m]
Expand All @@ -74,7 +75,7 @@ def sum_at(a: ArrayLike, indices: ArrayLike, minlength: int):
[
np.bincount(indices, weights=a[:, k], minlength=minlength)
for k in range(a.shape[1])
]
],
).T.reshape(out_shape)


Expand Down
Loading

0 comments on commit ae37687

Please sign in to comment.