Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
552a5bc
add tests for building with pip using the shared library
phlptp Mar 26, 2025
ec509ac
try installing shared library
phlptp Mar 26, 2025
9ef937c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 26, 2025
d6704f9
try different install command for shared library
phlptp Mar 26, 2025
6ba7f93
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 26, 2025
7fdec89
try to add RPATH to python library for unix like systems
phlptp Mar 27, 2025
7346ce1
Merge branch 'test_pip_shared' of https://github.com/LLNL/units into …
phlptp Mar 27, 2025
2121c69
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 27, 2025
f536641
not strip install rpath
phlptp Mar 27, 2025
5ce1ce8
Merge branch 'test_pip_shared' of https://github.com/LLNL/units into …
phlptp Mar 27, 2025
c3fef23
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 27, 2025
93fed83
add cmake rpath specification
phlptp Mar 27, 2025
95c8acb
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 27, 2025
83e94dd
rework packaging for shared library with python library
phlptp Mar 28, 2025
6e16a60
update pip workflows
phlptp Mar 28, 2025
e04c4a5
tweak tests
phlptp Mar 28, 2025
8c82b6b
try exporting LD_LIBRARY_PATH in test
phlptp Mar 28, 2025
11e7bcf
move the LD_LIBRARY command
phlptp Mar 28, 2025
305892c
add some methods
phlptp Mar 29, 2025
30dda7b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 29, 2025
aa7c2dd
rework the method for __format__
phlptp Mar 29, 2025
af13d4f
Merge branch 'test_pip_shared' of https://github.com/LLNL/units into …
phlptp Mar 29, 2025
3a12340
update the format method
phlptp Mar 29, 2025
0c009cf
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 29, 2025
9309fe3
update test and format code
phlptp Mar 29, 2025
dc0d27b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 30, 2025
7c1934e
fine tuning of format, not use std::to_string
phlptp Mar 30, 2025
d6399dd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 30, 2025
f1a5c2e
fix a test
phlptp Mar 30, 2025
ddeb647
Merge branch 'test_pip_shared' of https://github.com/LLNL/units into …
phlptp Mar 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion .github/workflows/pip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
fail-fast: false
matrix:
platform: [windows-latest, macos-latest, ubuntu-latest, ubuntu-24.04-arm]
python-version: ["3.10", "3.12"]
python-version: ["3.12", "3.13"]

steps:
- uses: actions/checkout@v4
Expand All @@ -33,3 +33,65 @@ jobs:

- name: Test
run: python -m pytest ./test/python

build_shared:
name: Build with Pip shared lib
runs-on: ${{ matrix.platform }}
strategy:
fail-fast: false
matrix:
platform: [ macos-latest, ubuntu-latest]
python-version: ["3.13"]

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Set min macOS version
if: runner.os == 'macOS'
run: |
echo "MACOSX_DEPLOYMENT_TARGET=11.0" >> $GITHUB_ENV

- name: Build and install
run: |
mkdir -p build
cd build
cmake .. -DUNITS_BUILD_SHARED_LIBRARY=ON -DUNITS_BUILD_STATIC_LIBRARY=OFF -DUNITS_INSTALL=ON
make -j 4
sudo make install
cd ..
python -m pip install pytest
pip install -vv -C cmake.define.UNITS_BUILD_SHARED_LIBRARY:BOOL=ON -C cmake.define.UNITS_BUILD_STATIC_LIBRARY:BOOL=OFF .

- name: Test
run: |
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib"
export DYLD_FALLBACK_LIBRARY_PATH="$DYLD_FALLBACK_LIBRARY_PATH:/usr/local/lib"
python -m pytest ./test/python

build_shared_windows:
name: Build with Pip shared lib
runs-on: ${{ matrix.platform }}
strategy:
fail-fast: false
matrix:
platform: [windows-latest]
python-version: ["3.12", "3.13"]

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Build and install
run: |
python -m pip install pytest
pip install -vv -C cmake.define.UNITS_BUILD_SHARED_LIBRARY:BOOL=ON -C cmake.define.UNITS_BUILD_STATIC_LIBRARY:BOOL=OFF -C cmake.define.UNITS_PYTHON_INSTALL_SHARED_LIBRARY:BOOL=ON .

