Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
edb4467
add branch audit file
oberstet Nov 21, 2025
1e12db1
Add FlatBuffers test vector generator for WAMP SerDes tests
oberstet Nov 21, 2025
b79e2d7
Fix FlatBuffers EVENT/PUBLISH: retained property and memoryview seria…
oberstet Nov 21, 2025
8e9164d
Update FlatBuffers schemas and generated code for forward_for support
oberstet Nov 21, 2025
01a7230
Update .proto submodule to include FlatBuffers test vectors
oberstet Nov 21, 2025
34016f0
Add WAMP message class architecture documentation
oberstet Nov 22, 2025
bb20e5c
Implement mixin-based message class architecture
oberstet Nov 22, 2025
aa20d26
docs: enhance __slots__ and mixin pattern documentation
oberstet Nov 22, 2025
509f791
refactor: migrate Event and Call to use mixin classes
oberstet Nov 22, 2025
0270d6d
refactor: migrate Result, Invocation, Yield, Error to use mixin classes
oberstet Nov 22, 2025
e580dd1
refactor: migrate Category 3 messages to use MessageWithForwardFor mixin
oberstet Nov 22, 2025
c8a8ca6
autoformat via ruff
oberstet Nov 22, 2025
d3a4df5
build: regenerate FlatBuffers wrappers to match CI
oberstet Nov 22, 2025
cadfa7f
fix: make autoformat recipe respect pyproject.toml exclusions
oberstet Nov 22, 2025
1bacba9
fix: correct FlatBuffers generated file import paths
oberstet Nov 22, 2025
3304ce8
style: apply ruff formatting to ClientRoles.py
oberstet Nov 22, 2025
bac479f
fix: correct YAML syntax in wheels.yml cache key
oberstet Nov 22, 2025
b3706c8
fix: use multi-line YAML format for cache key
oberstet Nov 22, 2025
aa473b8
docs: add comprehensive WAMP enumeration audit report
oberstet Nov 23, 2025
c4c085f
chore: update wamp-ai submodule to latest
oberstet Nov 23, 2025
9b14e2d
add answers / design decisions wrt ENUMERATION_AUDIT.md
oberstet Nov 23, 2025
6e63a99
BREAKING: Refactor Payload Passthru Mode enumerations and fix CancelMode
oberstet Nov 23, 2025
9e6b3e1
Update FlatBuffers test vector generator for PPT enum refactoring
oberstet Nov 23, 2025
3d80604
Update wamp-proto submodule with regenerated FlatBuffers test vectors
oberstet Nov 23, 2025
51482fd
Update .proto submodule to fc64d78 with regenerated FlatBuffers test …
oberstet Nov 23, 2025
c9598c3
Phase 3: Add non-breaking enum additions to FlatBuffers schemas
oberstet Nov 23, 2025
4f42071
Refactor EVENT_RECEIVED to Category 3 and add message category docume…
oberstet Nov 23, 2025
8f54e64
Add FlatBuffers test coverage for Category 1 WAMP messages
oberstet Nov 23, 2025
c694c2f
Fix FlatBuffers Category 1 message serialization/deserialization
oberstet Nov 24, 2025
8010031
Add FlatBuffers support for Category 3 messages (Forwarding Only)
oberstet Nov 24, 2025
6b8dd1d
Add FlatBuffers support for Category 4 messages (Both Payload and For…
oberstet Nov 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ai
Submodule .ai updated 1 files
+12 −3 .githooks/commit-msg
8 changes: 8 additions & 0 deletions .audit/oberstet_fix_1771.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- [ ] I did **not** use any AI-assistance tools to help create this pull request.
- [x] I **did** use AI-assistance tools to *help* create this pull request.
- [x] I have read, understood and followed the projects' [AI Policy](https://github.com/crossbario/autobahn-python/blob/main/AI_POLICY.md) when creating code, documentation etc. for this pull request.

Submitted by: @oberstet
Date: 2025-11-21
Related issue(s): #1771
Branch: oberstet:fix_1771
47 changes: 25 additions & 22 deletions .github/workflows/generate_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,62 +15,65 @@
def generate_summary(json_file: Path, title: str) -> str:
"""
Generate a markdown summary table from an index.json file.

Args:
json_file: Path to the index.json file
title: Title for the summary section

Returns:
Markdown formatted summary table as a string
"""
if not json_file.exists():
return f"⚠️ {json_file} not found\n"

try:
with open(json_file, 'r') as f:
with open(json_file, "r") as f:
data = json.load(f)
except (json.JSONDecodeError, IOError) as e:
return f"❌ Error reading {json_file}: {e}\n"

# Build markdown table
lines = [
"",
f"## {title}",
"",
"| Testee | Cases OK / Total | Status |",
"|--------|------------------|---------|"
"|--------|------------------|---------|",
]

for testee, cases in data.items():
total_cases = len(cases)
ok_cases = 0

for case_id, case_data in cases.items():
behavior = case_data.get("behavior")
behavior_close = case_data.get("behaviorClose")

# Test passes if both behaviors are OK, or both are INFORMATIONAL
if (behavior == "OK" and behavior_close == "OK") or \
(behavior == "INFORMATIONAL" and behavior_close == "INFORMATIONAL"):
if (behavior == "OK" and behavior_close == "OK") or (
behavior == "INFORMATIONAL" and behavior_close == "INFORMATIONAL"
):
ok_cases += 1
status = '✅' if ok_cases == total_cases else '❌'
lines.append(f'| {testee} | {ok_cases} / {total_cases} | {status} |')
return '\n'.join(lines)

status = "✅" if ok_cases == total_cases else "❌"
lines.append(f"| {testee} | {ok_cases} / {total_cases} | {status} |")

return "\n".join(lines)


def main():
"""Main entry point."""
parser = argparse.ArgumentParser(description='Generate WebSocket conformance summary table')
parser.add_argument('json_file', type=Path, help='Path to the index.json file')
parser.add_argument('title', help='Title for the summary section')

parser = argparse.ArgumentParser(
description="Generate WebSocket conformance summary table"
)
parser.add_argument("json_file", type=Path, help="Path to the index.json file")
parser.add_argument("title", help="Title for the summary section")

args = parser.parse_args()

summary = generate_summary(args.json_file, args.title)
print(summary)


if __name__ == "__main__":
main()
main()
101 changes: 59 additions & 42 deletions .github/workflows/verify_conformance.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,103 +15,120 @@
def verify_conformance(json_file: Path, test_type: str) -> bool:
"""
Verify 100% conformance for a given index.json file.

Args:
json_file: Path to the index.json file
test_type: Type of test (e.g., "Client" or "Server")

Returns:
True if all tests passed, False otherwise
"""
if not json_file.exists():
print(f"❌ {json_file} not found")
return False

print(f"==> Checking {test_type} conformance...")

try:
with open(json_file, 'r') as f:
with open(json_file, "r") as f:
data = json.load(f)
except (json.JSONDecodeError, IOError) as e:
print(f"❌ Error reading {json_file}: {e}")
return False

all_passed = True
total_testees = len(data)
passed_testees = 0

for testee, cases in data.items():
total_cases = len(cases)
ok_cases = 0
failed_cases = []

for case_id, case_data in cases.items():
behavior = case_data.get("behavior")
behavior_close = case_data.get("behaviorClose")

# Test passes if both behaviors are OK, or both are INFORMATIONAL
if (behavior == "OK" and behavior_close == "OK") or \
(behavior == "INFORMATIONAL" and behavior_close == "INFORMATIONAL"):
if (behavior == "OK" and behavior_close == "OK") or (
behavior == "INFORMATIONAL" and behavior_close == "INFORMATIONAL"
):
ok_cases += 1
else:
failed_cases.append({
"case_id": case_id,
"behavior": behavior,
"behaviorClose": behavior_close
})

failed_cases.append(
{
"case_id": case_id,
"behavior": behavior,
"behaviorClose": behavior_close,
}
)

if ok_cases == total_cases:
print(f'✅ {testee}: {ok_cases}/{total_cases} tests passed')
print(f"✅ {testee}: {ok_cases}/{total_cases} tests passed")
passed_testees += 1
else:
print(f'❌ {testee}: {ok_cases}/{total_cases} tests passed')
print(f"❌ {testee}: {ok_cases}/{total_cases} tests passed")
# Show details of first few failed cases for debugging
for i, failed_case in enumerate(failed_cases[:3]):
print(f' Failed case {failed_case["case_id"]}: '
f'behavior={failed_case["behavior"]}, '
f'behaviorClose={failed_case["behaviorClose"]}')
print(
f" Failed case {failed_case['case_id']}: "
f"behavior={failed_case['behavior']}, "
f"behaviorClose={failed_case['behaviorClose']}"
)
if len(failed_cases) > 3:
print(f' ... and {len(failed_cases) - 3} more failed cases')
print(f" ... and {len(failed_cases) - 3} more failed cases")
all_passed = False

print('')
print(f'{test_type} Summary: {passed_testees}/{total_testees} testees passed all tests')


print("")
print(
f"{test_type} Summary: {passed_testees}/{total_testees} testees passed all tests"
)

if not all_passed:
print(f'❌ {test_type} conformance: FAILED - Not all tests passed')
print(f"❌ {test_type} conformance: FAILED - Not all tests passed")
return False
else:
print(f'✅ {test_type} conformance: PASSED - All tests passed')
print(f"✅ {test_type} conformance: PASSED - All tests passed")
return True


def main():
"""Main entry point."""
parser = argparse.ArgumentParser(description='Verify WebSocket conformance test results')
parser.add_argument('client_json', type=Path, help='Path to client index.json file')
parser.add_argument('server_json', type=Path, help='Path to server index.json file')

parser = argparse.ArgumentParser(
description="Verify WebSocket conformance test results"
)
parser.add_argument("client_json", type=Path, help="Path to client index.json file")
parser.add_argument("server_json", type=Path, help="Path to server index.json file")

args = parser.parse_args()

print("==> Verifying 100% WebSocket conformance...")

client_passed = verify_conformance(args.client_json, "Client")
print("")
server_passed = verify_conformance(args.server_json, "Server")

print("")
print("==> Overall WebSocket Conformance Verification:")

if client_passed and server_passed:
print("✅ PASSED - Both client and server conformance tests achieved 100% pass rate")
print(
"✅ PASSED - Both client and server conformance tests achieved 100% pass rate"
)
sys.exit(0)
else:
print("❌ FAILED - One or more conformance tests did not achieve 100% pass rate")
print(
"❌ FAILED - One or more conformance tests did not achieve 100% pass rate"
)
print("")
print("This means the WebSocket implementation has conformance issues that need to be addressed.")
print("Download the detailed reports from the workflow artifacts to investigate specific failures.")
print(
"This means the WebSocket implementation has conformance issues that need to be addressed."
)
print(
"Download the detailed reports from the workflow artifacts to investigate specific failures."
)
sys.exit(1)


if __name__ == "__main__":
main()
main()
3 changes: 1 addition & 2 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,7 @@ jobs:
with:
path: ${{ env.UV_CACHE_DIR }}
key:
uv-cache-${{ matrix.platform }}-${{ matrix.arch
}}-${{ hashFiles('pyproject.toml') }}
uv-cache-${{ matrix.platform }}-${{ matrix.arch }}-${{ hashFiles('pyproject.toml') }}
restore-keys: |
uv-cache-${{ matrix.platform }}-${{ matrix.arch }}-
uv-cache-${{ matrix.platform }}-
Expand Down
2 changes: 1 addition & 1 deletion .proto
Loading
Loading