Skip to content

Commit 04b0430

Browse files
authored
Add __libsoxr_version__ to check version of linked libsoxr (#20)
* Get __libsoxr_version__ from separated C source
1 parent 65b743a commit 04b0430

11 files changed

+131
-20
lines changed

.gitignore

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
src/soxr/_csoxr_version.c
2+
src/soxr/_version.py
3+
4+
5+
### Python ###
16
# Byte-compiled / optimized / DLL files
27
__pycache__/
38
*.py[cod]
@@ -94,7 +99,22 @@ ipython_config.py
9499
# install all needed dependencies.
95100
#Pipfile.lock
96101

97-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
102+
# poetry
103+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
104+
# This is especially recommended for binary packages to ensure reproducibility, and is more
105+
# commonly ignored for libraries.
106+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
107+
#poetry.lock
108+
109+
# pdm
110+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
111+
#pdm.lock
112+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
113+
# in version control.
114+
# https://pdm.fming.dev/#use-with-ide
115+
.pdm.toml
116+
117+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
98118
__pypackages__/
99119

100120
# Celery stuff
@@ -136,3 +156,20 @@ dmypy.json
136156

137157
# Cython debug symbols
138158
cython_debug/
159+
160+
# PyCharm
161+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
162+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
163+
# and can be added to the global gitignore or merged into this file. For a more nuclear
164+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
165+
#.idea/
166+
167+
### Python Patch ###
168+
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
169+
poetry.toml
170+
171+
# ruff
172+
.ruff_cache/
173+
174+
# LSP config files
175+
pyrightconfig.json

BUILDING.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,18 @@ python -m build
2323
libsoxr should be installed before building.
2424
(e.g. `sudo apt install libsoxr-dev`)
2525
```
26-
python -m build -C=--global-option=--use-system-libsoxr
26+
python -m build -C--build-option=--use-system-libsoxr
2727
```
2828
It will link libsoxr dynamically and libsoxr won't bundled in the wheel package.
2929

3030

31+
## Install
32+
Install built .whl package(not .tar.gz sdist).
33+
```
34+
pip install dist/soxr-[...].whl
35+
```
36+
37+
3138
## Test
3239
```
3340
# Install dependencies

MANIFEST.in

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ include libsoxr/src/*.c
22
include libsoxr/src/*.h
33
include libsoxr/COPYING.LGPL
44
include libsoxr/LICENCE
5+
include src/soxr/csoxr_version.c
56
include src/soxr/*.h
67
include src/soxr/*.pxd
78
include src/soxr/*.py

pyproject.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ requires = [
33
"setuptools>=42",
44
"wheel",
55
"Cython>=3.0a7",
6-
"setuptools_scm[toml]>=3.4",
6+
"setuptools_scm[toml]>=6.2",
77
"oldest-supported-numpy"
88
]
99
build-backend = "setuptools.build_meta"
1010

1111
[tool.setuptools_scm]
12-
write_to = "src/soxr/version.py"
12+
write_to = "src/soxr/_version.py"

setup.py

+55-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
1+
"""
2+
Python-SoXR setup.py for Cython build
3+
4+
Please refer to BUILDING.md for building instructions.
5+
Do not run setup.py directly for the build process.
6+
"""
7+
8+
import logging
9+
import subprocess
110
import sys
211
import sysconfig
312

4-
from setuptools import setup, Extension
5-
613
from distutils.ccompiler import get_default_compiler
14+
from setuptools import setup, Extension
15+
from setuptools.command.sdist import sdist
716

817

918
SYS_LIBSOXR = False
1019

11-
# python -m build -C=--global-option=--use-system-libsoxr
20+
# python -m build -C=--build-option=--use-system-libsoxr
1221
if '--use-system-libsoxr' in sys.argv:
1322
sys.argv.remove('--use-system-libsoxr')
1423
SYS_LIBSOXR = True
@@ -28,7 +37,37 @@ def include_dirs(self):
2837
def include_dirs(self, dirs):
2938
self._include = dirs
3039

31-
src_libsoxr = [
40+
41+
def get_git_version(cwd=''):
42+
try:
43+
result = subprocess.run(
44+
['git', 'describe', '--tags', '--always', '--dirty'],
45+
cwd=cwd, capture_output=True, check=True, text=True)
46+
47+
ver = result.stdout.strip()
48+
return ver
49+
except Exception as e:
50+
logging.warning(f'Error retrieving submodule version: {e}')
51+
return 'unknown'
52+
53+
54+
CSOXR_VERSION_C = '''
55+
#include "csoxr_version.h"
56+
const char * libsoxr_version() { return "%s"; }
57+
'''
58+
59+
60+
class SDistBundledCommand(sdist):
61+
def run(self):
62+
ver = get_git_version('libsoxr')
63+
with open(f'src/soxr/_csoxr_version.c', 'wt') as f:
64+
f.write(CSOXR_VERSION_C % (ver))
65+
logging.info(f'libsoxr version: {ver}')
66+
67+
super().run()
68+
69+
70+
src_static = [
3271
'libsoxr/src/soxr.c',
3372
'libsoxr/src/data-io.c',
3473
'libsoxr/src/dbesi0.c',
@@ -55,11 +94,16 @@ def include_dirs(self, dirs):
5594
# 'libsoxr/src/cr64s.c',
5695
# 'libsoxr/src/pffft64s.c',
5796
# 'libsoxr/src/util64s.c',
97+
98+
# Cython wrapper
99+
'src/soxr/cysoxr.pyx',
100+
'src/soxr/_csoxr_version.c', # csoxr libsoxr_version()
58101
]
59102

60-
src = [
103+
src_dynamic = [
61104
# Cython wrapper
62-
'src/soxr/cysoxr.pyx'
105+
'src/soxr/cysoxr.pyx',
106+
'src/soxr/csoxr_version.c', # libsoxr soxr_version()
63107
]
64108

65109
compile_args = ['-DSOXR_LIB']
@@ -76,25 +120,28 @@ def include_dirs(self, dirs):
76120
extensions = [
77121
CySoxrExtension(
78122
"soxr.cysoxr",
79-
src_libsoxr + src,
123+
src_static,
80124
include_dirs=['libsoxr/src', 'src/soxr'],
81125
language="c",
82126
extra_compile_args=compile_args)
83127
]
84128

85129
extensions_dynamic = [
86-
CySoxrExtension('soxr.cysoxr', src, language='c', libraries=['soxr'])
130+
CySoxrExtension('soxr.cysoxr', src_dynamic, language='c', libraries=['soxr'])
87131
]
88132

89133

90134
if __name__ == "__main__":
91135
from Cython.Build import cythonize
92136

93137
if SYS_LIBSOXR:
138+
logging.info('Building Python-SoXR using system libsoxr...')
94139
setup(
95140
ext_modules=cythonize(extensions_dynamic, language_level='3'),
96141
)
97142
else:
143+
logging.info('Building Python-SoXR using bundled libsoxr...')
98144
setup(
145+
cmdclass={'sdist': SDistBundledCommand},
99146
ext_modules=cythonize(extensions, language_level='3'),
100147
)

src/soxr/__init__.py

+7-8
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77

88
import numpy as np
99

10-
from .cysoxr import CySoxr
11-
from .cysoxr import cysoxr_divide_proc
12-
from .cysoxr import cysoxr_oneshot
10+
from . import cysoxr
1311
from .cysoxr import QQ, LQ, MQ, HQ, VHQ
12+
from ._version import __version__
1413

15-
from .version import version as __version__
1614

15+
__libsoxr_version__ = cysoxr.libsoxr_version()
1716

1817
# libsoxr locates memory per each channel.
1918
# Too much channels will cause memory error.
@@ -83,7 +82,7 @@ def __init__(self,
8382

8483
q = _quality_to_enum(quality)
8584

86-
self._cysoxr = CySoxr(in_rate, out_rate, num_channels, self._type.type, q)
85+
self._cysoxr = cysoxr.CySoxr(in_rate, out_rate, num_channels, self._type.type, q)
8786

8887
def resample_chunk(self, x, last=False):
8988
""" Resample chunk with streaming resampler
@@ -157,14 +156,14 @@ def resample(x, in_rate: float, out_rate: float, quality='HQ'):
157156
x = np.ascontiguousarray(x) # make array C-contiguous
158157

159158
if x.ndim == 1:
160-
y = cysoxr_divide_proc(in_rate, out_rate, x[:, np.newaxis], q)
159+
y = cysoxr.cysoxr_divide_proc(in_rate, out_rate, x[:, np.newaxis], q)
161160
return np.squeeze(y, axis=1)
162161
elif x.ndim == 2:
163162
num_channels = x.shape[1]
164163
if num_channels < 1 or _CH_LIMIT < num_channels:
165164
raise ValueError(_CH_EXEED_ERR_STR.format(num_channels))
166165

167-
return cysoxr_divide_proc(in_rate, out_rate, x, q)
166+
return cysoxr.cysoxr_divide_proc(in_rate, out_rate, x, q)
168167
else:
169168
raise ValueError('Input must be 1-D or 2-D array')
170169

@@ -175,4 +174,4 @@ def _resample_oneshot(x, in_rate: float, out_rate: float, quality='HQ'):
175174
`soxr_oneshot()` becomes slow with long input.
176175
This function exists for test purpose.
177176
"""
178-
return cysoxr_oneshot(in_rate, out_rate, x, _quality_to_enum(quality))
177+
return cysoxr.cysoxr_oneshot(in_rate, out_rate, x, _quality_to_enum(quality))

src/soxr/_csoxr_version.c

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "csoxr_version.h"
2+
3+
const char * libsoxr_version() {
4+
return "undefined";
5+
}

src/soxr/csoxr.pxd

+4
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,7 @@ cdef extern from 'soxr.h':
5858
cdef unsigned long SOXR_VHQ
5959

6060
cdef soxr_io_spec_t soxr_io_spec(soxr_datatype_t itype, soxr_datatype_t otype)
61+
62+
63+
cdef extern from 'csoxr_version.h':
64+
cdef const char * libsoxr_version()

src/soxr/csoxr_version.c

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <soxr.h>
2+
#include "csoxr_version.h"
3+
4+
const char * libsoxr_version() {
5+
return soxr_version();
6+
}

src/soxr/csoxr_version.h

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const char * libsoxr_version();

src/soxr/cysoxr.pyx

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ ctypedef fused datatype_t:
2424
cython.short
2525

2626

27+
cpdef str libsoxr_version():
28+
return csoxr.libsoxr_version().decode('UTF-8')
29+
30+
2731
# NumPy scalar type to soxr_io_spec_t
2832
cdef csoxr.soxr_io_spec_t to_io_spec(type ntype):
2933
cdef csoxr.soxr_datatype_t io_type

0 commit comments

Comments
 (0)