Skip to content

Commit

Permalink
Rearrange a codebase, metadata and make it abi3 compatible. (#6)
Browse files Browse the repository at this point in the history
* Initial attempt to make some changes for abi3-compatibility.

* Massive rearrangement.
- Put source files in one package.
- Add an __init__.py and __init__.pyi to provide a target for type stubs.
 - Probably too eager; typeshed will probably provide these until 3.12 is EOL.
- Change setup configuration to
 a. Put as much as possible in pyproject.toml.
 b. Eliminate the need for setup.cfg.
 c. Don't break everything when attempting to build with `build` — the audioop header file just wasn't being seen.
- Most importantly, make it abi3. i.e., the resulting wheel should be compatible for >=3.12 environments.

* Account for some type errors and missing braces for an if clause.

* Slight bit of cleanup in pyproject.toml and setup.py.

* Revert the upgraded requirement to 3.12; it's true and makes it less annoying to publish before 3.13.0.

* Fix license name

Used the wrong one out of habit.

* Don't lie too much for the abi tag.
- More of a footgun than anything.

* change ci to work on PRs

* pin to the 3.13 rc for devcontainer, not a specific patch version

* update project meta, name and python version constraints

* Based on feedback, do restrict install to >=3.13.
- Add a note in setup.py about the limited API compatibility being more permissive but would lead to potential clobbering if requires-python matched it.

* Fix typo in comment and expand slightly.

* Add a py.typed file.

* change ci to work on PRs

* pin to the 3.13 rc for devcontainer, not a specific patch version

* update project meta, name and python version constraints

* Remove setup.cfg again and update project name.

* Ugly, but adding this back for a moment might fix the merge conflict?

* And now delete it again.

* Initial attempt to make some changes for abi3-compatibility.

* Massive rearrangement.
- Put source files in one package.
- Add an __init__.py and __init__.pyi to provide a target for type stubs.
 - Probably too eager; typeshed will probably provide these until 3.12 is EOL.
- Change setup configuration to
 a. Put as much as possible in pyproject.toml.
 b. Eliminate the need for setup.cfg.
 c. Don't break everything when attempting to build with `build` — the audioop header file just wasn't being seen.
- Most importantly, make it abi3. i.e., the resulting wheel should be compatible for >=3.12 environments.

* Account for some type errors and missing braces for an if clause.

* Slight bit of cleanup in pyproject.toml and setup.py.

* Revert the upgraded requirement to 3.12; it's true and makes it less annoying to publish before 3.13.0.

* Fix license name

Used the wrong one out of habit.

* Don't lie too much for the abi tag.
- More of a footgun than anything.

* Based on feedback, do restrict install to >=3.13.
- Add a note in setup.py about the limited API compatibility being more permissive but would lead to potential clobbering if requires-python matched it.

* Fix typo in comment and expand slightly.

* Add a py.typed file.

* Implement the limited api and abi3 tag in a less hacky way.

Source: pypa/wheel#583

* Hardcode the limited api version on the wheel (both the macro and the tag) to be 3.13.
- This should be the final necessary measure to avoid clobbering.

* Remove a now unnecessary comment.

* Improve types beyond what typeshed has.
- Typeshed has argument types as `bytes` to substitute for buffers since buffers didn't have a representation in the type system for a long time. Now that `collections.abc.Buffer` exists, there's a better alternative.
 - This means that memoryview, bytarray, etc. won't show up as type-checker errors when given as inputs.
- Tests actually type-check as a result. No changes to logic were made, just type annotations.
- TODO: Consider upstreaming to typeshed?

Reference material:
- https://docs.python.org/3/library/typing.html#typing.ByteString
- https://docs.python.org/3/library/collections.abc.html#collections.abc.Buffer
- https://peps.python.org/pep-0688
 - "No special meaning for bytes" mentions why these were annotated with `bytes` before.
- https://typing.readthedocs.io/en/latest/source/modernizing.html#typing-bytestring

---------

Co-authored-by: Alex Nørgaard <umbra@abstractumbra.dev>
  • Loading branch information
Sachaa-Thanasius and AbstractUmbra committed Apr 25, 2024
1 parent b6503e5 commit af2305b
Show file tree
Hide file tree
Showing 12 changed files with 243 additions and 89 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
build/
dist/
*.egg-info/
__pycache__/
3 changes: 2 additions & 1 deletion .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/local/include/python3.13"
"/usr/local/include/python3.13",
"/usr/include/python3.13"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
Expand Down
8 changes: 0 additions & 8 deletions MANIFEST.in

This file was deleted.

59 changes: 59 additions & 0 deletions audioop/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from ._audioop import (
error,
add,
adpcm2lin,
alaw2lin,
avg,
avgpp,
bias,
byteswap,
cross,
findfactor,
findfit,
findmax,
getsample,
lin2adpcm,
lin2alaw,
lin2lin,
lin2ulaw,
max,
maxpp,
minmax,
mul,
ratecv,
reverse,
rms,
tomono,
tostereo,
ulaw2lin,
)

__all__ = (
"error",
"add",
"adpcm2lin",
"alaw2lin",
"avg",
"avgpp",
"bias",
"byteswap",
"cross",
"findfactor",
"findfit",
"findmax",
"getsample",
"lin2adpcm",
"lin2alaw",
"lin2lin",
"lin2ulaw",
"max",
"maxpp",
"minmax",
"mul",
"ratecv",
"reverse",
"rms",
"tomono",
"tostereo",
"ulaw2lin",
)
45 changes: 45 additions & 0 deletions audioop/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from collections.abc import Buffer
from typing import TypeAlias

_AdpcmState: TypeAlias = tuple[int, int]
_RatecvState: TypeAlias = tuple[int, tuple[tuple[int, int], ...]]

class error(Exception): ...

def add(fragment1: Buffer, fragment2: Buffer, width: int, /) -> bytes: ...
def adpcm2lin(fragment: Buffer, width: int, state: _AdpcmState | None, /) -> tuple[bytes, _AdpcmState]: ...
def alaw2lin(fragment: Buffer, width: int, /) -> bytes: ...
def avg(fragment: Buffer, width: int, /) -> int: ...
def avgpp(fragment: Buffer, width: int, /) -> int: ...
def bias(fragment: Buffer, width: int, bias: int, /) -> bytes: ...
def byteswap(fragment: Buffer, width: int, /) -> bytes: ...
def cross(fragment: Buffer, width: int, /) -> int: ...
def findfactor(fragment: Buffer, reference: Buffer, /) -> float: ...
def findfit(fragment: Buffer, reference: Buffer, /) -> tuple[int, float]: ...
def findmax(fragment: Buffer, length: int, /) -> int: ...
def getsample(fragment: Buffer, width: int, index: int, /) -> int: ...
def lin2adpcm(fragment: Buffer, width: int, state: _AdpcmState | None, /) -> tuple[bytes, _AdpcmState]: ...
def lin2alaw(fragment: Buffer, width: int, /) -> bytes: ...
def lin2lin(fragment: Buffer, width: int, newwidth: int, /) -> bytes: ...
def lin2ulaw(fragment: Buffer, width: int, /) -> bytes: ...
def max(fragment: Buffer, width: int, /) -> int: ...
def maxpp(fragment: Buffer, width: int, /) -> int: ...
def minmax(fragment: Buffer, width: int, /) -> tuple[int, int]: ...
def mul(fragment: Buffer, width: int, factor: float, /) -> bytes: ...
def ratecv(
fragment: Buffer,
width: int,
nchannels: int,
inrate: int,
outrate: int,
state: _RatecvState | None,
weightA: int = 1,
weightB: int = 0,
/,
) -> tuple[bytes, _RatecvState]: ...
def reverse(fragment: Buffer, width: int, /) -> bytes: ...
def rms(fragment: Buffer, width: int, /) -> int: ...
def tomono(fragment: Buffer, width: int, lfactor: float, rfactor: float, /) -> bytes: ...
def tostereo(fragment: Buffer, width: int, lfactor: float, rfactor: float, /) -> bytes: ...
def ulaw2lin(fragment: Buffer, width: int, /) -> bytes: ...
# pyright: ignore [reportShadowedImports]
13 changes: 10 additions & 3 deletions audioop.c → audioop/_audioop.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@

#include "Python.h"

#define _LTS_Py_SETREF(op, op2) \
do { \
PyObject *_py_tmp = (PyObject *)(op); \
(op) = (op2); \
Py_DECREF(_py_tmp); \
} while (0)

static const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF};
/* -1 trick is needed on Windows to support -0x80000000 without a warning */
static const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x7FFFFFFF-1};
Expand Down Expand Up @@ -1469,7 +1476,7 @@ audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
len = (Py_ssize_t)(ncp - PyBytes_AsString(str));
rv = PyBytes_FromStringAndSize
(PyBytes_AsString(str), len);
Py_SETREF(str, rv);
_LTS_Py_SETREF(str, rv);
if (str == NULL)
goto exit;
rv = Py_BuildValue("(O(iO))", str, d, samps);
Expand Down Expand Up @@ -1899,7 +1906,7 @@ audioop_adpcm2lin_impl(PyObject *module, Py_buffer *fragment, int width,
return rv;
}

#include "clinic/audioop.c.h"
#include "_audioop.c.h"

static PyMethodDef audioop_methods[] = {
AUDIOOP_MAX_METHODDEF
Expand Down Expand Up @@ -1990,7 +1997,7 @@ static struct PyModuleDef audioopmodule = {
};

PyMODINIT_FUNC
PyInit_audioop(void)
PyInit__audioop(void)
{
return PyModuleDef_Init(&audioopmodule);
}

0 comments on commit af2305b

Please sign in to comment.