From 9ee14ce08954f71be328831dff04f9026d03cdec Mon Sep 17 00:00:00 2001 From: David Graham Date: Sat, 7 Jun 2025 22:35:49 -0400 Subject: [PATCH 1/8] minimal working example using scikit_build_core build backend --- .clang-tidy | 147 ------------------------------ .editorconfig | 12 +++ .gitignore | 52 ++++++++--- CMakeLists.txt | 58 ++---------- bindings.cpp | 11 +++ pyproject.toml | 80 ++++++++++++++++ src/library.cpp | 47 ++++++++++ src/library.h | 12 +++ src/libseis.c | 77 ---------------- src/libseis.h | 69 -------------- src/libseis/__init__.py | 5 + src/libseis/_core.pyi | 19 ++++ src/velocity.c | 28 ------ src/velocity.h | 19 ---- tests/__init__.py | 0 tests/libseis/__init__.py | 0 tests/libseis/test_script.py | 4 + {test => tests}/libseis_test.cpp | 0 {test => tests}/velocity_test.cpp | 0 uv.lock | 141 ++++++++++++++++++++++++++++ 20 files changed, 378 insertions(+), 403 deletions(-) delete mode 100644 .clang-tidy create mode 100644 bindings.cpp create mode 100644 pyproject.toml create mode 100644 src/library.cpp create mode 100644 src/library.h delete mode 100644 src/libseis.c delete mode 100644 src/libseis.h create mode 100644 src/libseis/__init__.py create mode 100644 src/libseis/_core.pyi delete mode 100644 src/velocity.c delete mode 100644 src/velocity.h create mode 100644 tests/__init__.py create mode 100644 tests/libseis/__init__.py create mode 100644 tests/libseis/test_script.py rename {test => tests}/libseis_test.cpp (100%) rename {test => tests}/velocity_test.cpp (100%) create mode 100644 uv.lock diff --git a/.clang-tidy b/.clang-tidy deleted file mode 100644 index ae0153a..0000000 --- a/.clang-tidy +++ /dev/null @@ -1,147 +0,0 @@ -# Generated from CLion Inspection settings ---- -Checks: '-*, -bugprone-argument-comment, -bugprone-assert-side-effect, -bugprone-bad-signal-to-kill-thread, -bugprone-branch-clone, -bugprone-copy-constructor-init, -bugprone-dangling-handle, -bugprone-dynamic-static-initializers, -bugprone-fold-init-type, -bugprone-forward-declaration-namespace, -bugprone-forwarding-reference-overload, -bugprone-inaccurate-erase, -bugprone-incorrect-roundings, -bugprone-integer-division, -bugprone-lambda-function-name, -bugprone-macro-parentheses, -bugprone-macro-repeated-side-effects, -bugprone-misplaced-operator-in-strlen-in-alloc, -bugprone-misplaced-pointer-arithmetic-in-alloc, -bugprone-misplaced-widening-cast, -bugprone-move-forwarding-reference, -bugprone-multiple-statement-macro, -bugprone-no-escape, -bugprone-not-null-terminated-result, -bugprone-parent-virtual-call, -bugprone-posix-return, -bugprone-reserved-identifier, -bugprone-sizeof-container, -bugprone-sizeof-expression, -bugprone-spuriously-wake-up-functions, -bugprone-string-constructor, -bugprone-string-integer-assignment, -bugprone-string-literal-with-embedded-nul, -bugprone-suspicious-enum-usage, -bugprone-suspicious-include, -bugprone-suspicious-memory-comparison, -bugprone-suspicious-memset-usage, -bugprone-suspicious-missing-comma, -bugprone-suspicious-semicolon, -bugprone-suspicious-string-compare, -bugprone-swapped-arguments, -bugprone-terminating-continue, -bugprone-throw-keyword-missing, -bugprone-too-small-loop-variable, -bugprone-undefined-memory-manipulation, -bugprone-undelegated-constructor, -bugprone-unhandled-self-assignment, -bugprone-unused-raii, -bugprone-unused-return-value, -bugprone-use-after-move, -bugprone-virtual-near-miss, -cert-dcl21-cpp, -cert-dcl58-cpp, -cert-err34-c, -cert-err52-cpp, -cert-err60-cpp, -cert-flp30-c, -cert-msc50-cpp, -cert-msc51-cpp, -cert-str34-c, -cppcoreguidelines-interfaces-global-init, -cppcoreguidelines-narrowing-conversions, -cppcoreguidelines-pro-type-member-init, -cppcoreguidelines-pro-type-static-cast-downcast, -cppcoreguidelines-slicing, -google-default-arguments, -google-explicit-constructor, -google-runtime-operator, -hicpp-exception-baseclass, -hicpp-multiway-paths-covered, -misc-misplaced-const, -misc-new-delete-overloads, -misc-no-recursion, -misc-non-copyable-objects, -misc-throw-by-value-catch-by-reference, -misc-unconventional-assign-operator, -misc-uniqueptr-reset-release, -modernize-avoid-bind, -modernize-concat-nested-namespaces, -modernize-deprecated-headers, -modernize-deprecated-ios-base-aliases, -modernize-loop-convert, -modernize-make-shared, -modernize-make-unique, -modernize-pass-by-value, -modernize-raw-string-literal, -modernize-redundant-void-arg, -modernize-replace-auto-ptr, -modernize-replace-disallow-copy-and-assign-macro, -modernize-replace-random-shuffle, -modernize-return-braced-init-list, -modernize-shrink-to-fit, -modernize-unary-static-assert, -modernize-use-auto, -modernize-use-bool-literals, -modernize-use-emplace, -modernize-use-equals-default, -modernize-use-equals-delete, -modernize-use-nodiscard, -modernize-use-noexcept, -modernize-use-nullptr, -modernize-use-override, -modernize-use-transparent-functors, -modernize-use-uncaught-exceptions, -mpi-buffer-deref, -mpi-type-mismatch, -openmp-use-default-none, -performance-faster-string-find, -performance-for-range-copy, -performance-implicit-conversion-in-loop, -performance-inefficient-algorithm, -performance-inefficient-string-concatenation, -performance-inefficient-vector-operation, -performance-move-const-arg, -performance-move-constructor-init, -performance-no-automatic-move, -performance-noexcept-move-constructor, -performance-trivially-destructible, -performance-type-promotion-in-math-fn, -performance-unnecessary-copy-initialization, -performance-unnecessary-value-param, -portability-simd-intrinsics, -readability-avoid-const-params-in-decls, -readability-const-return-type, -readability-container-size-empty, -readability-convert-member-functions-to-static, -readability-delete-null-pointer, -readability-deleted-default, -readability-inconsistent-declaration-parameter-name, -readability-make-member-function-const, -readability-misleading-indentation, -readability-misplaced-array-index, -readability-non-const-parameter, -readability-redundant-control-flow, -readability-redundant-declaration, -readability-redundant-function-ptr-dereference, -readability-redundant-smartptr-get, -readability-redundant-string-cstr, -readability-redundant-string-init, -readability-simplify-subscript-expr, -readability-static-accessed-through-instance, -readability-static-definition-in-anonymous-namespace, -readability-string-compare, -readability-uniqueptr-delete-release, -readability-use-anyofallof' \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index 082c9dd..ec1863a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,18 @@ trim_trailing_whitespace = true end_of_line = lf insert_final_newline = true indent_style = space +max_line_length = 100 + +[*.py] +indent_style = space +indent_size = 4 [*.{c,cc,h,cpp,hpp}] indent_size = 2 + +[*.md] +indent_size = 4 +max_line_length = 120 + +[*.{yaml,yml}] +indent_size = 2 diff --git a/.gitignore b/.gitignore index 509633e..9b90f9a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,23 @@ -# Compiled Object files +# General **/.DS_Store +**/*.bak* +*.log + +## C/C++ +build/**/* +include/* +lib/* +bin/* +Testing +tests/Temporary +*.bin *.slo *.lo *.o *.obj - -# Compiled Dynamic libraries *.so *.dylib *.dll - -# Executables *.exe *.out *.app @@ -26,14 +33,31 @@ **/*.cbp **/CMakeScripts **/compile_commands.json +build.ninja +.cmake/ -## Local +# IDE .idea/ -build/**/* -include/* -lib/* -bin/* -test/test_runner -Testing -test/Temporary -*.bin +.vscode/ + +# Python +venv/ +.venv/ +*.egg-info/ +.ipynb_checkpoints/ +.mypy_cache/ +.ruff_cache/ +/data/ +/media/ +__pycache__/ +_build/ +build/ +dist/ +.coverage* +coverage.* +log.html +output.xml +.pytest_cache/ +report.html +coverage_html/ + diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ee3856..3fd809c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,52 +1,12 @@ -### Libseis -cmake_minimum_required(VERSION 3.22.0) +cmake_minimum_required(VERSION 3.15) -project("libseis") +project( + ${SKBUILD_PROJECT_NAME} + VERSION ${SKBUILD_PROJECT_VERSION} + LANGUAGES CXX) -### Variables -set(CMAKE_CXX_STANDARD 11) +set(PYBIND11_FINDPYTHON ON) +find_package(pybind11 CONFIG REQUIRED) -set(LIB_NAME "seis") -set(PROJECT_VERSION_MAJOR 0) -set(PROJECT_VERSION_MINOR 1) -set(PROJECT_VERSION_PATCH 0) - -set(SRC_DIR "src") - -### create libseis library -include_directories(src) -add_library(${LIB_NAME} SHARED ${SRC_DIR}/libseis.c ${SRC_DIR}/velocity.c) - - -set_target_properties( - ${LIB_NAME} PROPERTIES - VERSION "v${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" - PUBLIC_HEADER ${SRC_DIR}/libseis.h - PUBLIC_HEADER ${SRC_DIR}/velocity.h -) - -install( - TARGETS ${LIB_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) - -### Google Test ### -include(FetchContent) -FetchContent_Declare( - googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.12.1 -) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) -FetchContent_MakeAvailable(googletest) - -enable_testing() -add_executable(libseis_test test/libseis_test.cpp) -add_executable(velocity_test test/velocity_test.cpp) -target_link_libraries(libseis_test ${LIB_NAME} GTest::gtest_main) -target_link_libraries(velocity_test ${LIB_NAME} GTest::gtest_main) -include(GoogleTest) -gtest_discover_tests(libseis_test) -gtest_discover_tests(velocity_test) +pybind11_add_module(_core MODULE src/library.cpp) +install(TARGETS _core DESTINATION libseis) diff --git a/bindings.cpp b/bindings.cpp new file mode 100644 index 0000000..67b5423 --- /dev/null +++ b/bindings.cpp @@ -0,0 +1,11 @@ +// +// Created by dg on 6/7/25. +// +#include "library.h" +#include + +namespace py = pybind11; + +PYBIND11_MODULE(mylib, m) { + m.def("add", &mylib::add, "A function which adds two numbers"); +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..3d1ca17 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,80 @@ +[project] +name = "libseis" +version = "0.0.2" +description = "Library of C++/Python serismic processing utils" +readme = "README.md" +authors = [ + { name = "David Graham", email = "dpgraham4401@gmail.com" }, +] +requires-python = ">=3.10" +classifiers = [ + "Development Status :: 4 - Alpha", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Private :: Do Not Upload", +] + + +[dependency-groups] +dev = [ + "pytest>=8.4.0", +] + +[build-system] +requires = ["scikit-build-core>=0.10", "pybind11"] +build-backend = "scikit_build_core.build" + + +[tool.scikit-build] +wheel.expand-macos-universal-tags = true +minimum-version = "build-system.requires" +build-dir = "build/{wheel_tag}" + + +[tool.pytest.ini_options] +minversion = "8.0" +addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"] +xfail_strict = true +log_cli_level = "INFO" +filterwarnings = [ + "error", + "ignore::pytest.PytestCacheWarning", +] +testpaths = ["tests"] + +[tool.cibuildwheel] +build-frontend = "build[uv]" +test-command = "pytest {project}/tests" +test-extras = ["test"] + +[tool.cibuildwheel.pyodide] +build-frontend = { name = "build", args = ["--exports", "whole_archive"] } + +[tool.ruff.lint] +extend-select = [ + "B", # flake8-bugbear + "I", # isort + "ARG", # flake8-unused-arguments + "C4", # flake8-comprehensions + "EM", # flake8-errmsg + "ICN", # flake8-import-conventions + "G", # flake8-logging-format + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PL", # pylint + "PT", # flake8-pytest-style + "PTH", # flake8-use-pathlib + "RET", # flake8-return + "RUF", # Ruff-specific + "SIM", # flake8-simplify + "T20", # flake8-print + "UP", # pyupgrade + "YTT", # flake8-2020 + "EXE", # flake8-executable + "NPY", # NumPy specific rules + "PD", # pandas-vet +] diff --git a/src/library.cpp b/src/library.cpp new file mode 100644 index 0000000..bf10013 --- /dev/null +++ b/src/library.cpp @@ -0,0 +1,47 @@ +// +// Created by dg on 6/7/25. +// + +#include + +#define STRINGIFY(x) #x +#define MACRO_STRINGIFY(x) STRINGIFY(x) + +int add(int i, int j) { + return i + j; +} + +namespace py = pybind11; + +PYBIND11_MODULE(_core, m) { + m.doc() = R"pbdoc( + Pybind11 example plugin + ----------------------- + + .. currentmodule:: libseis + + .. autosummary:: + :toctree: _generate + + add + subtract + )pbdoc"; + + m.def("add", &add, R"pbdoc( + Add two numbers + + Some other explanation about the add function. + )pbdoc"); + + m.def("subtract", [](int i, int j) { return i - j; }, R"pbdoc( + Subtract two numbers + + Some other explanation about the subtract function. + )pbdoc"); + +#ifdef VERSION_INFO + m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); +#else + m.attr("__version__") = "dev"; +#endif +} diff --git a/src/library.h b/src/library.h new file mode 100644 index 0000000..0164e2a --- /dev/null +++ b/src/library.h @@ -0,0 +1,12 @@ +// +// Created by dg on 6/7/25. +// + +#ifndef CPPLIB_LIBRARY_H +#define CPPLIB_LIBRARY_H + +namespace mylib { +int add(int a, int b); +} + +#endif // CPPLIB_LIBRARY_H diff --git a/src/libseis.c b/src/libseis.c deleted file mode 100644 index 9745872..0000000 --- a/src/libseis.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "libseis.h" -#include -#include -#include -#include - -double *read_double(char path[], int nt, int nx) { - FILE *fptr; - double *data; - data = (double *)malloc(nt * nx * sizeof(double)); - fptr = fopen(path, "rb"); - if (fptr == NULL) { - printf("unable to open file at %s\n", path); - exit(EXIT_FAILURE); - } - for (int i = 0; i < nt * nx; i++) { - fread(&data[i], sizeof(double), 1, fptr); - } - fclose(fptr); - return data; -} - -void write_double(char path[], double *data, int nt, int nx) { - FILE *fptr; - fptr = fopen(path, "wb"); - if (fptr == NULL) { - printf("unable to open file at %s\n", path); - exit(EXIT_FAILURE); - } - for (int i = 0; i < nx * nt; i++) { - fwrite(&data[i], sizeof(double), 1, fptr); - } - fclose(fptr); -} - -/** - * Creates a new gather with the same data as the input gather, but with each - * sample multiplied by a power of its corresponding time value. - * - * @param gather The input gather to be multiplied. - * @param power The power to raise the time values to. - * @return A new gather with the same dimensions as the input gather, but with - * modified data. - */ -Gather *gain_gather(Gather *gather, double power) { - Gather *new_gather = malloc(sizeof(Gather)); - if (new_gather == NULL) { - fprintf(stderr, "Error: input gather is NULL\n"); - } - memcpy(new_gather, gather, sizeof(Gather)); - new_gather->data = malloc(gather->nt * gather->nx * sizeof(double)); - if (new_gather->data == NULL) { - fprintf(stderr, "Error: input gather data is NULL\n"); - } - memcpy(new_gather->data, gather->data, - gather->nt * gather->nx * sizeof(double)); - for (int trace_index = 0; trace_index < gather->nx; trace_index++) { - for (int sample_index = 0; sample_index < gather->nt; sample_index++) { - double time = (double)sample_index * new_gather->dt; - double t_pow = pow(time, power); - int data_index = (trace_index * new_gather->nt) + sample_index; - new_gather->data[data_index] = gather->data[data_index] * t_pow; - } - } - return new_gather; -} - -void display_gather(Gather *gather) { - printf("--------------------\n"); - printf("Gather: id %d\n", gather->id); - printf("Sample Rate: %f seconds\n", gather->dt); - printf("Sampling Frequency: %f Hz\n", 1 / gather->dt); - printf("Nyquist Frequency: %f Hz\n", 1 / (gather->dt * 2)); - printf("Samples per trace: %d\n", gather->nt); - printf("Number of traces: %d\n", gather->nx); - printf("--------------------\n"); -} diff --git a/src/libseis.h b/src/libseis.h deleted file mode 100644 index d5c3298..0000000 --- a/src/libseis.h +++ /dev/null @@ -1,69 +0,0 @@ -// Libseis.h -// Libseis is a small, simple, collections of functions for seismic processing. -// David Graham - 2023-15-01 - -typedef enum { - SINGLE, - DOUBLE, -} PRECISION; - -/** - * @brief A collection of seismic traces and attributes - * - * @details A gather holds encapsulates all the information about seismic - * gathers, including the number of traces, the time sampling, number of time - * samples, and the data itself. It's intended to be generic enough to be used - * by various seismic gather types, such as CMP, or shot. - * - * @param - * id: (int) The gather's unique identifier - * @param - * nt: (int) number times samples in each trace, assumed homogeneous number of - * samples in each trace - * @param - * nx: (int) number traces - * @param - * dt: (double) the time sampling of the traces, assumed homogeneous - * @param - * data: (pointer) pointer to the array of samples - * @param - * precision: (enum PRECISION) the precision of the samples (e.g., double, - * double) - */ -typedef struct Gather { - int id; - int nt; - int nx; - double dt; - double *data; - PRECISION precision; -} Gather; - -double *read_double(char path[], int nt, int nx); - -void write_double(char path[], double *data, int nt, int nx); - -/** - * gain_gather - * - * @details - * Applies a time-variant scaling to a series of seismic traces in the same - * gather. It can be used to compensate for exponential decay (constant Q) in - * amplitude with time See "Tpow: an estimator of seismic amplitude decay" by - * Fowler & Claerbout nt' = nt * (dt * t^pow) - * - * @param - * gather: A pointer to a shot, CMP, or other seismic gather with all necessary - * fields. - * @param - * power: The power (double) applied to the seismic trace as a function of time. - * - * @returns - * A pointer to a new gather with the supplied Tpow applied. - * All gather attributes, besides the seismic data, are copied from the original - * gather - * - */ -Gather *gain_gather(Gather *gather, double power); - -void display_gather(Gather *gather); diff --git a/src/libseis/__init__.py b/src/libseis/__init__.py new file mode 100644 index 0000000..df39ed5 --- /dev/null +++ b/src/libseis/__init__.py @@ -0,0 +1,5 @@ +from __future__ import annotations + +from ._core import __doc__, add + +__all__ = ["__doc__", "add"] \ No newline at end of file diff --git a/src/libseis/_core.pyi b/src/libseis/_core.pyi new file mode 100644 index 0000000..ae3102b --- /dev/null +++ b/src/libseis/_core.pyi @@ -0,0 +1,19 @@ +""" +Pybind11 example plugin +----------------------- + +.. currentmodule:: libseis._core + +.. autosummary:: + :toctree: _generate + + add + subtract +""" + +def add(i: int, j: int) -> int: + """ + Add two numbers + + Some other explanation about the add function. + """ diff --git a/src/velocity.c b/src/velocity.c deleted file mode 100644 index b90f83d..0000000 --- a/src/velocity.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "velocity.h" - -#include - -VelocityModel *allocate_velocity_model(const int rows, const int cols) { - VelocityModel *model = malloc(sizeof(VelocityModel)); - model->rows = rows; - model->cols = cols; - - model->data = (double **)malloc(rows * sizeof(double *)); - for (int i = 0; i < rows; i++) { - model->data[i] = (double *)malloc(cols * sizeof(double)); - } - - return model; -} - -VelocityModel *simple_velocity_model(VelocityModel *model, - const double gradient, - const double startingVelocity) { - - for (int i = 0; i < model->rows; i++) { - for (int j = 0; j < model->cols; j++) { - model->data[i][j] = startingVelocity + gradient * i; - } - }; - return model; -} diff --git a/src/velocity.h b/src/velocity.h deleted file mode 100644 index 5b56f6c..0000000 --- a/src/velocity.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by dg on 5/4/24. -// - -#ifndef VELOCITY_H -#define VELOCITY_H - -typedef struct { - int rows; - int cols; - double **data; -} VelocityModel; - -VelocityModel *allocate_velocity_model(int rows, int cols); - -VelocityModel *simple_velocity_model(VelocityModel *model, double gradient, - double startingVelocity); - -#endif // VELOCITY_H diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/libseis/__init__.py b/tests/libseis/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/libseis/test_script.py b/tests/libseis/test_script.py new file mode 100644 index 0000000..1d248a7 --- /dev/null +++ b/tests/libseis/test_script.py @@ -0,0 +1,4 @@ +import libseis +class TestLibseis: + def test_add(self): + assert libseis.add(3, 4) == 7 diff --git a/test/libseis_test.cpp b/tests/libseis_test.cpp similarity index 100% rename from test/libseis_test.cpp rename to tests/libseis_test.cpp diff --git a/test/velocity_test.cpp b/tests/velocity_test.cpp similarity index 100% rename from test/velocity_test.cpp rename to tests/velocity_test.cpp diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..381193e --- /dev/null +++ b/uv.lock @@ -0,0 +1,141 @@ +version = 1 +revision = 2 +requires-python = ">=3.10" + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, +] + +[[package]] +name = "libseis" +version = "0.0.2" +source = { editable = "." } + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, +] + +[package.metadata] + +[package.metadata.requires-dev] +dev = [{ name = "pytest", specifier = ">=8.4.0" }] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" }, +] + +[[package]] +name = "pytest" +version = "8.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/aa/405082ce2749be5398045152251ac69c0f3578c7077efc53431303af97ce/pytest-8.4.0.tar.gz", hash = "sha256:14d920b48472ea0dbf68e45b96cd1ffda4705f33307dcc86c676c1b5104838a6", size = 1515232, upload-time = "2025-06-02T17:36:30.03Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/de/afa024cbe022b1b318a3d224125aa24939e99b4ff6f22e0ba639a2eaee47/pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e", size = 363797, upload-time = "2025-06-02T17:36:27.859Z" }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" }, +] From 17c58003cd9ec44c38fb11606ae8b0c7b4257f56 Mon Sep 17 00:00:00 2001 From: David Graham Date: Sun, 8 Jun 2025 09:27:13 -0400 Subject: [PATCH 2/8] add pre-commit --- .pre-commit-config.yaml | 65 +++++++++++++++++++ pyproject.toml | 1 + uv.lock | 134 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..5450612 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,65 @@ +# To use: +# +# pre-commit run -a +# +# Or: +# +# pre-commit install # (runs every time you commit in git) +# +# To update this file: +# +# pre-commit autoupdate +# +# See https://github.com/pre-commit/pre-commit + +ci: + autoupdate_commit_msg: "chore: update pre-commit hooks" + autofix_commit_msg: "style: pre-commit fixes" + +repos: +# Standard hooks +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml + exclude: ^conda\.recipe/meta\.yaml$ + - id: debug-statements + - id: end-of-file-fixer + - id: mixed-line-ending + - id: requirements-txt-fixer + - id: trailing-whitespace + +# Check linting and style issues +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.11.12" + hooks: + - id: ruff + args: ["--fix", "--show-fixes"] + - id: ruff-format + exclude: ^(docs) + +# Changes tabs to spaces +- repo: https://github.com/Lucas-C/pre-commit-hooks + rev: v1.5.5 + hooks: + - id: remove-tabs + exclude: ^(docs) + +# CMake formatting +- repo: https://github.com/cheshirekow/cmake-format-precommit + rev: v0.6.13 + hooks: + - id: cmake-format + additional_dependencies: [pyyaml] + types: [file] + files: (\.cmake|CMakeLists.txt)(.in)?$ + +# .clang-format file +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v13.0.0 + hooks: + - id: clang-format diff --git a/pyproject.toml b/pyproject.toml index 3d1ca17..aca4eed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ classifiers = [ [dependency-groups] dev = [ + "pre-commit>=4.2.0", "pytest>=8.4.0", ] diff --git a/uv.lock b/uv.lock index 381193e..b856d2a 100644 --- a/uv.lock +++ b/uv.lock @@ -2,6 +2,15 @@ version = 1 revision = 2 requires-python = ">=3.10" +[[package]] +name = "cfgv" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -11,6 +20,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "distlib" +version = "0.3.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923, upload-time = "2024-10-09T18:35:47.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973, upload-time = "2024-10-09T18:35:44.272Z" }, +] + [[package]] name = "exceptiongroup" version = "1.3.0" @@ -23,6 +41,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, ] +[[package]] +name = "filelock" +version = "3.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, +] + +[[package]] +name = "identify" +version = "2.6.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/88/d193a27416618628a5eea64e3223acd800b40749a96ffb322a9b55a49ed1/identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6", size = 99254, upload-time = "2025-05-23T20:37:53.3Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/cd/18f8da995b658420625f7ef13f037be53ae04ec5ad33f9b718240dcfd48c/identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2", size = 99145, upload-time = "2025-05-23T20:37:51.495Z" }, +] + [[package]] name = "iniconfig" version = "2.1.0" @@ -39,13 +75,26 @@ source = { editable = "." } [package.dev-dependencies] dev = [ + { name = "pre-commit" }, { name = "pytest" }, ] [package.metadata] [package.metadata.requires-dev] -dev = [{ name = "pytest", specifier = ">=8.4.0" }] +dev = [ + { name = "pre-commit", specifier = ">=4.2.0" }, + { name = "pytest", specifier = ">=8.4.0" }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, +] [[package]] name = "packaging" @@ -56,6 +105,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] +[[package]] +name = "platformdirs" +version = "4.3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, +] + [[package]] name = "pluggy" version = "1.6.0" @@ -65,6 +123,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] +[[package]] +name = "pre-commit" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, +] + [[package]] name = "pygments" version = "2.19.1" @@ -92,6 +166,50 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2f/de/afa024cbe022b1b318a3d224125aa24939e99b4ff6f22e0ba639a2eaee47/pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e", size = 363797, upload-time = "2025-06-02T17:36:27.859Z" }, ] +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199, upload-time = "2024-08-06T20:31:40.178Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758, upload-time = "2024-08-06T20:31:42.173Z" }, + { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463, upload-time = "2024-08-06T20:31:44.263Z" }, + { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280, upload-time = "2024-08-06T20:31:50.199Z" }, + { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239, upload-time = "2024-08-06T20:31:52.292Z" }, + { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802, upload-time = "2024-08-06T20:31:53.836Z" }, + { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527, upload-time = "2024-08-06T20:31:55.565Z" }, + { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052, upload-time = "2024-08-06T20:31:56.914Z" }, + { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774, upload-time = "2024-08-06T20:31:58.304Z" }, + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, +] + [[package]] name = "tomli" version = "2.2.1" @@ -139,3 +257,17 @@ sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d0 wheels = [ { url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" }, ] + +[[package]] +name = "virtualenv" +version = "20.31.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/2c/444f465fb2c65f40c3a104fd0c495184c4f2336d65baf398e3c75d72ea94/virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af", size = 6076316, upload-time = "2025-05-08T17:58:23.811Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/40/b1c265d4b2b62b58576588510fc4d1fe60a86319c8de99fd8e9fec617d2c/virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11", size = 6057982, upload-time = "2025-05-08T17:58:21.15Z" }, +] From 9135f06cc2877ada9521327f4778e5f4088b1dbe Mon Sep 17 00:00:00 2001 From: David Graham Date: Sun, 8 Jun 2025 09:30:07 -0400 Subject: [PATCH 3/8] Use UV as a project management tool bump license date --- .github/workflows/CI.yml | 38 +++++++++++++++---- .gitignore | 7 +++- CMakeLists.txt | 31 ++++++++++++++- LICENSE | 2 +- bindings.cpp | 11 ------ pyproject.toml | 9 +++++ src/libseis/__init__.py | 4 +- src/libseis/{_core.pyi => _add.pyi} | 2 +- src/{library.cpp => libseis/add.cpp} | 23 ++++++----- src/{library.h => libseis/add.hpp} | 2 +- src/libseis/add_test.cpp | 7 ++++ tests/libseis/test_add.py | 7 ++++ tests/libseis/test_script.py | 4 -- tests/libseis_test.cpp | 44 --------------------- tests/velocity_test.cpp | 57 ---------------------------- 15 files changed, 104 insertions(+), 144 deletions(-) delete mode 100644 bindings.cpp rename src/libseis/{_core.pyi => _add.pyi} (88%) rename src/{library.cpp => libseis/add.cpp} (59%) rename src/{library.h => libseis/add.hpp} (87%) create mode 100644 src/libseis/add_test.cpp create mode 100644 tests/libseis/test_add.py delete mode 100644 tests/libseis/test_script.py delete mode 100644 tests/libseis_test.cpp delete mode 100644 tests/velocity_test.cpp diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 207beaa..3a9a608 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -8,33 +8,55 @@ on: env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type BUILD_TYPE: Release jobs: - build_test: + cpp_tests: + name: "C++ Unit Tests" strategy: fail-fast: false matrix: os: [ ubuntu-latest, macos-latest ] - # The CMake configure and build commands are platform-agnostic and should work equally well on Windows or Mac. - # You can convert this to a matrix build if you need cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - name: Build - # Build your program with the given configuration run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - name: Test working-directory: ${{github.workspace}}/build - # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: ctest -C ${{env.BUILD_TYPE}} + + python_tests: + name: "Python Tests" + strategy: + matrix: + os: [ ubuntu-latest, macos-latest ] + python-version: [ '3.10', '3.11', '3.12', '3.13' ] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: 'Install uv' + uses: astral-sh/setup-uv@v5 + with: + cache-dependency-glob: "**/pyproject.toml" + + - name: Install dependencies + run: uv sync --locked --all-extras --dev + + - name: 'Run unit tests' + run: pytest -n auto diff --git a/.gitignore b/.gitignore index 9b90f9a..faa62e6 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,12 @@ tests/Temporary *.out *.app +# Google Test +googletest/ +_deps +libseis_test[1]_include.cmake +**/*.cmake + # Cmake **/cmake-build-debug **/CMakeCache.txt @@ -60,4 +66,3 @@ output.xml .pytest_cache/ report.html coverage_html/ - diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fd809c..e675e7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,33 @@ project( set(PYBIND11_FINDPYTHON ON) find_package(pybind11 CONFIG REQUIRED) +find_package(Python REQUIRED COMPONENTS Interpreter Development.Module) -pybind11_add_module(_core MODULE src/library.cpp) -install(TARGETS _core DESTINATION libseis) +pybind11_add_module(_add MODULE src/libseis/add.cpp) +install(TARGETS _add DESTINATION libseis) + +# Test ### Create static library to test the C++ code +add_library(libseis STATIC src/libseis/add.cpp) +target_compile_features(libseis PRIVATE cxx_std_17) +target_compile_options(libseis PRIVATE -Wall -Wpedantic -Weffc++ -Wextra + -Wfatal-errors) +set_property(TARGET libseis PROPERTY POSITION_INDEPENDENT_CODE ON) +target_include_directories(libseis PRIVATE ${Python_INCLUDE_DIRS}) + +# Fetch Google Test from GitHub +include(FetchContent) +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.12.1) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt + ON + CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +enable_testing() +add_executable(libseis_test src/libseis/add_test.cpp) +target_link_libraries(libseis_test libseis Python::Python GTest::gtest_main) +include(GoogleTest) +gtest_discover_tests(libseis_test) diff --git a/LICENSE b/LICENSE index b5af9a6..26ad29e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 David Paul Graham +Copyright (c) 2025 David Paul Graham Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/bindings.cpp b/bindings.cpp deleted file mode 100644 index 67b5423..0000000 --- a/bindings.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// -// Created by dg on 6/7/25. -// -#include "library.h" -#include - -namespace py = pybind11; - -PYBIND11_MODULE(mylib, m) { - m.def("add", &mylib::add, "A function which adds two numbers"); -} diff --git a/pyproject.toml b/pyproject.toml index aca4eed..ec36902 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,15 @@ requires = ["scikit-build-core>=0.10", "pybind11"] build-backend = "scikit_build_core.build" +[tool.uv] +cache-keys = [ + { file = "pyproject.toml" }, + { git = { commit = true } }, + { file = "CMakeLists.txt" }, + { file = "src/**/*.cpp" }, + { file = "src/**/*.hpp" }, +] + [tool.scikit-build] wheel.expand-macos-universal-tags = true minimum-version = "build-system.requires" diff --git a/src/libseis/__init__.py b/src/libseis/__init__.py index df39ed5..0dfbbe4 100644 --- a/src/libseis/__init__.py +++ b/src/libseis/__init__.py @@ -1,5 +1,5 @@ from __future__ import annotations -from ._core import __doc__, add +from ._add import __doc__, add -__all__ = ["__doc__", "add"] \ No newline at end of file +__all__ = ["__doc__", "add"] diff --git a/src/libseis/_core.pyi b/src/libseis/_add.pyi similarity index 88% rename from src/libseis/_core.pyi rename to src/libseis/_add.pyi index ae3102b..a31b7ef 100644 --- a/src/libseis/_core.pyi +++ b/src/libseis/_add.pyi @@ -2,7 +2,7 @@ Pybind11 example plugin ----------------------- -.. currentmodule:: libseis._core +.. currentmodule:: libseis._add .. autosummary:: :toctree: _generate diff --git a/src/library.cpp b/src/libseis/add.cpp similarity index 59% rename from src/library.cpp rename to src/libseis/add.cpp index bf10013..3d19232 100644 --- a/src/library.cpp +++ b/src/libseis/add.cpp @@ -2,19 +2,17 @@ // Created by dg on 6/7/25. // +#include "add.hpp" #include -#define STRINGIFY(x) #x -#define MACRO_STRINGIFY(x) STRINGIFY(x) - -int add(int i, int j) { - return i + j; -} +namespace libseis { +int add(const int i, const int j) { return i + j; } +} // namespace libseis namespace py = pybind11; -PYBIND11_MODULE(_core, m) { - m.doc() = R"pbdoc( +PYBIND11_MODULE(_add, m) { + m.doc() = R"pbdoc( Pybind11 example plugin ----------------------- @@ -27,21 +25,22 @@ PYBIND11_MODULE(_core, m) { subtract )pbdoc"; - m.def("add", &add, R"pbdoc( + m.def("add", &libseis::add, R"pbdoc( Add two numbers Some other explanation about the add function. )pbdoc"); - m.def("subtract", [](int i, int j) { return i - j; }, R"pbdoc( + m.def( + "subtract", [](int i, int j) { return i - j; }, R"pbdoc( Subtract two numbers Some other explanation about the subtract function. )pbdoc"); #ifdef VERSION_INFO - m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); + m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); #else - m.attr("__version__") = "dev"; + m.attr("__version__") = "dev"; #endif } diff --git a/src/library.h b/src/libseis/add.hpp similarity index 87% rename from src/library.h rename to src/libseis/add.hpp index 0164e2a..2ff63ca 100644 --- a/src/library.h +++ b/src/libseis/add.hpp @@ -5,7 +5,7 @@ #ifndef CPPLIB_LIBRARY_H #define CPPLIB_LIBRARY_H -namespace mylib { +namespace libseis { int add(int a, int b); } diff --git a/src/libseis/add_test.cpp b/src/libseis/add_test.cpp new file mode 100644 index 0000000..6e1996f --- /dev/null +++ b/src/libseis/add_test.cpp @@ -0,0 +1,7 @@ +#include "add.hpp" +#include "gtest/gtest.h" + +TEST(AddFunctionTest, HandlesPositiveNumbers) { + EXPECT_EQ(libseis::add(1, 2), 3); + EXPECT_EQ(libseis::add(10, 20), 30); +} diff --git a/tests/libseis/test_add.py b/tests/libseis/test_add.py new file mode 100644 index 0000000..f38a57b --- /dev/null +++ b/tests/libseis/test_add.py @@ -0,0 +1,7 @@ +import libseis + + +class TestLibseis: + def test_add(self): + expected = 7 + assert libseis.add(3, 4) == expected diff --git a/tests/libseis/test_script.py b/tests/libseis/test_script.py deleted file mode 100644 index 1d248a7..0000000 --- a/tests/libseis/test_script.py +++ /dev/null @@ -1,4 +0,0 @@ -import libseis -class TestLibseis: - def test_add(self): - assert libseis.add(3, 4) == 7 diff --git a/tests/libseis_test.cpp b/tests/libseis_test.cpp deleted file mode 100644 index cabc828..0000000 --- a/tests/libseis_test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "gtest/gtest.h" - -extern "C" { -#include "libseis.h" -#include -} - -int const nt_test = 10; -int const nx_test = 1; - -double double_trace1[nt_test] = { - 0.000, 2.000, 4.000, 8.000, 1.000, 2.000, 3.000, 4.000, 5.000, 6.000, -}; - -double cmp_array[nt_test * 2] = { - 0.000, 2.000, 4.000, 8.000, 1.000, 2.000, 3.000, 4.000, 5.000, 6.000, - 0.000, 0.000, 1.000, 0.020, 0.301, -0.101, 0.035, 0.011, -0.006, 0.009, -}; - -struct Gather cmp = {1, nt_test, 2, 1, cmp_array, DOUBLE}; - -TEST(LibseisIO, ReadWriteFloat) { - char tmp_file[] = "/tmp/data.bin"; - write_double(tmp_file, double_trace1, nt_test, nx_test); - double *data = read_double(tmp_file, nt_test, nx_test); - for (int i = 0; i < nt_test; i++) { - EXPECT_EQ(data[i], double_trace1[i]); - } -} - -TEST(GainCmp, GainsCmpGather) { - double t_pow = 2; - Gather *foo = gain_gather(&cmp, t_pow); - - printf("Check that the t^power function operates correctly"); - for (int i = 0; i < foo->nt; i++) { - printf("%f * (%f^%f) = %f\n", cmp.data[i], foo->dt * i, t_pow, - foo->data[i]); - double t_powered = cmp.data[i] * pow(foo->dt * i, t_pow); - EXPECT_EQ(foo->data[i], t_powered); - } -} - -TEST(Gather, GatherDisplay) { display_gather(&cmp); } \ No newline at end of file diff --git a/tests/velocity_test.cpp b/tests/velocity_test.cpp deleted file mode 100644 index cffe957..0000000 --- a/tests/velocity_test.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "gtest/gtest.h" -extern "C" { -#include "velocity.h" -} - -TEST(VelocityModel, AllocateVelocityModel) { - constexpr int rows = 5; - constexpr int cols = 5; - - // Call the function to test - VelocityModel *model = allocate_velocity_model(rows, cols); - - // Check if the function returned a non-null pointer - ASSERT_NE(model, nullptr); - - // Check if the rows and cols are correctly set - EXPECT_EQ(model->rows, rows); - EXPECT_EQ(model->cols, cols); - - // Check if the data array is correctly allocated - ASSERT_NE(model->data, nullptr); - - // Check each row of the data array - for (int i = 0; i < rows; i++) { - ASSERT_NE(model->data[i], nullptr); - } -} - -TEST(SimpleVelocityModel, ShouldApplyCorrectGradient) { - int rows = 5; - int cols = 10; - double gradient = 2.0; - double startingVelocity = 1.0; - VelocityModel *model = allocate_velocity_model(rows, cols); - model = simple_velocity_model(model, gradient, startingVelocity); - for (int i = 0; i < model->rows; i++) { - for (int j = 0; j < model->cols; j++) { - ASSERT_EQ(model->data[i][j], startingVelocity + gradient * i); - } - } - free(model); -} - -TEST(SimpleVelocityModel, ShouldHandleZeroGradient) { - int rows = 5; - int cols = 10; - double gradient = 0.0; - double startingVelocity = 1.0; - VelocityModel *model = allocate_velocity_model(rows, cols); - model = simple_velocity_model(model, gradient, startingVelocity); - for (int i = 0; i < model->rows; i++) { - for (int j = 0; j < model->cols; j++) { - ASSERT_EQ(model->data[i][j], startingVelocity); - } - } - free(model); -} \ No newline at end of file From 7a6d2653f596c1213493acc1198efb09cd328e10 Mon Sep 17 00:00:00 2001 From: David Graham Date: Sun, 8 Jun 2025 12:30:17 -0400 Subject: [PATCH 4/8] convert old C files to cpp code --- src/libseis/gather.cpp | 79 ++++++++++++++++++++++++++++++++++++++++ src/libseis/gather.hpp | 8 ++++ src/libseis/velocity.cpp | 29 +++++++++++++++ src/libseis/velocity.hpp | 27 ++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 src/libseis/gather.cpp create mode 100644 src/libseis/gather.hpp create mode 100644 src/libseis/velocity.cpp create mode 100644 src/libseis/velocity.hpp diff --git a/src/libseis/gather.cpp b/src/libseis/gather.cpp new file mode 100644 index 0000000..7d14701 --- /dev/null +++ b/src/libseis/gather.cpp @@ -0,0 +1,79 @@ +// +// Created by dg on 6/8/25. +// + +#include "gather.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Equivalent of the C struct. Ideally move to a header file. +struct Gather { + int id; + int nt; + int nx; + double dt; + std::vector data; +}; + +std::vector read_double(const std::string &path, int nt, int nx) { + std::ifstream file(path, std::ios::binary); + if (!file) { + throw std::runtime_error("Unable to open file at " + path); + } + + std::vector data(nt * nx); + file.read(reinterpret_cast(data.data()), nt * nx * sizeof(double)); + if (!file) { + throw std::runtime_error("Failed to read data from file at " + path); + } + + return data; +} + +void write_double(const std::string &path, const std::vector &data, + int nt, int nx) { + std::ofstream file(path, std::ios::binary); + if (!file) { + throw std::runtime_error("Unable to open file at " + path); + } + + file.write(reinterpret_cast(data.data()), + nt * nx * sizeof(double)); + if (!file) { + throw std::runtime_error("Failed to write data to file at " + path); + } +} + +std::unique_ptr gain_gather(const Gather &gather, double power) { + auto new_gather = std::make_unique(gather); + new_gather->data.resize(gather.nt * gather.nx); + + for (int trace_index = 0; trace_index < gather.nx; ++trace_index) { + for (int sample_index = 0; sample_index < gather.nt; ++sample_index) { + double time = static_cast(sample_index) * gather.dt; + double t_pow = std::pow(time, power); + int data_index = trace_index * gather.nt + sample_index; + new_gather->data[data_index] = gather.data[data_index] * t_pow; + } + } + + return new_gather; +} + +void display_gather(const Gather &gather) { + std::cout << "--------------------\n"; + std::cout << "Gather: id " << gather.id << '\n'; + std::cout << "Sample Rate: " << gather.dt << " seconds\n"; + std::cout << "Sampling Frequency: " << 1.0 / gather.dt << " Hz\n"; + std::cout << "Nyquist Frequency: " << 1.0 / (2 * gather.dt) << " Hz\n"; + std::cout << "Samples per trace: " << gather.nt << '\n'; + std::cout << "Number of traces: " << gather.nx << '\n'; + std::cout << "--------------------\n"; +} diff --git a/src/libseis/gather.hpp b/src/libseis/gather.hpp new file mode 100644 index 0000000..be4b054 --- /dev/null +++ b/src/libseis/gather.hpp @@ -0,0 +1,8 @@ +// +// Created by dg on 6/8/25. +// + +#ifndef GATHER_H +#define GATHER_H + +#endif // GATHER_H diff --git a/src/libseis/velocity.cpp b/src/libseis/velocity.cpp new file mode 100644 index 0000000..c07bf90 --- /dev/null +++ b/src/libseis/velocity.cpp @@ -0,0 +1,29 @@ +// +// Created by dg on 6/8/25. +// + +#include "velocity.hpp" + +VelocityModel::VelocityModel(const int rows, const int cols) + : _rows(rows), _cols(cols), _data(rows * cols) { + if (rows <= 0 || cols <= 0) { + throw std::invalid_argument("VelocityModel dimensions must be positive"); + } +} + +double &VelocityModel::at(const int row, const int col) { + return _data.at(row * _cols + col); +} + +const double &VelocityModel::at(int row, int col) const { + return _data.at(row * _cols + col); +} + +void VelocityModel::initialize_simple_model(const double gradient, + const double starting_velocity) { + for (int i = 0; i < _rows; ++i) { + for (int j = 0; j < _cols; ++j) { + at(i, j) = starting_velocity + gradient * i; + } + } +} diff --git a/src/libseis/velocity.hpp b/src/libseis/velocity.hpp new file mode 100644 index 0000000..bbb8a7c --- /dev/null +++ b/src/libseis/velocity.hpp @@ -0,0 +1,27 @@ +// +// Created by dg on 6/8/25. +// + +#pragma once + +#include +#include +#include + +class VelocityModel { +public: + VelocityModel(int rows, int cols); + + double &at(int row, int col); + const double &at(int row, int col) const; + + int rows() const { return _rows; } + int cols() const { return _cols; } + + void initialize_simple_model(double gradient, double starting_velocity); + +private: + int _rows; + int _cols; + std::vector _data; // flattened 2D array +}; From b2ef1707c0b7021dd8a9392458620c0acb28d885 Mon Sep 17 00:00:00 2001 From: David Graham Date: Sun, 8 Jun 2025 18:47:49 -0400 Subject: [PATCH 5/8] Reorganize the Cpp files separate from the python library --- CMakeLists.txt | 27 +++++++-------------- src/core/CMakeLists.txt | 19 +++++++++++++++ src/core/README.md | 11 +++++++++ src/core/add/README.md | 3 +++ src/core/add/add.cpp | 9 +++++++ src/{libseis => core/add}/add.hpp | 2 +- src/{libseis => core/add}/add_test.cpp | 0 src/{libseis/add.cpp => core/bindings.cpp} | 10 +++----- src/{libseis => core/gather}/gather.cpp | 2 +- src/{libseis => core/gather}/gather.hpp | 0 src/{libseis => core/velocity}/velocity.cpp | 2 +- src/{libseis => core/velocity}/velocity.hpp | 0 src/libseis/__init__.py | 7 +++--- src/libseis/{_add.pyi => _num.pyi} | 0 src/libseis/math.py | 10 ++++++++ tests/libseis/test_add.py | 4 +++ 16 files changed, 74 insertions(+), 32 deletions(-) create mode 100644 src/core/CMakeLists.txt create mode 100644 src/core/README.md create mode 100644 src/core/add/README.md create mode 100644 src/core/add/add.cpp rename src/{libseis => core/add}/add.hpp (85%) rename src/{libseis => core/add}/add_test.cpp (100%) rename src/{libseis/add.cpp => core/bindings.cpp} (81%) rename src/{libseis => core/gather}/gather.cpp (98%) rename src/{libseis => core/gather}/gather.hpp (100%) rename src/{libseis => core/velocity}/velocity.cpp (95%) rename src/{libseis => core/velocity}/velocity.hpp (100%) rename src/libseis/{_add.pyi => _num.pyi} (100%) create mode 100644 src/libseis/math.py diff --git a/CMakeLists.txt b/CMakeLists.txt index e675e7d..38c2b97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,35 +5,26 @@ project( VERSION ${SKBUILD_PROJECT_VERSION} LANGUAGES CXX) +# Include core modules +add_subdirectory(src/core) + +# Python bindings with pybind11 set(PYBIND11_FINDPYTHON ON) find_package(pybind11 CONFIG REQUIRED) find_package(Python REQUIRED COMPONENTS Interpreter Development.Module) +pybind11_add_module(_num MODULE src/core/bindings.cpp) +target_link_libraries(_num PRIVATE libseis) +install(TARGETS _num DESTINATION libseis) -pybind11_add_module(_add MODULE src/libseis/add.cpp) -install(TARGETS _add DESTINATION libseis) - -# Test ### Create static library to test the C++ code -add_library(libseis STATIC src/libseis/add.cpp) -target_compile_features(libseis PRIVATE cxx_std_17) -target_compile_options(libseis PRIVATE -Wall -Wpedantic -Weffc++ -Wextra - -Wfatal-errors) -set_property(TARGET libseis PROPERTY POSITION_INDEPENDENT_CODE ON) -target_include_directories(libseis PRIVATE ${Python_INCLUDE_DIRS}) - -# Fetch Google Test from GitHub +# Testing ### include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.12.1) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt - ON - CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) - enable_testing() -add_executable(libseis_test src/libseis/add_test.cpp) +add_executable(libseis_test src/core/add/add_test.cpp) target_link_libraries(libseis_test libseis Python::Python GTest::gtest_main) include(GoogleTest) gtest_discover_tests(libseis_test) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt new file mode 100644 index 0000000..cc41a5e --- /dev/null +++ b/src/core/CMakeLists.txt @@ -0,0 +1,19 @@ +# Gather sources into individual libraries +add_library(libadd STATIC add/add.cpp) +target_include_directories(libadd PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/add) + +add_library(libgather STATIC gather/gather.cpp) +target_include_directories(libgather PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/gather) + +add_library(libvelocity STATIC velocity/velocity.cpp) +target_include_directories(libvelocity + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/velocity) + +# Combined library: libseis aggregates all +add_library(libseis INTERFACE) +target_link_libraries(libseis INTERFACE libadd libgather libvelocity) +# target_compile_features(libseis PRIVATE cxx_std_17) +# target_compile_options(libseis PRIVATE -Wall -Wpedantic -Weffc++ -Wextra +# -Wfatal-errors) +set_property(TARGET libseis PROPERTY POSITION_INDEPENDENT_CODE ON) +target_include_directories(libseis PRIVATE ${Python_INCLUDE_DIRS}) diff --git a/src/core/README.md b/src/core/README.md new file mode 100644 index 0000000..8757e80 --- /dev/null +++ b/src/core/README.md @@ -0,0 +1,11 @@ +# Seismic library core modules + +C++ library and Python extension modules for seismic data processing and analysis. + +Modules are created using [pybind11](https://pybind11.readthedocs.io/en/stable/) and +built using [CMake](https://cmake.org/). + +## Organization + +The core libraries are not exposed (currently, 06/2025) directly, but are used to create +private Python modules which we are selectively exposed to the user. diff --git a/src/core/add/README.md b/src/core/add/README.md new file mode 100644 index 0000000..2ff1e61 --- /dev/null +++ b/src/core/add/README.md @@ -0,0 +1,3 @@ +# ADD + +Just used for setting up the libseis package. diff --git a/src/core/add/add.cpp b/src/core/add/add.cpp new file mode 100644 index 0000000..fa79458 --- /dev/null +++ b/src/core/add/add.cpp @@ -0,0 +1,9 @@ +// +// Created by dg on 6/7/25. +// + +#include "add.hpp" + +namespace libseis { +int add(const int i, const int j) { return i + j; } +} // namespace libseis diff --git a/src/libseis/add.hpp b/src/core/add/add.hpp similarity index 85% rename from src/libseis/add.hpp rename to src/core/add/add.hpp index 2ff63ca..44f858a 100644 --- a/src/libseis/add.hpp +++ b/src/core/add/add.hpp @@ -6,7 +6,7 @@ #define CPPLIB_LIBRARY_H namespace libseis { -int add(int a, int b); +int add(int i, int j); } #endif // CPPLIB_LIBRARY_H diff --git a/src/libseis/add_test.cpp b/src/core/add/add_test.cpp similarity index 100% rename from src/libseis/add_test.cpp rename to src/core/add/add_test.cpp diff --git a/src/libseis/add.cpp b/src/core/bindings.cpp similarity index 81% rename from src/libseis/add.cpp rename to src/core/bindings.cpp index 3d19232..a8db50c 100644 --- a/src/libseis/add.cpp +++ b/src/core/bindings.cpp @@ -1,17 +1,13 @@ // -// Created by dg on 6/7/25. +// Created by David Graham on 6/8/25. // -#include "add.hpp" +#include "add/add.hpp" #include -namespace libseis { -int add(const int i, const int j) { return i + j; } -} // namespace libseis - namespace py = pybind11; -PYBIND11_MODULE(_add, m) { +PYBIND11_MODULE(_num, m) { m.doc() = R"pbdoc( Pybind11 example plugin ----------------------- diff --git a/src/libseis/gather.cpp b/src/core/gather/gather.cpp similarity index 98% rename from src/libseis/gather.cpp rename to src/core/gather/gather.cpp index 7d14701..1a2ea23 100644 --- a/src/libseis/gather.cpp +++ b/src/core/gather/gather.cpp @@ -2,7 +2,7 @@ // Created by dg on 6/8/25. // -#include "gather.hpp" +#include "../libseis/gather.hpp" #include #include #include diff --git a/src/libseis/gather.hpp b/src/core/gather/gather.hpp similarity index 100% rename from src/libseis/gather.hpp rename to src/core/gather/gather.hpp diff --git a/src/libseis/velocity.cpp b/src/core/velocity/velocity.cpp similarity index 95% rename from src/libseis/velocity.cpp rename to src/core/velocity/velocity.cpp index c07bf90..a42013c 100644 --- a/src/libseis/velocity.cpp +++ b/src/core/velocity/velocity.cpp @@ -2,7 +2,7 @@ // Created by dg on 6/8/25. // -#include "velocity.hpp" +#include "../libseis/velocity.hpp" VelocityModel::VelocityModel(const int rows, const int cols) : _rows(rows), _cols(cols), _data(rows * cols) { diff --git a/src/libseis/velocity.hpp b/src/core/velocity/velocity.hpp similarity index 100% rename from src/libseis/velocity.hpp rename to src/core/velocity/velocity.hpp diff --git a/src/libseis/__init__.py b/src/libseis/__init__.py index 0dfbbe4..8fd0fd6 100644 --- a/src/libseis/__init__.py +++ b/src/libseis/__init__.py @@ -1,5 +1,4 @@ -from __future__ import annotations +from ._num import __doc__, add +from .math import add_one -from ._add import __doc__, add - -__all__ = ["__doc__", "add"] +__all__ = ["__doc__", "add", "add_one"] diff --git a/src/libseis/_add.pyi b/src/libseis/_num.pyi similarity index 100% rename from src/libseis/_add.pyi rename to src/libseis/_num.pyi diff --git a/src/libseis/math.py b/src/libseis/math.py new file mode 100644 index 0000000..95c16ca --- /dev/null +++ b/src/libseis/math.py @@ -0,0 +1,10 @@ +from ._num import add + + +def add_one(i: int) -> int: + """ + Add one to the given integer. + + This function takes an integer and returns the integer incremented by one. + """ + return add(i, 1) diff --git a/tests/libseis/test_add.py b/tests/libseis/test_add.py index f38a57b..2ece910 100644 --- a/tests/libseis/test_add.py +++ b/tests/libseis/test_add.py @@ -5,3 +5,7 @@ class TestLibseis: def test_add(self): expected = 7 assert libseis.add(3, 4) == expected + + def test_add_one(self): + expected = 4 + assert libseis.add_one(3) == expected From 5de1e1781c38543b9003b7c141d3b28c5a67458f Mon Sep 17 00:00:00 2001 From: David Graham Date: Sun, 8 Jun 2025 20:30:49 -0400 Subject: [PATCH 6/8] Add the gather module to python package and create an initial implementation of the gather class --- .github/workflows/CI.yml | 2 +- CMakeLists.txt | 5 ++ src/core/CMakeLists.txt | 8 +-- src/core/bindings.cpp | 19 ++++-- src/core/gather/gather.cpp | 129 +++++++++++++++++------------------ src/core/gather/gather.hpp | 12 ++++ src/libseis/__init__.py | 3 +- src/libseis/_gather.pyi | 10 +++ tests/libseis/test_add.py | 12 +++- tests/libseis/test_gather.py | 29 ++++++++ 10 files changed, 147 insertions(+), 82 deletions(-) create mode 100644 src/libseis/_gather.pyi create mode 100644 tests/libseis/test_gather.py diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3a9a608..ba19783 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,4 +1,4 @@ -name: Clang CI +name: CI on: push: diff --git a/CMakeLists.txt b/CMakeLists.txt index 38c2b97..368fcb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,10 +12,15 @@ add_subdirectory(src/core) set(PYBIND11_FINDPYTHON ON) find_package(pybind11 CONFIG REQUIRED) find_package(Python REQUIRED COMPONENTS Interpreter Development.Module) + pybind11_add_module(_num MODULE src/core/bindings.cpp) target_link_libraries(_num PRIVATE libseis) install(TARGETS _num DESTINATION libseis) +pybind11_add_module(_gather MODULE src/core/bindings.cpp) +target_link_libraries(_gather PRIVATE libseis) +install(TARGETS _gather DESTINATION libseis) + # Testing ### include(FetchContent) FetchContent_Declare( diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cc41a5e..bdf72c3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -5,13 +5,13 @@ target_include_directories(libadd PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/add) add_library(libgather STATIC gather/gather.cpp) target_include_directories(libgather PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/gather) -add_library(libvelocity STATIC velocity/velocity.cpp) -target_include_directories(libvelocity - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/velocity) +# add_library(libvelocity STATIC velocity/velocity.cpp) +# target_include_directories(libvelocity PUBLIC +# ${CMAKE_CURRENT_SOURCE_DIR}/velocity) # Combined library: libseis aggregates all add_library(libseis INTERFACE) -target_link_libraries(libseis INTERFACE libadd libgather libvelocity) +target_link_libraries(libseis INTERFACE libadd libgather) # target_compile_features(libseis PRIVATE cxx_std_17) # target_compile_options(libseis PRIVATE -Wall -Wpedantic -Weffc++ -Wextra # -Wfatal-errors) diff --git a/src/core/bindings.cpp b/src/core/bindings.cpp index a8db50c..1ac6171 100644 --- a/src/core/bindings.cpp +++ b/src/core/bindings.cpp @@ -5,6 +5,8 @@ #include "add/add.hpp" #include +#include "gather.hpp" + namespace py = pybind11; PYBIND11_MODULE(_num, m) { @@ -27,16 +29,19 @@ PYBIND11_MODULE(_num, m) { Some other explanation about the add function. )pbdoc"); - m.def( - "subtract", [](int i, int j) { return i - j; }, R"pbdoc( - Subtract two numbers - - Some other explanation about the subtract function. - )pbdoc"); - #ifdef VERSION_INFO m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); #else m.attr("__version__") = "dev"; #endif } + +PYBIND11_MODULE(_gather, m) { + py::class_(m, "Gather") + .def(py::init<>()) + .def_readwrite("id", &Gather::id) + .def_readwrite("dt", &Gather::dt) + .def_readwrite("nt", &Gather::nt) + .def_readwrite("nx", &Gather::nx) + .def("__str__", &Gather::display); +} diff --git a/src/core/gather/gather.cpp b/src/core/gather/gather.cpp index 1a2ea23..fed6777 100644 --- a/src/core/gather/gather.cpp +++ b/src/core/gather/gather.cpp @@ -2,10 +2,8 @@ // Created by dg on 6/8/25. // -#include "../libseis/gather.hpp" +#include "gather.hpp" #include -#include -#include #include #include #include @@ -13,67 +11,66 @@ #include #include -// Equivalent of the C struct. Ideally move to a header file. -struct Gather { - int id; - int nt; - int nx; - double dt; - std::vector data; -}; +// struct Gather { +// int id; +// int nt; +// int nx; +// double dt; +// std::vector data; +// }; -std::vector read_double(const std::string &path, int nt, int nx) { - std::ifstream file(path, std::ios::binary); - if (!file) { - throw std::runtime_error("Unable to open file at " + path); - } - - std::vector data(nt * nx); - file.read(reinterpret_cast(data.data()), nt * nx * sizeof(double)); - if (!file) { - throw std::runtime_error("Failed to read data from file at " + path); - } - - return data; -} - -void write_double(const std::string &path, const std::vector &data, - int nt, int nx) { - std::ofstream file(path, std::ios::binary); - if (!file) { - throw std::runtime_error("Unable to open file at " + path); - } - - file.write(reinterpret_cast(data.data()), - nt * nx * sizeof(double)); - if (!file) { - throw std::runtime_error("Failed to write data to file at " + path); - } -} - -std::unique_ptr gain_gather(const Gather &gather, double power) { - auto new_gather = std::make_unique(gather); - new_gather->data.resize(gather.nt * gather.nx); - - for (int trace_index = 0; trace_index < gather.nx; ++trace_index) { - for (int sample_index = 0; sample_index < gather.nt; ++sample_index) { - double time = static_cast(sample_index) * gather.dt; - double t_pow = std::pow(time, power); - int data_index = trace_index * gather.nt + sample_index; - new_gather->data[data_index] = gather.data[data_index] * t_pow; - } - } - - return new_gather; -} - -void display_gather(const Gather &gather) { - std::cout << "--------------------\n"; - std::cout << "Gather: id " << gather.id << '\n'; - std::cout << "Sample Rate: " << gather.dt << " seconds\n"; - std::cout << "Sampling Frequency: " << 1.0 / gather.dt << " Hz\n"; - std::cout << "Nyquist Frequency: " << 1.0 / (2 * gather.dt) << " Hz\n"; - std::cout << "Samples per trace: " << gather.nt << '\n'; - std::cout << "Number of traces: " << gather.nx << '\n'; - std::cout << "--------------------\n"; -} +// std::vector read_double(const std::string &path, int nt, int nx) { +// std::ifstream file(path, std::ios::binary); +// if (!file) { +// throw std::runtime_error("Unable to open file at " + path); +// } +// +// std::vector data(nt * nx); +// file.read(reinterpret_cast(data.data()), nt * nx * sizeof(double)); +// if (!file) { +// throw std::runtime_error("Failed to read data from file at " + path); +// } +// +// return data; +// } +// +// void write_double(const std::string &path, const std::vector &data, +// int nt, int nx) { +// std::ofstream file(path, std::ios::binary); +// if (!file) { +// throw std::runtime_error("Unable to open file at " + path); +// } +// +// file.write(reinterpret_cast(data.data()), +// nt * nx * sizeof(double)); +// if (!file) { +// throw std::runtime_error("Failed to write data to file at " + path); +// } +// } +// +// std::unique_ptr gain_gather(const Gather &gather, double power) { +// auto new_gather = std::make_unique(gather); +// new_gather->data.resize(gather.nt * gather.nx); +// +// for (int trace_index = 0; trace_index < gather.nx; ++trace_index) { +// for (int sample_index = 0; sample_index < gather.nt; ++sample_index) { +// double time = static_cast(sample_index) * gather.dt; +// double t_pow = std::pow(time, power); +// int data_index = trace_index * gather.nt + sample_index; +// new_gather->data[data_index] = gather.data[data_index] * t_pow; +// } +// } +// +// return new_gather; +// } +// +// void display_gather(const Gather &gather) { +// std::cout << "--------------------\n"; +// std::cout << "Gather: id " << gather.id << '\n'; +// std::cout << "Sample Rate: " << gather.dt << " seconds\n"; +// std::cout << "Sampling Frequency: " << 1.0 / gather.dt << " Hz\n"; +// std::cout << "Nyquist Frequency: " << 1.0 / (2 * gather.dt) << " Hz\n"; +// std::cout << "Samples per trace: " << gather.nt << '\n'; +// std::cout << "Number of traces: " << gather.nx << '\n'; +// std::cout << "--------------------\n"; +// } diff --git a/src/core/gather/gather.hpp b/src/core/gather/gather.hpp index be4b054..1db6155 100644 --- a/src/core/gather/gather.hpp +++ b/src/core/gather/gather.hpp @@ -4,5 +4,17 @@ #ifndef GATHER_H #define GATHER_H +#include + +class Gather { +public: + int id; + int nt; + int nx; + double dt; + [[nodiscard]] std::string display() const { + return "Gather id: " + std::to_string(id); + } +}; #endif // GATHER_H diff --git a/src/libseis/__init__.py b/src/libseis/__init__.py index 8fd0fd6..78911ea 100644 --- a/src/libseis/__init__.py +++ b/src/libseis/__init__.py @@ -1,4 +1,5 @@ +from ._gather import Gather from ._num import __doc__, add from .math import add_one -__all__ = ["__doc__", "add", "add_one"] +__all__ = ["Gather", "__doc__", "add", "add_one"] diff --git a/src/libseis/_gather.pyi b/src/libseis/_gather.pyi new file mode 100644 index 0000000..2d44b64 --- /dev/null +++ b/src/libseis/_gather.pyi @@ -0,0 +1,10 @@ +from typing import Self + +class Gather: + """ + A seismic gather. + """ + + id: int + + def __init__(self) -> Self: ... diff --git a/tests/libseis/test_add.py b/tests/libseis/test_add.py index 2ece910..4292a13 100644 --- a/tests/libseis/test_add.py +++ b/tests/libseis/test_add.py @@ -1,11 +1,17 @@ -import libseis +from libseis import add, add_one class TestLibseis: + """This is just here while we set up pybind11, cmake, pytest, etc. + + The add example function can be removed once we're at a place where we don't + need to test the build system. + """ + def test_add(self): expected = 7 - assert libseis.add(3, 4) == expected + assert add(3, 4) == expected def test_add_one(self): expected = 4 - assert libseis.add_one(3) == expected + assert add_one(3) == expected diff --git a/tests/libseis/test_gather.py b/tests/libseis/test_gather.py new file mode 100644 index 0000000..e2caa10 --- /dev/null +++ b/tests/libseis/test_gather.py @@ -0,0 +1,29 @@ +import pytest + +from libseis import Gather + + +class TestSeismicGather: + """Test the Gather class from.""" + + @pytest.fixture + def gather(self): + """Fixture to create a Gather instance.""" + return Gather() + + def test_gather_init(self, gather): + """Test the Gather class base constructor.""" + assert isinstance(gather, Gather) + + @pytest.mark.parametrize("attr", ["id", "dt", "nx", "nt"]) + def test_public_int_attributes(self, gather, attr): + """Test that the id attribute is publicly accessible.""" + val = 42 + setattr(gather, attr, val) + assert getattr(gather, attr) == val + + def test_gather_has_str_method(self, gather, capfd): + """Test the Gather class __str__.""" + print(gather) # noqa: T201 + out, _ = capfd.readouterr() + assert "Gather" in out From c422f45d710ed5cacdaeaf03beeda766cc35cd10 Mon Sep 17 00:00:00 2001 From: David Graham Date: Sun, 8 Jun 2025 20:36:25 -0400 Subject: [PATCH 7/8] add ruff to dev deps --- pyproject.toml | 1 + uv.lock | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index ec36902..9d954f9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ dev = [ "pre-commit>=4.2.0", "pytest>=8.4.0", + "ruff>=0.11.13", ] [build-system] diff --git a/uv.lock b/uv.lock index b856d2a..6b0741f 100644 --- a/uv.lock +++ b/uv.lock @@ -77,6 +77,7 @@ source = { editable = "." } dev = [ { name = "pre-commit" }, { name = "pytest" }, + { name = "ruff" }, ] [package.metadata] @@ -85,6 +86,7 @@ dev = [ dev = [ { name = "pre-commit", specifier = ">=4.2.0" }, { name = "pytest", specifier = ">=8.4.0" }, + { name = "ruff", specifier = ">=0.11.13" }, ] [[package]] @@ -210,6 +212,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, ] +[[package]] +name = "ruff" +version = "0.11.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/da/9c6f995903b4d9474b39da91d2d626659af3ff1eeb43e9ae7c119349dba6/ruff-0.11.13.tar.gz", hash = "sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514", size = 4282054, upload-time = "2025-06-05T21:00:15.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/ce/a11d381192966e0b4290842cc8d4fac7dc9214ddf627c11c1afff87da29b/ruff-0.11.13-py3-none-linux_armv6l.whl", hash = "sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46", size = 10292516, upload-time = "2025-06-05T20:59:32.944Z" }, + { url = "https://files.pythonhosted.org/packages/78/db/87c3b59b0d4e753e40b6a3b4a2642dfd1dcaefbff121ddc64d6c8b47ba00/ruff-0.11.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48", size = 11106083, upload-time = "2025-06-05T20:59:37.03Z" }, + { url = "https://files.pythonhosted.org/packages/77/79/d8cec175856ff810a19825d09ce700265f905c643c69f45d2b737e4a470a/ruff-0.11.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b", size = 10436024, upload-time = "2025-06-05T20:59:39.741Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5b/f6d94f2980fa1ee854b41568368a2e1252681b9238ab2895e133d303538f/ruff-0.11.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a", size = 10646324, upload-time = "2025-06-05T20:59:42.185Z" }, + { url = "https://files.pythonhosted.org/packages/6c/9c/b4c2acf24ea4426016d511dfdc787f4ce1ceb835f3c5fbdbcb32b1c63bda/ruff-0.11.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc", size = 10174416, upload-time = "2025-06-05T20:59:44.319Z" }, + { url = "https://files.pythonhosted.org/packages/f3/10/e2e62f77c65ede8cd032c2ca39c41f48feabedb6e282bfd6073d81bb671d/ruff-0.11.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629", size = 11724197, upload-time = "2025-06-05T20:59:46.935Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f0/466fe8469b85c561e081d798c45f8a1d21e0b4a5ef795a1d7f1a9a9ec182/ruff-0.11.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933", size = 12511615, upload-time = "2025-06-05T20:59:49.534Z" }, + { url = "https://files.pythonhosted.org/packages/17/0e/cefe778b46dbd0cbcb03a839946c8f80a06f7968eb298aa4d1a4293f3448/ruff-0.11.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165", size = 12117080, upload-time = "2025-06-05T20:59:51.654Z" }, + { url = "https://files.pythonhosted.org/packages/5d/2c/caaeda564cbe103bed145ea557cb86795b18651b0f6b3ff6a10e84e5a33f/ruff-0.11.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71", size = 11326315, upload-time = "2025-06-05T20:59:54.469Z" }, + { url = "https://files.pythonhosted.org/packages/75/f0/782e7d681d660eda8c536962920c41309e6dd4ebcea9a2714ed5127d44bd/ruff-0.11.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9", size = 11555640, upload-time = "2025-06-05T20:59:56.986Z" }, + { url = "https://files.pythonhosted.org/packages/5d/d4/3d580c616316c7f07fb3c99dbecfe01fbaea7b6fd9a82b801e72e5de742a/ruff-0.11.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc", size = 10507364, upload-time = "2025-06-05T20:59:59.154Z" }, + { url = "https://files.pythonhosted.org/packages/5a/dc/195e6f17d7b3ea6b12dc4f3e9de575db7983db187c378d44606e5d503319/ruff-0.11.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7", size = 10141462, upload-time = "2025-06-05T21:00:01.481Z" }, + { url = "https://files.pythonhosted.org/packages/f4/8e/39a094af6967faa57ecdeacb91bedfb232474ff8c3d20f16a5514e6b3534/ruff-0.11.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432", size = 11121028, upload-time = "2025-06-05T21:00:04.06Z" }, + { url = "https://files.pythonhosted.org/packages/5a/c0/b0b508193b0e8a1654ec683ebab18d309861f8bd64e3a2f9648b80d392cb/ruff-0.11.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492", size = 11602992, upload-time = "2025-06-05T21:00:06.249Z" }, + { url = "https://files.pythonhosted.org/packages/7c/91/263e33ab93ab09ca06ce4f8f8547a858cc198072f873ebc9be7466790bae/ruff-0.11.13-py3-none-win32.whl", hash = "sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250", size = 10474944, upload-time = "2025-06-05T21:00:08.459Z" }, + { url = "https://files.pythonhosted.org/packages/46/f4/7c27734ac2073aae8efb0119cae6931b6fb48017adf048fdf85c19337afc/ruff-0.11.13-py3-none-win_amd64.whl", hash = "sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3", size = 11548669, upload-time = "2025-06-05T21:00:11.147Z" }, + { url = "https://files.pythonhosted.org/packages/ec/bf/b273dd11673fed8a6bd46032c0ea2a04b2ac9bfa9c628756a5856ba113b0/ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b", size = 10683928, upload-time = "2025-06-05T21:00:13.758Z" }, +] + [[package]] name = "tomli" version = "2.2.1" From d802a7dac7c4c3ae90a7cca63ef5cf42b7a9f152 Mon Sep 17 00:00:00 2001 From: David Graham Date: Sun, 8 Jun 2025 21:18:37 -0400 Subject: [PATCH 8/8] Update CI pipeline, remove macos for time being --- .github/workflows/CI.yml | 28 ++++++++++++++++------------ pyproject.toml | 5 +++++ uv.lock | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ba19783..a935dd5 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ "*" ] + branches: + - "main" pull_request: - branches: [ "main" ] env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) @@ -17,19 +17,22 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-latest, macos-latest ] + os: [ ubuntu-latest ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - name: Configure CMake + - name: 'Install dependencies' + run: sudo apt-get install -y cmake pybind11-dev + + - name: 'Configure CMake' run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - - name: Build + - name: 'Build' run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - name: Test + - name: 'Test' working-directory: ${{github.workspace}}/build # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: ctest -C ${{env.BUILD_TYPE}} @@ -38,14 +41,14 @@ jobs: name: "Python Tests" strategy: matrix: - os: [ ubuntu-latest, macos-latest ] + os: [ ubuntu-latest ] python-version: [ '3.10', '3.11', '3.12', '3.13' ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - name: Set up Python + - name: 'Set up Python' uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -54,9 +57,10 @@ jobs: uses: astral-sh/setup-uv@v5 with: cache-dependency-glob: "**/pyproject.toml" + enable-cache: true - - name: Install dependencies + - name: 'Install dependencies' run: uv sync --locked --all-extras --dev - name: 'Run unit tests' - run: pytest -n auto + run: uv run pytest -n auto diff --git a/pyproject.toml b/pyproject.toml index 9d954f9..00836d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,10 +20,15 @@ classifiers = [ [dependency-groups] +build = [ + "pybind11>=2.13.6", +] dev = [ "pre-commit>=4.2.0", "pytest>=8.4.0", + "pytest-xdist>=3.7.0", "ruff>=0.11.13", + { include-group = "build" }, ] [build-system] diff --git a/uv.lock b/uv.lock index 6b0741f..9dee61e 100644 --- a/uv.lock +++ b/uv.lock @@ -41,6 +41,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, ] +[[package]] +name = "execnet" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/ff/b4c0dc78fbe20c3e59c0c7334de0c27eb4001a2b2017999af398bf730817/execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3", size = 166524, upload-time = "2024-04-08T09:04:19.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612, upload-time = "2024-04-08T09:04:17.414Z" }, +] + [[package]] name = "filelock" version = "3.18.0" @@ -74,18 +83,26 @@ version = "0.0.2" source = { editable = "." } [package.dev-dependencies] +build = [ + { name = "pybind11" }, +] dev = [ { name = "pre-commit" }, + { name = "pybind11" }, { name = "pytest" }, + { name = "pytest-xdist" }, { name = "ruff" }, ] [package.metadata] [package.metadata.requires-dev] +build = [{ name = "pybind11", specifier = ">=2.13.6" }] dev = [ { name = "pre-commit", specifier = ">=4.2.0" }, + { name = "pybind11", specifier = ">=2.13.6" }, { name = "pytest", specifier = ">=8.4.0" }, + { name = "pytest-xdist", specifier = ">=3.7.0" }, { name = "ruff", specifier = ">=0.11.13" }, ] @@ -141,6 +158,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, ] +[[package]] +name = "pybind11" +version = "2.13.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d2/c1/72b9622fcb32ff98b054f724e213c7f70d6898baa714f4516288456ceaba/pybind11-2.13.6.tar.gz", hash = "sha256:ba6af10348c12b24e92fa086b39cfba0eff619b61ac77c406167d813b096d39a", size = 218403, upload-time = "2024-09-14T00:35:22.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/2f/0f24b288e2ce56f51c920137620b4434a38fd80583dbbe24fc2a1656c388/pybind11-2.13.6-py3-none-any.whl", hash = "sha256:237c41e29157b962835d356b370ededd57594a26d5894a795960f0047cb5caf5", size = 243282, upload-time = "2024-09-14T00:35:20.361Z" }, +] + [[package]] name = "pygments" version = "2.19.1" @@ -168,6 +194,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2f/de/afa024cbe022b1b318a3d224125aa24939e99b4ff6f22e0ba639a2eaee47/pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e", size = 363797, upload-time = "2025-06-02T17:36:27.859Z" }, ] +[[package]] +name = "pytest-xdist" +version = "3.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/dc/865845cfe987b21658e871d16e0a24e871e00884c545f246dd8f6f69edda/pytest_xdist-3.7.0.tar.gz", hash = "sha256:f9248c99a7c15b7d2f90715df93610353a485827bc06eefb6566d23f6400f126", size = 87550, upload-time = "2025-05-26T21:18:20.251Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/b2/0e802fde6f1c5b2f7ae7e9ad42b83fd4ecebac18a8a8c2f2f14e39dce6e1/pytest_xdist-3.7.0-py3-none-any.whl", hash = "sha256:7d3fbd255998265052435eb9daa4e99b62e6fb9cfb6efd1f858d4d8c0c7f0ca0", size = 46142, upload-time = "2025-05-26T21:18:18.759Z" }, +] + [[package]] name = "pyyaml" version = "6.0.2"