From 53e378897d47d874ce89600a2d310fec97f953ea Mon Sep 17 00:00:00 2001 From: Katherine Fleming <2205659+kflemin@users.noreply.github.com> Date: Wed, 15 Apr 2026 15:34:15 -0600 Subject: [PATCH 1/6] nlr-cmei updates --- Dockerfile | 2 +- bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd | 2 +- bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.3.0.xsd | 2 +- .../Example \342\200\223 Valid Schema Invalid UseCase.xml" | 2 +- bsyncviewer/lib/validator/examples/schema2.2.0/L200_Audit.xml | 2 +- bsyncviewer/templates/base.html | 2 +- bsyncviewer/templates/base2.html | 2 +- bsyncviewer/templates/index.html | 2 +- bsyncviewer/tests/data/test_schema.xsd | 2 +- bsyncviewer/tests/data/test_valid_schema.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index f8a31001..f6b01894 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # VERSION 0.2 -# AUTHOR: Nicholas Long +# AUTHOR: Nicholas Long # DESCRIPTION: Dockerfile for running BuildingSync Website with Python 3.9+ # TO_BUILD_AND_RUN: docker-compose build && docker-compose up FROM alpine:3.18 diff --git a/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd b/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd index 36c6cd8d..fa36c638 100644 --- a/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd +++ b/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd @@ -1,5 +1,5 @@ - + BuildingSync Schema - Version 0.2 (May 22, 2016) diff --git a/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.3.0.xsd b/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.3.0.xsd index 14ad57c8..d84e8f4b 100644 --- a/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.3.0.xsd +++ b/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.3.0.xsd @@ -1,5 +1,5 @@ - + BuildingSync Schema - Version 0.3 (May 31, 2018) diff --git "a/bsyncviewer/lib/validator/examples/schema1.0.0/Example \342\200\223 Valid Schema Invalid UseCase.xml" "b/bsyncviewer/lib/validator/examples/schema1.0.0/Example \342\200\223 Valid Schema Invalid UseCase.xml" index 36cab897..d0344bbe 100644 --- "a/bsyncviewer/lib/validator/examples/schema1.0.0/Example \342\200\223 Valid Schema Invalid UseCase.xml" +++ "b/bsyncviewer/lib/validator/examples/schema1.0.0/Example \342\200\223 Valid Schema Invalid UseCase.xml" @@ -1,4 +1,4 @@ - + diff --git a/bsyncviewer/lib/validator/examples/schema2.2.0/L200_Audit.xml b/bsyncviewer/lib/validator/examples/schema2.2.0/L200_Audit.xml index 624b7564..f98370af 100644 --- a/bsyncviewer/lib/validator/examples/schema2.2.0/L200_Audit.xml +++ b/bsyncviewer/lib/validator/examples/schema2.2.0/L200_Audit.xml @@ -4,7 +4,7 @@ This file is intended to document all of the required elements and attributes for a Level 2 audit. --> - + diff --git a/bsyncviewer/templates/base.html b/bsyncviewer/templates/base.html index 943e4e41..1a3b6431 100644 --- a/bsyncviewer/templates/base.html +++ b/bsyncviewer/templates/base.html @@ -110,7 +110,7 @@

{% block title %}(no title){% endblock %}

diff --git a/bsyncviewer/templates/base2.html b/bsyncviewer/templates/base2.html index 3c1f1d6a..d356b8d5 100644 --- a/bsyncviewer/templates/base2.html +++ b/bsyncviewer/templates/base2.html @@ -132,7 +132,7 @@

{% block title %}(no title){% endblock title %}

BuildingSync® is a registered trademark of the Alliance for Energy Innovation, LLC.

-

The National Laboratory of the Rockies is a national laboratory of the U.S. Department of Energy, Office of Critical Minerals and Energy Innovation.

+

The National Laboratory of the Rockies is a national laboratory of the U.S. Department of Energy, Office of Critical Minerals and Energy Innovation.