- name: Test
run: python -m pytest ./test/python
29 changes: 29 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,36 @@ if(NOT UNITS_HEADER_ONLY AND UNITS_BUILD_PYTHON_LIBRARY)

# Install directive for scikit-build-core
install(TARGETS units_llnl_ext LIBRARY DESTINATION units_llnl)
if(UNITS_BUILD_SHARED_LIBRARY AND UNITS_PYTHON_INSTALL_SHARED_LIBRARY)

# -------------------------------------------------------------
# setting the RPATH
# -------------------------------------------------------------
if(NOT DEFINED CMAKE_MACOSX_RPATH)
set(CMAKE_MACOSX_RPATH ON)
endif()

# add the automatically determined parts of the RPATH which point to directories
# outside the build tree to the install RPATH
if(NOT DEFINED CMAKE_INSTALL_RPATH_USE_LINK_PATH)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
endif()

# Add the local directory to the rpath
if(NOT APPLE)
list(APPEND CMAKE_INSTALL_RPATH "$ORIGIN")
else()
list(APPEND CMAKE_INSTALL_RPATH "@loader_path")
list(APPEND CMAKE_INSTALL_RPATH "@executable_path")
endif()

install(
TARGETS units
RUNTIME DESTINATION units_llnl
ARCHIVE DESTINATION units_llnl
LIBRARY DESTINATION units_llnl
)
endif()
endif()

if(UNITS_INSTALL AND NOT SKBUILD)
Expand Down
102 changes: 67 additions & 35 deletions python/units_python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ SPDX-License-Identifier: BSD-3-Clause

#include "units/units.hpp"
#include "units/units_math.hpp"
#include <algorithm>
#include <sstream>

namespace nb = nanobind;

