Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
62 changes: 62 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Tests

on:
push:
pull_request:

permissions:
contents: read

jobs:
test:
name: Python ${{ matrix.python-version }} (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
- "3.15"
include:
- os: macos-latest
python-version: "3.15"
- os: windows-latest
python-version: "3.15"

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- run: python -m pip install tox
- run: python -m tox -e py

protobuf:
name: Python ${{ matrix.python.version }} / Protobuf ${{ matrix.protobuf-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python:
- version: "3.14"
tox: py314
- version: "3.15"
tox: py315
protobuf-version:
- "6"
- "7"

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python.version }}
- run: python -m pip install tox
- run: python -m tox -e ${{ matrix.python.tox }}-protobuf${{ matrix.protobuf-version }}
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# macOS Finder metadata
.DS_Store

# Python bytecode and packaging outputs
__pycache__/
*.py[cod]
*.egg-info/
build/
dist/

# Local development environments
.venv/
.tox/
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Subscription to real-time information: Subscribe to order status changes, market
| Webull MX | https://www.webull.com.mx/open-api-management |
| Webull ZA | https://www.webull.co.za/open-api-management |
| Webull EU | https://www.webull.eu/open-api-management |
- Requires Python 3.8 through 3.14.
- Requires Python 3.8 through 3.15.

## Interface Protocol

Expand All @@ -59,4 +59,23 @@ The bottom layer of Webull OpenAPI provides three protocols, HTTP / GRPC / MQTT,
| Webull BR | https://developer.webull.com.br/apis/docs |
| Webull MX | https://developer.webull.com.mx/apis/docs |
| Webull ZA | https://developer.webull.co.za/apis/docs |
| Webull EU | https://developer.webull.eu/apis/docs |
| Webull EU | https://developer.webull.eu/apis/docs |

## Compatibility tests

The tox suite runs offline retry, quote-category, HTTP-client construction,
signing, MQTT/TLS, Protobuf decoding, and local gRPC streaming checks. Python
3.15 CI covers Linux, macOS, and Windows. Protobuf 6 and 7 are also tested on
Python 3.14 and 3.15.

```bash
python -m pip install tox
python -m tox -e py315,py315-protobuf6,py315-protobuf7
```

Python 3.15 selects [gRPC 1.84 or newer](https://github.com/grpc/grpc/releases/tag/v1.84.0)
for published interpreter-specific wheels and [CFFI 2.1.1 or newer](https://cryptography.io/en/latest/changelog/)
to avoid an earlier ABI issue. The test suite uses local
sockets and requires no Webull credentials. Other examples under `tests/data`
and `tests/trade` include remote calls with placeholder credentials and are
manual integration examples.
14 changes: 9 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,19 @@
"cryptography>=3.4,<42; python_version<'3.12'",
"cryptography>=41.0,<43; python_version>='3.12' and python_version<'3.14'",
"cryptography>=43.0,<55; python_version>='3.14'",
# Earlier CFFI releases have a Python 3.15 ABI issue (see cryptography's 51.0.0 changelog).
"cffi>=2.1.1; python_version>='3.15'",

# protobuf
"protobuf>=4.21.12,<5; python_version<'3.12'",
"protobuf>=4.25.0,<6; python_version>='3.12'",
"protobuf>=4.21.12,<8; python_version<'3.12'",
"protobuf>=4.25.0,<8; python_version>='3.12'",

# grpc
"grpcio>=1.51.1,<1.60; python_version<'3.12'",
"grpcio>=1.60.0,<1.70; python_version>='3.12' and python_version<'3.14'",
"grpcio>=1.75.1,<2; python_version>='3.14'"
"grpcio>=1.75.1,<2; python_version>='3.14' and python_version<'3.15'",
# gRPC 1.84 is the first release with public CPython 3.15 wheels.
"grpcio>=1.84.0,<2; python_version>='3.15'"
]

extras_require = {
Expand All @@ -45,7 +49,7 @@
}

setup_args = {
'python_requires':'>=3.8,<3.15',
'python_requires':'>=3.8,<3.16',
'version': VERSION,
'author': AUTHOR,
'author_email': AUTHOR_EMAIL,
Expand All @@ -60,4 +64,4 @@
'install_requires': requires
}

setup(name='webull-openapi-python-sdk', **setup_args)
setup(name='webull-openapi-python-sdk', **setup_args)
Empty file added tests/compat/__init__.py
Empty file.
27 changes: 27 additions & 0 deletions tests/compat/test_protobuf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
import unittest

import google.protobuf

from webull.data.quotes.subscribe.message_pb2 import Snapshot
from webull.trade.events.events_pb2 import SubscribeRequest


class TestProtobufCompatibility(unittest.TestCase):

def test_expected_protobuf_major_is_installed(self):
expected_major = os.environ["EXPECTED_PROTOBUF_MAJOR"]

self.assertEqual(google.protobuf.__version__.split(".", 1)[0], expected_major)

def test_generated_messages_round_trip(self):
messages = (
Snapshot(price="123.45", volume="10"),
SubscribeRequest(subscribeType=1, accounts=["account-id"]),
)

for message in messages:
with self.subTest(message=message.DESCRIPTOR.full_name):
restored = type(message)()
restored.ParseFromString(message.SerializeToString())
self.assertEqual(restored, message)
Loading