diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..d5c922c --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,50 @@ +name: Tests + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + test: + name: Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: + - "3.8" + - "3.9" + - "3.10" + - "3.11" + - "3.12" + - "3.13" + - "3.14" + + 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: Protobuf ${{ matrix.protobuf-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + protobuf-version: + - "6" + - "7" + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v6 + with: + python-version: "3.14" + - run: python -m pip install tox + - run: python -m tox -e py314-protobuf${{ matrix.protobuf-version }} diff --git a/setup.py b/setup.py index 464f168..85f562a 100644 --- a/setup.py +++ b/setup.py @@ -28,8 +28,8 @@ "cryptography>=43.0,<55; python_version>='3.14'", # 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'", @@ -60,4 +60,4 @@ 'install_requires': requires } -setup(name='webull-openapi-python-sdk', **setup_args) \ No newline at end of file +setup(name='webull-openapi-python-sdk', **setup_args) diff --git a/tests/compat/__init__.py b/tests/compat/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/compat/test_protobuf.py b/tests/compat/test_protobuf.py new file mode 100644 index 0000000..90d7504 --- /dev/null +++ b/tests/compat/test_protobuf.py @@ -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) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..85c9e81 --- /dev/null +++ b/tox.ini @@ -0,0 +1,19 @@ +[tox] +envlist = py{38,39,310,311,312,313,314}, py314-protobuf{6,7} +skip_missing_interpreters = true + +[testenv] +description = run the offline unit tests with {basepython} +commands = + python -m unittest discover -s tests/core/retry -v + python -m unittest discover -s tests/data/common -v + +[testenv:py314-protobuf{6,7}] +description = test generated messages with a pinned protobuf major +deps = + protobuf6: protobuf>=6,<7 + protobuf7: protobuf>=7,<8 +setenv = + protobuf6: EXPECTED_PROTOBUF_MAJOR=6 + protobuf7: EXPECTED_PROTOBUF_MAJOR=7 +commands = python -m unittest tests.compat.test_protobuf -v