ci: fix bSDD 429 rate limiting and restore ColumnPSetsOfSets.ifc schema

bsdd.py: the Client made every request with a bare requests.get, so a single
429 from the (unauthenticated, aggressively rate limited) bSDD API failed the
whole test. Route requests through a Session with a mounted urllib3 Retry
(5 attempts, backoff, honouring Retry-After) for 429/5xx, matching how a
resilient API client should behave, not just papering over the test.

ColumnPSetsOfSets.ifc: FILE_SCHEMA was accidentally changed from IFC4X3_ADD2
to IFC2X3 in a7738eeb64 (an unrelated logger refactor), a one line collateral
edit to this fixture. The file's DATA section still uses IFCPROPERTYSETDEFINITIONSET,
an IFC4+ only type. Parsing it against IFC2X3 threw "Entity ... not found in
schema", which silently fell back to interpreting the value as a raw nested
aggregate instead of the intended defined-type wrapper, producing the
double-nested tuple that broke test_stream, test_file and test_rocks in
test_streaming_rocksdb_and_simpletyperefs.py. Restoring the original schema
declared when the fixture was added (ff3fa48332) fixes all three.

Generated with the assistance of an AI coding tool.
This commit is contained in:
Petru Conduraru
2026-07-16 17:45:53 +03:00
committed by Dion Moult
parent 5c8eab981c
commit 6911418c67
+17 -2
View File
@@ -26,7 +26,9 @@ import webbrowser
from typing import TYPE_CHECKING, Any, Literal, Optional, TypedDict
import requests
from requests.adapters import HTTPAdapter
from typing_extensions import NotRequired
from urllib3.util import Retry
if TYPE_CHECKING:
import ifcopenshell
@@ -517,12 +519,25 @@ class Client:
self.auth_endpoint = "https://buildingsmartservices.b2clogin.com/tfp/buildingsmartservices.onmicrosoft.com/b2c_1_signupsignin/oauth2/v2.0/authorize"
self.token_endpoint = "https://buildingsmartservices.b2clogin.com/tfp/buildingsmartservices.onmicrosoft.com/b2c_1_signupsignin/oauth2/v2.0/token"
self.client_id = "4aba821f-d4ff-498b-a462-c2837dbbba70"
# The bSDD API is aggressively rate limited (HTTP 429). Retry transient
# failures with backoff instead of immediately raising, honouring the
# server's `Retry-After` header when present.
self.session = requests.Session()
retries = Retry(
total=5,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
respect_retry_after_header=True,
allowed_methods=["GET", "POST"],
)
self.session.mount("https://", HTTPAdapter(max_retries=retries))
self.session.mount("http://", HTTPAdapter(max_retries=retries))
def get(self, endpoint, params=None, is_auth_required=False):
headers = {"User-Agent": "IfcOpenShell.bSDD.py/0.8.0"}
if is_auth_required:
headers["Authorization"] = "Bearer " + self.get_access_token()
response = requests.get(f"{self.baseurl}{endpoint}", timeout=10, headers=headers, params=params or None)
response = self.session.get(f"{self.baseurl}{endpoint}", timeout=10, headers=headers, params=params or None)
try:
response.raise_for_status()
except requests.exceptions.HTTPError as e:
@@ -539,7 +554,7 @@ class Client:
old_baseurl = "https://bs-dd-api-prototype.azurewebsites.net/"
if is_auth_required:
headers["Authorization"] = "Bearer " + self.get_access_token()
return requests.get(f"{old_baseurl}{endpoint}", timeout=10, headers=headers, params=params or None).json()
return self.session.get(f"{old_baseurl}{endpoint}", timeout=10, headers=headers, params=params or None).json()
def post(self):
pass # TODO