Skip to content

CASSPYTHON-18: removed obsolete check for python version > 3.7+#1290

Open
bschoening wants to merge 3 commits intoapache:trunkfrom
bschoening:CASSPYTHON-18
Open

CASSPYTHON-18: removed obsolete check for python version > 3.7+#1290
bschoening wants to merge 3 commits intoapache:trunkfrom
bschoening:CASSPYTHON-18

Conversation

@bschoening
Copy link
Copy Markdown
Contributor

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes an obsolete Python version guard around the Eventlet + ThreadPoolExecutor workaround, simplifying executor selection now that the driver targets newer Python versions.

Changes:

  • Simplified _create_thread_pool_executor by removing the redundant sys.version_info check.
  • Always attempts to detect Eventlet usage and switches to futurist.GreenThreadPoolExecutor when needed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cassandra/cluster.py Outdated
Comment thread cassandra/cluster.py
@absurdfarce
Copy link
Copy Markdown
Contributor

There are a number of other spots where sys.version_info is consulted to make decisions about functionality. It's true that all the rest of them are in test code but it might be a good idea to fix all of them in one go anyway:

$ rg version_info
tests/unit/advanced/test_insights.py
66:        if sys.version_info > (3,):

tests/integration/advanced/graph/fluent/__init__.py
588:        if sys.version_info >= (3, 0):

tests/unit/test_policies.py
1297:        if sys.version_info >= (3, 11):

docs/api/cassandra.rst
6:.. data:: __version_info__

tests/unit/test_row_factories.py
31:NAMEDTUPLE_CREATION_BUG = sys.version_info >= (3,) and sys.version_info < (3, 7)

cassandra/cluster.py
1427:        if sys.version_info[0] >= 3 and sys.version_info[1] >= 7:

tests/integration/standard/test_metadata.py
1095:        if sys.version_info[0:2] != (2, 7):

tests/integration/cqlengine/columns/test_validation.py
615:        if sys.version_info < (3, 1):
739:        if sys.version_info < (3, 1):

tests/integration/cqlengine/base.py
51:    if sys.version_info > (3, 0):

I can make the changes and push a commit to this branch if that's useful.

Comment thread cassandra/cluster.py
"to hang indefinitely. If you want to use the Eventlet reactor, you "
"need to install the `futurist` package to allow the driver to use "
"the GreenThreadPoolExecutor. See https://github.com/eventlet/eventlet/issues/508 "
"for more details."))
Copy link
Copy Markdown
Contributor

@absurdfarce absurdfarce Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should perhaps change this usage to be more consistent with the current state of things on two fronts:

  1. Remove the conditionals on Python versions
  2. Recommend against eventlet anyways

Maybe something more like the following?

When using eventlet the concurrent.futures.ThreadPoolExecutor will hang indefinitely. If you want to use the eventlet reactor, you need to install the futurist package to allow the driver to use the GreenThreadPoolExecutor. See eventlet/eventlet#508 for more details.

Note that the eventlet reactor is deprecated and will be removed in 3.31.0. We strongly recommend using the asyncore or libev reactors for production code.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I'm not even 💯 sure we need this at all. It looks as if eventlet fixed this issue here and that this code was released in version 0.26.0. That version went out in July of 2020 so it's hard to imagine anyone getting an old enough version of eventlet for this to actually be a problem if they did a requirements install today.

@bschoening
Copy link
Copy Markdown
Contributor Author

@absurdfarce there are two left which I didn't fully understand, if you could update the PR with changes to those two, that would be terrific.

integration/standard/test_metadata.py:    if sys.version_info[0:2] != (2, 7):
unit/test_row_factories.p: NAMEDTUPLE_CREATION_BUG = sys.version_info >= (3,) and sys.version_info < (3, 7)

@bschoening
Copy link
Copy Markdown
Contributor Author

Gemini suggest the following:

@greaterthancass20
def test_export_keyspace_schema_udts(self):
"""
Test udt exports (Modernized for Python 3.10+)
"""
# We still need this: UDTs require Native Protocol v3+
if PROTOCOL_VERSION < 3:
raise unittest.SkipTest(
"Protocol 3.0+ is required for UDT change events, currently testing against %r"
% (PROTOCOL_VERSION,))

cluster = TestCluster()
session = cluster.connect()

