From 2acaced035b49d008d59592dd86567e93a47e139 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Mon, 1 Jun 2026 11:55:32 -0500 Subject: [PATCH 1/2] Draft --- .../src/geos/xml_tools/attribute_coverage.py | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/geos-xml-tools/src/geos/xml_tools/attribute_coverage.py b/geos-xml-tools/src/geos/xml_tools/attribute_coverage.py index 5687db36..37e644b3 100644 --- a/geos-xml-tools/src/geos/xml_tools/attribute_coverage.py +++ b/geos-xml-tools/src/geos/xml_tools/attribute_coverage.py @@ -10,23 +10,30 @@ def parse_schema_element( root: ElementTree.Element, node: ElementTree.Element, xsd: str = '{http://www.w3.org/2001/XMLSchema}', - recursive_types: Iterable[ str ] = [ 'PeriodicEvent', 'SoloEvent', 'HaltEvent' ], - folders: Iterable[ str ] = [ 'src', 'examples' ] ) -> record_type: + folders: Iterable[ str ] = [ 'src', 'examples' ], + _seen: set | None = None ) -> record_type: """Parse the xml schema at the current level. Args: root (lxml.etree.Element): the root schema node node (lxml.etree.Element): current schema node xsd (str): the file namespace - recursive_types (list): node tags that allow recursive nesting folders (list): folders to sort xml attribute usage into + _seen (set): complexType names visited on the current recursion + path, used to break cycles. Managed by recursive calls. Returns: dict: Dictionary of attributes and children for the current node """ element_type = node.get( 'type' ) - element_name = node.get( 'name' ) + if _seen is None: + _seen = set() + if element_type in _seen: + return { 'attributes': {}, 'children': {} } + _seen = _seen | { element_type } element_def = root.find( "%scomplexType[@name='%s']" % ( xsd, element_type ) ) + if element_def is None: + return { 'attributes': {}, 'children': {} } local_types: record_type = { 'attributes': {}, 'children': {} } # Parse attributes @@ -41,8 +48,11 @@ def parse_schema_element( root: ElementTree.Element, if choice_node: for child in choice_node[ 0 ].findall( '%selement' % ( xsd ) ): child_name = child.get( 'name' ) - if not ( ( child_name in recursive_types ) and ( element_name in recursive_types ) ): - local_types[ 'children' ][ child_name ] = parse_schema_element( root, child ) + local_types[ 'children' ][ child_name ] = parse_schema_element( root, + child, + xsd=xsd, + folders=folders, + _seen=_seen ) return local_types @@ -71,10 +81,14 @@ def collect_xml_attributes_level( local_types: record_type, node: ElementTree.El folder (str): the source folder for the current file """ for ka in node.attrib: - local_types[ 'attributes' ][ ka ][ folder ].append( node.get( ka ) ) + # Skip attributes not present in the parsed schema (e.g. off-schema + # attributes in a deck, or truncated recursive complexTypes). + slot = local_types.get( 'attributes', {} ).get( ka ) + if slot is not None and folder in slot: + slot[ folder ].append( node.get( ka ) ) for child in node: - if child.tag in local_types[ 'children' ]: + if isinstance( child.tag, str ) and child.tag in local_types.get( 'children', {} ): collect_xml_attributes_level( local_types[ 'children' ][ child.tag ], child, folder ) From 6c598c9fa9a167ad30611828610bb2b0b54b9e71 Mon Sep 17 00:00:00 2001 From: Randolph Settgast Date: Fri, 5 Jun 2026 21:24:30 -0700 Subject: [PATCH 2/2] fix label checks to read current label status --- .github/workflows/python-package.yml | 42 ++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index f533a136..af2bda2c 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -140,40 +140,66 @@ jobs: check_integration_label: runs-on: ubuntu-latest needs: [build] + permissions: + pull-requests: read outputs: has_geos_integration_label: ${{ steps.set-label.outputs.has_label }} steps: - name: Check if PR has '${{ env.LABEL_TEST_GEOS_INTEGRATION }}' label id: set-label + # Fetch labels live from the GitHub REST API rather than reading + # github.event.pull_request.labels. The event payload is a snapshot + # frozen at the time the workflow was first triggered, so labels + # added after that first run are invisible to re-runs. + env: + GITHUB_TOKEN: ${{ github.token }} + REQUIRED_LABEL: ${{ env.LABEL_TEST_GEOS_INTEGRATION }} run: | echo "Checking for label..." LABEL_FOUND=false - LABELS='${{ toJson(github.event.pull_request.labels.*.name) }}' + PR_JSON=$(curl --fail --silent --show-error \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${GITHUB_TOKEN}" \ + "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}") + LABELS=$(echo "${PR_JSON}" | jq -crM '[.labels[].name]') echo "PR Labels: $LABELS" - if echo "$LABELS" | grep -q "${{ env.LABEL_TEST_GEOS_INTEGRATION }}"; then + if echo "$LABELS" | jq -e --arg label "${REQUIRED_LABEL}" 'index($label) != null' > /dev/null; then LABEL_FOUND=true - echo "Label '${{ env.LABEL_TEST_GEOS_INTEGRATION }}' found" + echo "Label '${REQUIRED_LABEL}' found" fi - echo "has_label=$LABEL_FOUND" >> $GITHUB_OUTPUT + echo "has_label=$LABEL_FOUND" >> "$GITHUB_OUTPUT" check_force_integration_label: runs-on: ubuntu-latest # needs: [build] + permissions: + pull-requests: read outputs: has_geos_integration_force_label: ${{ steps.set-label.outputs.has_label }} steps: - name: Check if PR has '${{ env.LABEL_FORCE_GEOS_INTEGRATION }}' label id: set-label + # Fetch labels live from the GitHub REST API rather than reading + # github.event.pull_request.labels. The event payload is a snapshot + # frozen at the time the workflow was first triggered, so labels + # added after that first run are invisible to re-runs. + env: + GITHUB_TOKEN: ${{ github.token }} + REQUIRED_LABEL: ${{ env.LABEL_FORCE_GEOS_INTEGRATION }} run: | echo "Checking for label..." LABEL_FOUND=false - LABELS='${{ toJson(github.event.pull_request.labels.*.name) }}' + PR_JSON=$(curl --fail --silent --show-error \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${GITHUB_TOKEN}" \ + "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}") + LABELS=$(echo "${PR_JSON}" | jq -crM '[.labels[].name]') echo "PR Labels: $LABELS" - if echo "$LABELS" | grep -q "${{ env.LABEL_FORCE_GEOS_INTEGRATION }}"; then + if echo "$LABELS" | jq -e --arg label "${REQUIRED_LABEL}" 'index($label) != null' > /dev/null; then LABEL_FOUND=true - echo "Label '${{ env.LABEL_FORCE_GEOS_INTEGRATION }}' found" + echo "Label '${REQUIRED_LABEL}' found" fi - echo "has_label=$LABEL_FOUND" >> $GITHUB_OUTPUT + echo "has_label=$LABEL_FOUND" >> "$GITHUB_OUTPUT" # Step 3: Check if GEOS integration is required based on changed files check_geos_integration_required: