NREL / OpenStudio

OpenStudio is a cross-platform collection of software tools to support whole building energy modeling using EnergyPlus and advanced daylight analysis using Radiance.
https://www.openstudio.net/
Other
506 stars 192 forks source link

Unable to run template ModelMeasure Python test with 3.8.0 CLI on mac #5271

Closed jmarrec closed 1 month ago

jmarrec commented 1 month ago

Looks like this should have been fixed through https://github.com/NREL/OpenStudio/pull/5008 but I am still getting errors on Openstudio version: 3.8.0+f953b6fcaf, M1 Pro Mac, Ventura 13.7

openstudio test_model_measure.py

Traceback ``` Traceback (most recent call last): File "", line 10, in File "", line 843, in exec_module File "", line 219, in _call_with_frames_removed File "/Users/radhikar/Documents/OpenStudio/src/utilities/bcl/templates/ModelMeasure/tests/test_model_measure.py", line 150, in pytest.main() File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 155, in main config = _prepareconfig(args, plugins) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 337, in _prepareconfig config = pluginmanager.hook.pytest_cmdline_parse( File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_hooks.py", line 513, in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_manager.py", line 120, in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_callers.py", line 139, in _multicall raise exception.with_traceback(exception.__traceback__) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_callers.py", line 122, in _multicall teardown.throw(exception) # type: ignore[union-attr] File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/helpconfig.py", line 105, in pytest_cmdline_parse config = yield File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_callers.py", line 103, in _multicall res = hook_impl.function(*args) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 1143, in pytest_cmdline_parse self.parse(args) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 1492, in parse self._preparse(args, addopts=addopts) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 1379, in _preparse self.pluginmanager.load_setuptools_entrypoints("pytest11") File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_manager.py", line 421, in load_setuptools_entrypoints plugin = ep.load() File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/importlib/metadata.py", line 77, in load module = import_module(match.group('module')) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "", line 1014, in _gcd_import File "", line 991, in _find_and_load File "", line 975, in _find_and_load_unlocked File "", line 671, in _load_unlocked File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/assertion/rewrite.py", line 178, in exec_module exec(co, module.__dict__) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pytest_cov/plugin.py", line 9, in import coverage File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/__init__.py", line 24, in from coverage.control import ( File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/control.py", line 28, in from coverage.collector import Collector, HAS_CTRACER File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/collector.py", line 19, in from coverage.data import CoverageData File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/data.py", line 24, in from coverage.sqldata import CoverageData File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/sqldata.py", line 16, in import sqlite3 File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/sqlite3/__init__.py", line 23, in from sqlite3.dbapi2 import * File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/sqlite3/dbapi2.py", line 27, in from _sqlite3 import * ImportError: dlopen(/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/lib-dynload/_sqlite3.cpython-38-darwin.so, 0x0002): Symbol not found: _sqlite3_enable_load_extension Referenced from: <9F88F376-4444-3BC2-BD26-89AD0EF1CCEE> /Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/lib-dynload/_sqlite3.cpython-38-darwin.so Expected in: <2EF69864-7D8D-3BA6-BBA3-46A6CDC7B1B9> /usr/lib/libsqlite3.dylib Failed to execute '/Users/radhikar/Documents/OpenStudio/src/utilities/bcl/templates/ModelMeasure/tests/test_model_measure.py' ```

Originally posted by @rajeee in https://github.com/NREL/OpenStudio/issues/4992#issuecomment-2400681604

jmarrec commented 1 month ago

M1 Max, on Sequioa 15.1, works plenty fine here.

otool -L /Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/lib-dynload/_sqlite3.cpython-38-darwin.so
/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/lib-dynload/_sqlite3.cpython-38-darwin.so:
    /usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 344.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)

I don't have /usr/lib/libsqlite3.dylib. But I do have a brew one

$ locate libsqlite3.dylib
/opt/homebrew/Cellar/sqlite/3.46.1/lib/libsqlite3.dylib