# 1. Setup Schema
session.execute("""
    CREATE KEYSPACE export_udts
    WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}
    AND durable_writes = true;
""")
session.execute("CREATE TYPE export_udts.street (street_number int, street_name text)")
session.execute("CREATE TYPE export_udts.zip (zipcode int, zip_plus_4 int)")
session.execute("""
    CREATE TYPE export_udts.address (
        street_address frozen<street>,
        zip_code frozen<zip>)
""")
session.execute("""
    CREATE TABLE export_udts.users (
        user text PRIMARY KEY,
        addresses map<text, frozen<address>>)
""")

# 2. Re-trigger a metadata refresh to ensure the driver has captured the schema
cluster.metadata.refresh_keyspace_metadata('export_udts')
keyspace_meta = cluster.metadata.keyspaces['export_udts']
export_string = keyspace_meta.export_as_string()

# 3. Modern Assertions
# In 3.10+, dict order is stable. We check for core components.
expected_parts = [
    "CREATE KEYSPACE export_udts",
    "'class': 'SimpleStrategy'",
    "'replication_factor': '1'",
    "CREATE TYPE export_udts.street",
    "CREATE TYPE export_udts.zip",
    "CREATE TYPE export_udts.address",
    "CREATE TABLE export_udts.users"
]

for part in expected_parts:
    self.assertIn(part, export_string)

# 4. Verify UDT Nesting Order (Address must come after Street/Zip)
street_idx = export_string.find("CREATE TYPE export_udts.street")
zip_idx = export_string.find("CREATE TYPE export_udts.zip")
address_idx = export_string.find("CREATE TYPE export_udts.address")

self.assertTrue(street_idx < address_idx, "Street UDT must be defined before Address UDT")
self.assertTrue(zip_idx < address_idx, "Zip UDT must be defined before Address UDT")


@test_category row_factory
Test for a regression in PYTHON-893. Shouldn't be an issue with currently
supported versions since the underlying issue was fixed in Python 3.7
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underlying problem is fixed in Python 3.7 (see PYTHON-893 for more on that point) so we should no longer have any case in which NAMEDTUPLE_CREATION_BUG eval's to true.

with self.VerifiedFunction(self, **kwargs) as vf:
fn_meta = self.keyspace_function_meta[vf.signature]
self.assertRegex(fn_meta.as_cql_query(), "CREATE FUNCTION.*\) RETURNS NULL ON NULL INPUT RETURNS .*")
self.assertRegex(fn_meta.as_cql_query(), "CREATE FUNCTION.*) RETURNS NULL ON NULL INPUT RETURNS .*")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three changes above were minor fixes to address some deprecation warnings noted when running the test via Python 3.10:

tests/integration/standard/test_metadata.py:1591
  /home/mersault/work/git/python-driver/tests/integration/standard/test_metadata.py:1591: DeprecationWarning: invalid escape sequence '\('
	self.assertRegex(fn_meta.as_cql_query(), "CREATE FUNCTION.*%s\(\) .*" % kwargs['name'])

tests/integration/standard/test_metadata.py:1639
  /home/mersault/work/git/python-driver/tests/integration/standard/test_metadata.py:1639: DeprecationWarning: invalid escape sequence '\)'
	self.assertRegex(fn_meta.as_cql_query(), "CREATE FUNCTION.*\) CALLED ON NULL INPUT RETURNS .*")

tests/integration/standard/test_metadata.py:1644
  /home/mersault/work/git/python-driver/tests/integration/standard/test_metadata.py:1644: DeprecationWarning: invalid escape sequence '\)'
	self.assertRegex(fn_meta.as_cql_query(), "CREATE FUNCTION.*\) RETURNS NULL ON NULL INPUT RETURNS .*")

% (PROTOCOL_VERSION,))

if sys.version_info[0:2] != (2, 7):
raise unittest.SkipTest('This test compares static strings generated from dict items, which may change orders. Test with 2.7.')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is certainly possible, but if we find ourselves in a situation where our output changes because a particular version is handling dictionary keys differently I would much rather know that (by way of a failing test) than silently skipping the test in question.

@absurdfarce
Copy link
Copy Markdown
Contributor

@bschoening Fixes should now be in place for test_row_factories.py and test_metadata.py. I'm going to run Jenkins against the current state of this build to confirm there aren't any unexpected regressions but I think we're getting pretty close.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants