Skip to content

Commit 1661f0e

Browse files
committed
use setuptools to install/build statswrapper
1 parent a3562d5 commit 1661f0e

6 files changed

Lines changed: 76 additions & 20 deletions

File tree

build.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from __future__ import annotations
2+
3+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
4+
from setuptools import Extension
5+
from setuptools.command.build_ext import build_ext
6+
7+
8+
class CustomBuildHook(BuildHookInterface):
9+
def initialize(self, version, build_data):
10+
build_data['ext_modules'] = [
11+
Extension(
12+
"api_tracer._stats_wrapper",
13+
["src/api_tracer/_stats_wrapper.c"],
14+
),
15+
]
16+
build_data['cmdclass'] = {"build_ext": build_ext}

examples/test_scipy.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
from scipy import stats
1+
# from opentelemetry.instrumentation.auto_instrumentation import initialize
2+
from api_tracer import install
3+
4+
# from api_tracer.console import setup_console
5+
6+
install(["scipy.stats._correlation", "scipy.stats._distn_infrastructure"])
7+
# initialize()
8+
# setup_console()
9+
10+
from scipy import stats # noqa: E402
211

312
stats.norm.pdf(x=1, loc=1, scale=0.01)
413
stats.norm(loc=1, scale=0.02).pdf(1)
@@ -8,3 +17,11 @@
817
# Y = stats.exp((X + 1)*0.01)
918
# from scipy import test
1019
# test()
20+
21+
# How many calls (errors, and how often something was odd with the args)
22+
print("counts: ", stats.norm.pdf._get_counts())
23+
24+
# Detailed statics for each parameter. How often was it passed
25+
# and how often were "a" and 3 passed (or something equal to them,
26+
# I do not consider types right now, although one could)?
27+
print("param stats: ", stats.norm.pdf._get_param_stats())

examples/test_statswrapper.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from __future__ import annotations
2+
3+
from api_tracer.statswrapper import stats_deco
4+
5+
6+
@stats_deco(None, b=("a", 3), c=None)
7+
def test_func(a, b=None, c=None):
8+
return a, b, c
9+
10+
11+
# Do things with test_func
12+
test_func(1, 3)
13+
14+
# How many calls (errors, and how often something was odd with the args)
15+
print("counts: ", test_func._get_counts())
16+
17+
# Detailed statics for each parameter. How often was it passed
18+
# and how often were "a" and 3 passed (or something equal to them,
19+
# I do not consider types right now, although one could)?
20+
print("param stats: ", test_func._get_param_stats())

pyproject.toml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[build-system]
2-
requires = ["hatchling>=1.26", "hatch-vcs"]
3-
build-backend = "hatchling.build"
2+
requires = ["setuptools>=77", "setuptools_scm[toml]>=7"]
3+
build-backend = "setuptools.build_meta"
44

55

66
[project]
77
name = "api-tracer"
88
authors = [
9-
{ name = "Guen Prawiroatmodjo", email = "guenp@hey.com" },
9+
{ name = "Scientific Python", email = "guenp@hey.com" },
1010
{ name = "Sebastian Berg", email = "sebastian@sipsolutions.net" },
1111
]
1212
description = "API tracer to gather usage telemetry for Python libraries"
@@ -56,14 +56,14 @@ docs = [
5656
]
5757

5858

59-
[tool.hatch]
60-
version.source = "vcs"
61-
build.hooks.vcs.version-file = "src/api_tracer/_version.py"
59+
[tool.setuptools_scm]
60+
write_to = "src/api_tracer/_version.py"
6261

63-
[tool.hatch.envs.default]
64-
# duplicate for now since hatch doesn't support groups yet
65-
dependencies = []
66-
scripts.test = "pytest {args}"
62+
63+
[tool.setuptools]
64+
ext-modules = [
65+
{name = "api_tracer.statswrapper._stats_wrapper", sources=["src/api_tracer/statswrapper/_stats_wrapper.c"]}
66+
]
6767

6868

6969
[tool.pytest.ini_options]

src/api_tracer/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2025 Guen Prawiroatmodjo. All rights reserved.
2+
Copyright (c) 2025 Scientific Python. All rights reserved.
33
44
api-tracer: API tracer to gather usage telemetry for Python libraries
55
"""
@@ -8,11 +8,14 @@
88

99
from api_tracer.path_finder import install
1010
from api_tracer.span import span
11+
from api_tracer.statswrapper import stats_deco, stats_deco_auto
1112

1213
from ._version import version as __version__
1314

1415
__all__ = [
1516
"__version__",
1617
"install",
1718
"span",
19+
"stats_deco",
20+
"stats_deco_auto",
1821
]

src/api_tracer/path_finder.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
from __future__ import annotations
2+
13
import inspect
24
import sys
35
from importlib.abc import MetaPathFinder
46
from importlib.machinery import SourceFileLoader
57
from importlib.util import spec_from_loader
68

7-
from api_tracer.span import span
9+
from api_tracer.statswrapper import stats_deco_auto
810

911
__all__ = ["install"]
1012

@@ -21,7 +23,7 @@ def __init__(self, module_names, *args, **kwargs):
2123
super().__init__(*args, **kwargs)
2224

2325
def find_spec(self, fullname, path, target=None):
24-
if any([name in fullname for name in self._module_names]):
26+
if any(name in fullname for name in self._module_names):
2527
for finder in sys.meta_path:
2628
if finder != self:
2729
spec = finder.find_spec(fullname, path, target)
@@ -32,8 +34,7 @@ def find_spec(self, fullname, path, target=None):
3234
loader=TelemetrySpanSourceFileLoader(spec.name, spec.origin),
3335
origin=spec.origin,
3436
)
35-
else:
36-
return spec
37+
return spec
3738

3839
return None
3940

@@ -48,14 +49,13 @@ def exec_module(self, module):
4849
for name, _function in functions:
4950
_module = inspect.getmodule(_function)
5051
if module == _module:
51-
setattr(_module, name, span(_function))
52+
setattr(_module, name, stats_deco_auto(_function))
5253

5354
# Add telemetry to methods
5455
for _, _class in classes:
5556
for name, method in inspect.getmembers(_class, predicate=inspect.isfunction):
56-
if inspect.getmodule(_class) == module:
57-
if not name.startswith("_"):
58-
setattr(_class, name, span(method))
57+
if inspect.getmodule(_class) == module and not name.startswith("_"):
58+
setattr(_class, name, stats_deco_auto(method))
5959

6060

6161
def install(module_names: list[str]):

0 commit comments

Comments
 (0)