-
Notifications
You must be signed in to change notification settings - Fork 573
Add support for python3.14 #1281
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,7 @@ Apache Cassandra Python Driver | |
| A modern, `feature-rich <https://github.com/datastax/python-driver#features>`_ and highly-tunable Python client library for Apache Cassandra (2.1+) and | ||
| DataStax Enterprise (4.7+) using exclusively Cassandra's binary protocol and Cassandra Query Language v3. | ||
|
|
||
| The driver supports Python 3.9 through 3.13. | ||
| The driver supports Python 3.9 through 3.14. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is being addressed in the 3.30.0 changelog and documentation PR |
||
|
|
||
| **Note:** DataStax products do not support big-endian systems. | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -149,6 +149,13 @@ def _try_libev_import(): | |
| except DependencyException as e: | ||
| return (None, e) | ||
|
|
||
| def _try_asyncio_import(): | ||
| try: | ||
| from cassandra.io.asyncioreactor import AsyncioConnection | ||
| return (AsyncioConnection, None) | ||
| except ImportError as e: | ||
| return (None, e) | ||
|
|
||
| def _try_asyncore_import(): | ||
| try: | ||
| from cassandra.io.asyncorereactor import AsyncoreConnection | ||
|
|
@@ -168,7 +175,7 @@ def _connection_reduce_fn(val,import_fn): | |
|
|
||
| log = logging.getLogger(__name__) | ||
|
|
||
| conn_fns = (_try_gevent_import, _try_eventlet_import, _try_libev_import, _try_asyncore_import) | ||
| conn_fns = (_try_gevent_import, _try_eventlet_import, _try_libev_import, _try_asyncio_import, _try_asyncore_import) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We definitely don't want to do this until the asyncio event loop is stable. We describe the asyncio reactor as "experimental" with good reason so I don't want to include this reactor in the default sequence until we're able to get it stabilized. The current plan is to work on that for the next release (3.31.0). I'd be okay with adding it to the default reactors at that point but we need to get there first. |
||
| (conn_class, excs) = reduce(_connection_reduce_fn, conn_fns, (None,[])) | ||
| if not conn_class: | ||
| raise DependencyException("Unable to load a default connection class", excs) | ||
|
|
@@ -883,18 +890,20 @@ def default_retry_policy(self, policy): | |
| * :class:`cassandra.io.twistedreactor.TwistedConnection` | ||
| * EXPERIMENTAL: :class:`cassandra.io.asyncioreactor.AsyncioConnection` | ||
|
|
||
| By default, ``AsyncoreConnection`` will be used, which uses | ||
| the ``asyncore`` module in the Python standard library. | ||
| By default, ``LibevConnection`` will be used when available. | ||
|
|
||
| If ``libev`` is installed, ``LibevConnection`` will be used instead. | ||
|
|
||
| If ``libev`` is not available, ``AsyncioConnection`` will be used when available. | ||
|
|
||
| If ``gevent`` or ``eventlet`` monkey-patching is detected, the corresponding | ||
| connection class will be used automatically. | ||
|
|
||
| ``AsyncoreConnection`` is still available on Python versions where the | ||
| ``asyncore`` module exists. | ||
|
|
||
| ``AsyncioConnection``, which uses the ``asyncio`` module in the Python | ||
| standard library, is also available, but currently experimental. Note that | ||
| it requires ``asyncio`` features that were only introduced in the 3.4 line | ||
| in 3.4.6, and in the 3.5 line in 3.5.1. | ||
| standard library, is also available, but currently experimental. | ||
| """ | ||
|
|
||
| control_connection_timeout = 2.0 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,11 +20,12 @@ | |
| import sys | ||
| import tempfile | ||
| import shutil | ||
| import ssl | ||
| from urllib.request import urlopen | ||
|
|
||
| _HAS_SSL = True | ||
| try: | ||
| from ssl import SSLContext, PROTOCOL_TLS, CERT_REQUIRED | ||
| from ssl import SSLContext, CERT_REQUIRED | ||
| except: | ||
| _HAS_SSL = False | ||
|
|
||
|
|
@@ -171,9 +172,12 @@ def parse_metadata_info(config, http_data): | |
|
|
||
|
|
||
| def _ssl_context_from_cert(ca_cert_location, cert_location, key_location): | ||
| ssl_context = SSLContext(PROTOCOL_TLS) | ||
| protocol = getattr(ssl, "PROTOCOL_TLS_CLIENT", ssl.PROTOCOL_TLS) | ||
| ssl_context = SSLContext(protocol) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you speak more about what this was intended to do @Ya-Sabyr? PROTOCOL_TLS_CLIENT has been included in the ssl module since 3.6 so this will always succeed, at least for versions of Python we explicitly support. This means that by default we will always use PROTOCOL_TLS_CLIENT for SSL ops against Astra which may offer some benefit (although that isn't clear to me). We could talk about that but I'm not sure why we wouldn't just use this instead: |
||
| ssl_context.load_verify_locations(ca_cert_location) | ||
| ssl_context.verify_mode = CERT_REQUIRED | ||
| if hasattr(ssl_context, "check_hostname"): | ||
| ssl_context.check_hostname = True | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A similar question here. check_hostname has been on SSLContext since Python 3.4 so the hasattr() check here will always return true (at least for modern Pythons). Implication there is that we'll always set check_hostname to True, which (a) may be a good idea anyway but (b) is definitely a change that should be considered by itself. Perhaps more directly relevant: PROTOCOL_TLS_CLIENT enables this by default so this is actually redundant given the change above. |
||
| ssl_context.load_cert_chain(certfile=cert_location, keyfile=key_location) | ||
|
|
||
| return ssl_context | ||
|
|
@@ -186,10 +190,11 @@ def _pyopenssl_context_from_cert(ca_cert_location, cert_location, key_location): | |
| raise ImportError( | ||
| "PyOpenSSL must be installed to connect to Astra with the Eventlet or Twisted event loops")\ | ||
| .with_traceback(e.__traceback__) | ||
| ssl_context = SSL.Context(SSL.TLSv1_METHOD) | ||
| ssl_method = getattr(SSL, "TLS_METHOD", SSL.TLSv1_METHOD) | ||
| ssl_context = SSL.Context(ssl_method) | ||
| ssl_context.set_verify(SSL.VERIFY_PEER, callback=lambda _1, _2, _3, _4, ok: ok) | ||
| ssl_context.use_certificate_file(cert_location) | ||
| ssl_context.use_privatekey_file(key_location) | ||
| ssl_context.load_verify_locations(ca_cert_location) | ||
|
|
||
| return ssl_context | ||
| return ssl_context | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ classifiers = [ | |
| "Programming Language :: Python :: 3.11", | ||
| "Programming Language :: Python :: 3.12", | ||
| "Programming Language :: Python :: 3.13", | ||
| "Programming Language :: Python :: 3.14", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We missed this in the original work on CASSPYTHON-3. This was subsequently addressed in the PR for CASSPYTHON-12. Note that since only Python 3.10 through 3.14 will be non-EOL at time of release you also need to remove Python 3.9 from the list of classifiers here. |
||
| "Programming Language :: Python :: Implementation :: CPython", | ||
| "Programming Language :: Python :: Implementation :: PyPy", | ||
| "Topic :: Software Development :: Libraries :: Python Modules" | ||
|
|
@@ -53,4 +54,4 @@ build-libev-extension = true | |
| build-cython-extensions = true | ||
| libev-includes = ["/usr/include/libev", "/usr/local/include", "/opt/local/include", "/usr/include"] | ||
| libev-libs = ["/usr/local/lib", "/opt/local/lib", "/usr/lib64"] | ||
| build-concurrency = 0 | ||
| build-concurrency = 0 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -996,7 +996,8 @@ def test_clone_shared_lbp(self): | |
| exec_profiles = {'rr1': rr1} | ||
| with TestCluster(execution_profiles=exec_profiles) as cluster: | ||
| session = cluster.connect(wait_for_all_pools=True) | ||
| self.assertGreater(len(cluster.metadata.all_hosts()), 1, "We only have one host connected at this point") | ||
| if len(cluster.metadata.all_hosts()) <= 1: | ||
| raise unittest.SkipTest("This test requires multiple connected hosts") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we want to silently skip tests here if we're not able to connect to the nodes. These tests are all configured to use a three-node ccm cluster and since we also wait on all connection pools to complete before returning (note the "wait_for_all_pools" arg to the connect() call) we should always have at least three connections here. If we don't something's gone quite wrong (or our test setup is bogus) so we should provide some feedback to the test runner to indicate that fact rather than silently skipping this test. As an example: I ran this test locally and saw it pass right away. It's also been passing in all our Jenkins runs. If you're seeing local failures @Ya-Sabyr it's probably something that should be investigated more completely rather than skipped. |
||
|
|
||
| rr1_clone = session.execution_profile_clone_update('rr1', row_factory=tuple_factory) | ||
| cluster.add_execution_profile("rr1_clone", rr1_clone) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| [tox] | ||
| envlist = py{39,310,311,312,313},pypy | ||
| envlist = py{39,310,311,312,313,314},pypy | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is being addressed in the 3.30.0 changelog and documentation PR |
||
|
|
||
| [base] | ||
| deps = pytest | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is being addressed in the 3.30.0 changelog and documentation PR