+ BuildingSync Schema - Version 1.0 (January 31, 2019) diff --git a/bsyncviewer/tests/data/test_valid_schema.xml b/bsyncviewer/tests/data/test_valid_schema.xml index 3b4de653..06f0e95b 100644 --- a/bsyncviewer/tests/data/test_valid_schema.xml +++ b/bsyncviewer/tests/data/test_valid_schema.xml @@ -1,4 +1,4 @@ - + From 8e322a3668196e52d2fc96eeb8ff672f3ca250f5 Mon Sep 17 00:00:00 2001 From: Katherine Fleming <2205659+kflemin@users.noreply.github.com> Date: Wed, 15 Apr 2026 15:49:20 -0600 Subject: [PATCH 2/6] one more --- bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd b/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd index fa36c638..6f9d43fb 100644 --- a/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd +++ b/bsyncviewer/lib/buildingsync_schemas/BuildingSync_v0.2.0.xsd @@ -1,6 +1,6 @@ - + BuildingSync Schema - Version 0.2 (May 22, 2016) From 68e98198162fd5cbf54e031539d243806df725df Mon Sep 17 00:00:00 2001 From: Katherine Fleming <2205659+kflemin@users.noreply.github.com> Date: Wed, 15 Apr 2026 17:08:44 -0600 Subject: [PATCH 3/6] update tox? --- tox.ini | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 1a3ca538..ddfe8f62 100644 --- a/tox.ini +++ b/tox.ini @@ -13,10 +13,14 @@ envlist = passenv= DJANGO_LOG_LEVEL DJANGO_SETTINGS_MODULE +deps = + setuptools + -r{toxinidir}/requirements-test.txt commands = coverage run manage.py test -deps = -r{toxinidir}/requirements-test.txt [testenv:precommit] basepython = python +deps = + setuptools + -r{toxinidir}/requirements-test.txt commands = pre-commit run --all-files -deps = -r{toxinidir}/requirements-test.txt From a953404e8859086d5c375d1fcdf5ce42cda1d52e Mon Sep 17 00:00:00 2001 From: Katherine Fleming <2205659+kflemin@users.noreply.github.com> Date: Wed, 15 Apr 2026 17:14:34 -0600 Subject: [PATCH 4/6] tox fix --- .github/workflows/ci.yml | 2 +- tox.ini | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bac88019..576ee2fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: - name: Run tox env: DJANGO_SETTINGS_MODULE: bsyncviewer.settings.gh_actions - run: tox -e ${{ matrix.tox_env }} + run: tox -r -e ${{ matrix.tox_env }} - name: Coveralls if: ${{ success() && matrix.tox_env == 'python' && matrix.python-version == '3.9' }} env: diff --git a/tox.ini b/tox.ini index ddfe8f62..08b8ceea 100644 --- a/tox.ini +++ b/tox.ini @@ -16,6 +16,8 @@ passenv= deps = setuptools -r{toxinidir}/requirements-test.txt +commands_pre = + python -c "import setuptools, pkg_resources; print(setuptools.__version__)" commands = coverage run manage.py test [testenv:precommit] From 03d7c98c6f005d7cad51fc2e3cd9a651b9280c46 Mon Sep 17 00:00:00 2001 From: Katherine Fleming <2205659+kflemin@users.noreply.github.com> Date: Thu, 16 Apr 2026 09:02:36 -0600 Subject: [PATCH 5/6] update setup python ci --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 576ee2fa..819e05a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: run: | sudo apt-get update sudo apt-get install python3-enchant -y - pip install --upgrade pip - pip install tox coveralls + python -m pip install --upgrade pip setuptools wheel + python -m pip install --upgrade tox coveralls - name: Run tox env: DJANGO_SETTINGS_MODULE: bsyncviewer.settings.gh_actions From 00fc3d8285a4e1cb4e86c3dd61bf30c3cb70d682 Mon Sep 17 00:00:00 2001 From: Alex Swindler Date: Thu, 16 Apr 2026 15:05:22 -0600 Subject: [PATCH 6/6] Remove stopit to get rid of the pkg_resources import that is broken with the latest setuptools --- .github/workflows/ci.yml | 6 +-- bsyncviewer/lib/timeout.py | 72 +++++++++++++++++++++++++++ bsyncviewer/lib/validator/workflow.py | 6 +-- requirements.txt | 1 - tox.ini | 10 +--- 5 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 bsyncviewer/lib/timeout.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 819e05a7..bac88019 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,12 +42,12 @@ jobs: run: | sudo apt-get update sudo apt-get install python3-enchant -y - python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox coveralls + pip install --upgrade pip + pip install tox coveralls - name: Run tox env: DJANGO_SETTINGS_MODULE: bsyncviewer.settings.gh_actions - run: tox -r -e ${{ matrix.tox_env }} + run: tox -e ${{ matrix.tox_env }} - name: Coveralls if: ${{ success() && matrix.tox_env == 'python' && matrix.python-version == '3.9' }} env: diff --git a/bsyncviewer/lib/timeout.py b/bsyncviewer/lib/timeout.py new file mode 100644 index 00000000..9b7ae41a --- /dev/null +++ b/bsyncviewer/lib/timeout.py @@ -0,0 +1,72 @@ +""" +Minimal CPython threading timeout helper. + +This replaces the small subset of ``stopit`` used by the validator workflow. +``stopit`` imports ``pkg_resources`` at module import time, and that module was +removed from setuptools 82.0.0. +""" + +import ctypes +import threading + + +class TimeoutException(Exception): + """Raised when a code block exceeds the allowed timeout.""" + + +def _async_raise(thread_id, exception_type): + result = ctypes.pythonapi.PyThreadState_SetAsyncExc( + ctypes.c_long(thread_id), ctypes.py_object(exception_type) + ) + if result == 0: + raise ValueError(f"Invalid thread ID {thread_id}") + if result > 1: + ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + +class ThreadingTimeout: + EXECUTED, EXECUTING, TIMED_OUT, INTERRUPTED, CANCELED = range(5) + + def __init__(self, seconds, swallow_exc=True): + self.seconds = seconds + self.swallow_exc = swallow_exc + self.state = self.EXECUTED + self._target_tid = threading.current_thread().ident + self._timer = None + + def __bool__(self): + return self.state in (self.EXECUTED, self.EXECUTING, self.CANCELED) + + __nonzero__ = __bool__ + + def __enter__(self): + self.state = self.EXECUTING + self._timer = threading.Timer(self.seconds, self._trigger_timeout) + self._timer.start() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_type is TimeoutException: + if self.state != self.TIMED_OUT: + self.state = self.INTERRUPTED + self._cancel_timer() + return self.swallow_exc + + if exc_type is None: + self.state = self.EXECUTED + + self._cancel_timer() + return False + + def cancel(self): + self.state = self.CANCELED + self._cancel_timer() + + def _cancel_timer(self): + if self._timer is not None: + self._timer.cancel() + + def _trigger_timeout(self): + self.state = self.TIMED_OUT + _async_raise(self._target_tid, TimeoutException) diff --git a/bsyncviewer/lib/validator/workflow.py b/bsyncviewer/lib/validator/workflow.py index b2a17d99..1fcaae86 100644 --- a/bsyncviewer/lib/validator/workflow.py +++ b/bsyncviewer/lib/validator/workflow.py @@ -1,10 +1,10 @@ import copy from collections import OrderedDict -import stopit import xmlschema from testsuite.validate_sch import validate_schematron +from bsyncviewer.lib.timeout import ThreadingTimeout, TimeoutException from bsyncviewer.models.schema import Schema from bsyncviewer.models.use_case import UseCase @@ -49,7 +49,7 @@ def validate_schema(self): resp["schema_version"] = self.schema.version # timeout "to_dict()" after 5 mins and use the less good method of getting errors - with stopit.ThreadingTimeout(300): + with ThreadingTimeout(300): try: # this returns all errors self.xml_dict, errors = my_schema.to_dict( @@ -74,7 +74,7 @@ def validate_schema(self): } resp["errors"].append(tmp_err) - except stopit.utils.TimeoutException: + except TimeoutException: print( "TIMEOUT EXCEPTION OCCURRED, trying shorter validation method..." ) diff --git a/requirements.txt b/requirements.txt index 121dbc80..d7676766 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,6 @@ djangorestframework-xml==2.0.0 psycopg2-binary==2.9.7 semantic-version==2.10.0 -stopit==1.1.2 xmlschema==4.1.0 xmltodict==1.0.2 diff --git a/tox.ini b/tox.ini index 08b8ceea..1a3ca538 100644 --- a/tox.ini +++ b/tox.ini @@ -13,16 +13,10 @@ envlist = passenv= DJANGO_LOG_LEVEL DJANGO_SETTINGS_MODULE -deps = - setuptools - -r{toxinidir}/requirements-test.txt -commands_pre = - python -c "import setuptools, pkg_resources; print(setuptools.__version__)" commands = coverage run manage.py test +deps = -r{toxinidir}/requirements-test.txt [testenv:precommit] basepython = python -deps = - setuptools - -r{toxinidir}/requirements-test.txt commands = pre-commit run --all-files +deps = -r{toxinidir}/requirements-test.txt