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.

(cherry picked from commit 6911418c67)
This commit is contained in:
Petru Conduraru
2026-07-16 17:45:53 +03:00
committed by Dion Moult
parent 19c048fca3
commit 38a005ccf5
+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