Try running through pytest directly with your system python.

pip install openstudio==3.8.0
cd src/utilities/bcl/templates/ModelMeasure/test
python -m pytest
rajeee commented 1 month ago

Thanks for creating this issue. Yeah, it works through the system python! That's what I ended up doing. So, this is no longer a blocker, but it would be nice to get this working through the CLI as well.

jmarrec commented 1 month ago

@rajee wait, were you also having issues on the docker NREL/3.8.0 (that's an ubuntu docker)?

jmarrec commented 1 month ago

Works fine, either through the CLI on the pytest file or via openstudio measure -r ., which will run pytest too. Maybe try that as well on your system?

$ cd src/utilities/bcl/templates
$ docker run -it --rm --platform linux/amd64 -v $(pwd):/var/simdata/openstudio/templates nrel/openstudio:3.8.0

Inside docker

cd templates/ModelMeasure
openstudio measure -r .

cd tests
openstudio test_model_measure.py
rajeee commented 1 month ago

@jmarrec Oh, maybe not. It didn't work for me locally, so I just put whatever worked locally to CI. But yeah, maybe it would have worked through the openstudio CLI on the CI on ubuntu docker.

jmarrec commented 1 month ago

Can you try openstudio measure --run_tests . locally please?

Also, can you post the output of these commands

otool -L /Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/lib-dynload/_sqlite3.cpython-38-darwin.so
locate libsqlite3.dylib
# if you have homebrew installed
brew info sqlite3
brew --prefix sqlite3
rajeee commented 1 month ago

Sure.

openstudio measure --run_tests . ─╯

Details ``` ┌────────────────────────────────────────────────────────────────────────────────┐ │ Starting Python Tests │ └────────────────────────────────────────────────────────────────────────────────┘ runPytestCmd= import pytest pytest.main([ "--junit-xml=/Users/radhikar/Documents/largee/resstock/test_results/pytest/junit.xml", "--cov=/Users/radhikar/Documents/largee/resstock", "--cov-report=term-missing", "--cov-report=json:/Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage.json", "--cov-report=lcov:/Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage.lcov", "--cov-report=html:/Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage_html", "--cov-report=xml:/Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage.xml", "-o", "junit_family=legacy", "/Users/radhikar/Documents/largee/resstock", ]) Traceback (most recent call last): File "", line 4, in File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 155, in main config = _prepareconfig(args, plugins) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 337, in _prepareconfig config = pluginmanager.hook.pytest_cmdline_parse( File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_hooks.py", line 513, in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_manager.py", line 120, in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_callers.py", line 139, in _multicall raise exception.with_traceback(exception.__traceback__) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_callers.py", line 122, in _multicall teardown.throw(exception) # type: ignore[union-attr] File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/helpconfig.py", line 105, in pytest_cmdline_parse config = yield File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_callers.py", line 103, in _multicall res = hook_impl.function(*args) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 1143, in pytest_cmdline_parse self.parse(args) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 1492, in parse self._preparse(args, addopts=addopts) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/config/__init__.py", line 1379, in _preparse self.pluginmanager.load_setuptools_entrypoints("pytest11") File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pluggy/_manager.py", line 421, in load_setuptools_entrypoints plugin = ep.load() File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/importlib/metadata.py", line 77, in load module = import_module(match.group('module')) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "", line 1014, in _gcd_import File "", line 991, in _find_and_load File "", line 975, in _find_and_load_unlocked File "", line 671, in _load_unlocked File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/_pytest/assertion/rewrite.py", line 178, in exec_module exec(co, module.__dict__) File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/pytest_cov/plugin.py", line 9, in import coverage File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/__init__.py", line 24, in from coverage.control import ( File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/control.py", line 28, in from coverage.collector import Collector, HAS_CTRACER File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/collector.py", line 19, in from coverage.data import CoverageData File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/data.py", line 24, in from coverage.sqldata import CoverageData File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/coverage/sqldata.py", line 16, in import sqlite3 File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/sqlite3/__init__.py", line 23, in from sqlite3.dbapi2 import * File "/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/sqlite3/dbapi2.py", line 27, in from _sqlite3 import * ImportError: dlopen(/Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/lib-dynload/_sqlite3.cpython-38-darwin.so, 0x0002): Symbol not found: _sqlite3_enable_load_extension Referenced from: <9F88F376-4444-3BC2-BD26-89AD0EF1CCEE> /Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/lib-dynload/_sqlite3.cpython-38-darwin.so Expected in: <2EF69864-7D8D-3BA6-BBA3-46A6CDC7B1B9> /usr/lib/libsqlite3.dylib Error executing Python code [1] 55261 segmentation fault openstudio measure --run_tests . ```

otool -L /Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/lib-dynload/_sqlite3.cpython-38-darwin.so ─╯

locate libsqlite3.dylib brew info sqlite3 brew --prefix sqlite3

Details ``` /Applications/OpenStudio-3.8.0/EnergyPlus/python_standard_lib/lib-dynload/_sqlite3.cpython-38-darwin.so: /usr/local/opt/sqlite/lib/libsqlite3.0.dylib (compatibility version 9.0.0, current version 9.6.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.0.0) WARNING: The locate database (/var/db/locate.database) does not exist. To create the database, run the following command: sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.locate.plist Please be aware that the database can take some time to generate; once the database has been created, this message will no longer appear. ==> sqlite: stable 3.46.1 (bottled) [keg-only] Command-line interface for SQLite https://sqlite.org/index.html Installed /opt/homebrew/Cellar/sqlite/3.46.1 (12 files, 4.8MB) Poured from bottle using the formulae.brew.sh API on 2024-10-08 at 13:45:51 From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/s/sqlite.rb License: blessing ==> Dependencies Required: readline ✔ ==> Caveats sqlite is keg-only, which means it was not symlinked into /opt/homebrew, because macOS already provides this software and installing another version in parallel can cause all kinds of trouble. If you need to have sqlite first in your PATH, run: echo 'export PATH="/opt/homebrew/opt/sqlite/bin:$PATH"' >> ~/.zshrc For compilers to find sqlite you may need to set: export LDFLAGS="-L/opt/homebrew/opt/sqlite/lib" export CPPFLAGS="-I/opt/homebrew/opt/sqlite/include" For pkg-config to find sqlite you may need to set: export PKG_CONFIG_PATH="/opt/homebrew/opt/sqlite/lib/pkgconfig" ==> Analytics install: 209,328 (30 days), 671,250 (90 days), 2,745,980 (365 days) install-on-request: 7,339 (30 days), 28,016 (90 days), 164,593 (365 days) build-error: 0 (30 days) /opt/homebrew/opt/sqlite ```
jmarrec commented 1 month ago

I find the otool suspicious. /usr/local/opt/sqlite/lib/libsqlite3.0.dylib... Are you 100% sure you installed the arm64 mac installer and not the x86_64 one? Can you do

$ file /Applications/OpenStudio-3.8.0/bin/openstudio
/Applications/OpenStudio-3.8.0/bin/openstudio: Mach-O 64-bit executable arm64

and

$ which openstudio
/usr/local/bin/openstudio
ls -la $(which openstudio)
lrwxr-xr-x@ 1 root  wheel  45 May 22 14:31 /usr/local/bin/openstudio -> /Applications/OpenStudio-3.8.0/bin/openstudio
$ /Applications/OpenStudio-3.8.0/bin/openstudio --version
3.8.0+f953b6fcaf
rajeee commented 1 month ago

Huh, looks like I mistakenly installed the x86_64 version.

file /Applications/OpenStudio-3.8.0/bin/openstudio ─╯ /Applications/OpenStudio-3.8.0/bin/openstudio: Mach-O 64-bit executable x86_64

Openstudio seems fine.

$ which openstudio
/usr/local/bin/openstudio
ls -la $(which openstudio)
lrwxr-xr-x@ 1 root  admin  45 Jul  1 09:15 /usr/local/bin/openstudio -> /Applications/OpenStudio-3.8.0/bin/openstudio
$ /Applications/OpenStudio-3.8.0/bin/openstudio --version
3.8.0+f953b6fcaf

I will try the arm64 version and report back. Pretty interesting that x86_64 version has been carrying me this far though!

rajeee commented 1 month ago

On a separate note, I remember seeing something about Mac installer being code signed. I thought it would prevent this:

image

jmarrec commented 1 month ago

Nope, only E+ is signed currently, and OSApp 1.8.0. For OS SDK, I filed

rajeee commented 1 month ago

Happy to report it's working now. Sorry about the operator-error!

─ openstudio measure --run_tests .                                                                                                                  ─╯
┌────────────────────────────────────────────────────────────────────────────────┐
│                             Starting Python Tests                              │
└────────────────────────────────────────────────────────────────────────────────┘
runPytestCmd=
import pytest

pytest.main([
  "--junit-xml=/Users/radhikar/Documents/largee/resstock/test_results/pytest/junit.xml",
  "--cov=/Users/radhikar/Documents/largee/resstock",
  "--cov-report=term-missing",
  "--cov-report=json:/Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage.json",
  "--cov-report=lcov:/Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage.lcov",
  "--cov-report=html:/Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage_html",
  "--cov-report=xml:/Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage.xml",
  "-o", "junit_family=legacy",
  "/Users/radhikar/Documents/largee/resstock",
])

================================================================= test session starts ==================================================================
platform darwin -- Python 3.8.12, pytest-8.1.1, pluggy-1.5.0
rootdir: /Users/radhikar/Documents/largee/resstock
plugins: cov-5.0.0
collected 12 items

measures/LoadFlexibility/tests/test_load_flexibility.py .                                                                                        [  8%]
measures/LoadFlexibility/tests/test_setpoint.py ...........                                                                                      [100%]

----------------------------- generated xml file: /Users/radhikar/Documents/largee/resstock/test_results/pytest/junit.xml ------------------------------

---------- coverage: platform darwin, python 3.8.12-final-0 ----------
Name                                                      Stmts   Miss  Cover   Missing
---------------------------------------------------------------------------------------
measures/LoadFlexibility/measure.py                          97     58    40%   20-23, 46, 54, 64, 83-86, 89-93, 96-106, 115-167
measures/LoadFlexibility/resources/__init__.py                0      0   100%
measures/LoadFlexibility/resources/input_helper.py           90      4    96%   51-54, 66
measures/LoadFlexibility/resources/setpoint.py              168     47    72%   48, 88, 92-95, 131-132, 137, 163-164, 169, 192-193, 198, 213-225, 228-233, 239-266
measures/LoadFlexibility/resources/xml_helper.py             20     15    25%   6-10, 13-16, 19-25
measures/LoadFlexibility/tests/test_load_flexibility.py      31      4    87%   137-141
measures/LoadFlexibility/tests/test_setpoint.py             151     40    74%   103-114, 134-145, 164-175, 194-198
package_info.py                                              16     16     0%   1-22
---------------------------------------------------------------------------------------
TOTAL                                                       573    184    68%
Coverage HTML written to dir /Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage_html
Coverage XML written to file /Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage.xml
Coverage JSON written to file /Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage.json
Coverage LCOV written to file /Users/radhikar/Documents/largee/resstock/test_results/pytest/python_coverage.lcov

================================================================= 12 passed in 15.77s ==================================================================
┌────────────────────────────────────────────────────────────────────────────────┐
│                              Starting ruby tests                               │
└────────────────────────────────────────────────────────────────────────────────
jmarrec commented 1 month ago

Glad this is resolved, thanks for the quick feedback when I was asking for diagnostics :)