using namespace nb::literals;
Expand Down Expand Up @@ -140,35 +143,38 @@ NB_MODULE(units_llnl_ext, mod)
"__mul__",
[](const units::precise_unit& unit,
const std::vector<double>& mult) {
std::vector<units::precise_measurement> results;
results.resize(mult.size());
for (std::size_t ii = 0; ii < mult.size(); ++ii) {
results[ii] = mult[ii] * unit;
}
std::vector<units::precise_measurement> results(mult.size());
std::transform(
mult.begin(),
mult.end(),
results.begin(),
[&unit](double value) { return value * unit; });
return results;
},
nb::is_operator())
.def(
"__rmul__",
[](const units::precise_unit& unit,
const std::vector<double>& mult) {
std::vector<units::precise_measurement> results;
results.resize(mult.size());
for (std::size_t ii = 0; ii < mult.size(); ++ii) {
results[ii] = mult[ii] * unit;
}
std::vector<units::precise_measurement> results(mult.size());
std::transform(
mult.begin(),
mult.end(),
results.begin(),
[&unit](double value) { return value * unit; });
return results;
},
nb::is_operator())
.def(
"__rlshift__",
[](const units::precise_unit& unit,
const std::vector<double>& mult) {
std::vector<units::precise_measurement> results;
results.resize(mult.size());
for (std::size_t ii = 0; ii < mult.size(); ++ii) {
results[ii] = mult[ii] * unit;
}
std::vector<units::precise_measurement> results(mult.size());
std::transform(
mult.begin(),
mult.end(),
results.begin(),
[&unit](double value) { return value * unit; });
return results;
},
nb::is_operator())
Expand Down Expand Up @@ -549,25 +555,48 @@ NB_MODULE(units_llnl_ext, mod)
.def(
"__format__",
[](const units::precise_measurement& measurement,
std::string fmt_string) {
std::string fmt_string) -> std::string {
std::string result;
if (fmt_string.empty()) {
return units::to_string(measurement);
}
if (fmt_string == "-") {
return units::to_string(
units::precise_measurement(
measurement.value(), units::precise::one));
}
if (fmt_string.front() == '-') {
return units::to_string(
units::precise_measurement(
measurement.value_as(
units::unit_from_string(fmt_string.substr(1))),
units::precise::one));
result = units::to_string(measurement);
} else if (fmt_string == "-") {
std::stringstream ss;
ss.precision(12);
ss << measurement.value();
result = ss.str();
} else if (fmt_string.front() == '-') {
auto target_unit =
units::unit_from_string(fmt_string.substr(1));
if (!units::is_valid(target_unit)) {
throw std::invalid_argument(
"Invalid unit in format string " +
fmt_string.substr(1));
}
auto new_value = measurement.value_as(target_unit);
if (std::isnan(new_value)) {
throw std::invalid_argument(
"Units are not compatible with given measurement " +
fmt_string.substr(1));
}
std::stringstream ss;
ss.precision(12);
ss << new_value;
result = ss.str();
} else {
return units::to_string(measurement.convert_to(
units::unit_from_string(fmt_string)));
auto target_unit = units::unit_from_string(fmt_string);
if (!units::is_valid(target_unit)) {
throw std::invalid_argument(
"Invalid unit in format string " + fmt_string);
}
auto new_meas = measurement.convert_to(target_unit);
if (!units::is_valid(new_meas)) {
throw std::invalid_argument(
"Units are not compatible with given measurement " +
fmt_string);
}
result = units::to_string(new_meas);
}
return result;
})
.def_prop_ro(
"dimension",
Expand All @@ -589,6 +618,11 @@ NB_MODULE(units_llnl_ext, mod)
[](const units::precise_measurement& measurement) {
return -measurement;
})
.def(
"__pos__",
[](const units::precise_measurement& measurement) {
return measurement;
})
.def(
"__invert__",
[](const units::precise_measurement& measurement) {
Expand Down Expand Up @@ -707,14 +741,12 @@ NB_MODULE(units_llnl_ext, mod)
.def(
"__rtruediv__",
[](const Dimension& dim1, double val) {
return Dimension{units::precise::one / dim1.base};
return Dimension{dim1.base.inv()};
},
nb::is_operator())
.def(
"__invert__",
[](const Dimension& dim) {
return Dimension{units::precise::one / dim.base};
})
[](const Dimension& dim) { return Dimension{dim.base.inv()}; })
.def(
"__pow__",
[](const Dimension& dim, int power) {
Expand Down
40 changes: 39 additions & 1 deletion test/python/test_measurement.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ def test_negation():
assert m3.value == -15.0


def test_pos():
m1 = u.Measurement("15 seconds")
m3 = +m1
assert m1 == m3


def test_conditions():
m1 = u.Measurement(34.5, "fq2te1tg1fe")
assert not m1
Expand Down Expand Up @@ -259,11 +265,43 @@ def test_format():
assert "kg" in s1

s2 = f"the measurement is {m1:-}"
assert s2 == "the measurement is 9.7552 "
assert s2 == "the measurement is 9.7552"

s3 = f"the measurement is {m1:-kg}"
assert "kg" not in s3

m3 = u.Measurement("3.4")

s4 = f"the measurement is {m3:-}"
assert "3.4" in s4


def test_format_error():
m1 = u.Measurement("9.7552 lb")
try:
s1 = f"the measurement is {m1:A}"
assert False
except ValueError:
assert True

try:
s1 = f"the measurement is {m1:sgsg2362yqbvwsdddddqwadsa}"
assert False
except ValueError:
assert True

try:
s1 = f"the measurement is {m1:-A}"
assert False
except ValueError:
assert True

try:
s1 = f"the measurement is {m1:-sgsg2362yqbvwsdddddqwadsa}"
assert False
except ValueError:
assert True


def test_close():
m1 = u.Measurement("10 lb")
Expand Down
Loading