Skip to content

PYTHON-5757 Deprecate Python 2 methods in SON#2732

Merged
aclark4life merged 2 commits intomongodb:masterfrom
aclark4life:PYTHON-5757
Mar 18, 2026
Merged

PYTHON-5757 Deprecate Python 2 methods in SON#2732
aclark4life merged 2 commits intomongodb:masterfrom
aclark4life:PYTHON-5757

Conversation

@aclark4life
Copy link
Contributor

@aclark4life aclark4life commented Mar 17, 2026

bson/son.py contains three methods that were added for Python 2 compatibility but are no longer needed

INTPYTHON-5757

Changes in this PR

bson/son.py contains three methods that were added for Python 2 compatibility but are no longer needed

Test Plan

Updated tests to use new syntax.

Checklist

Checklist for Author

  • Did you update the changelog (if necessary)?
  • Is there test coverage?
  • Is any followup work tracked in a JIRA ticket? If so, add link(s).

Checklist for Reviewer

  • Does the title of the PR reference a JIRA Ticket?
  • Do you fully understand the implementation? (Would you be comfortable explaining how this code works to someone else?)
  • Is all relevant documentation (README or docstring) updated?

Copy link

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

This PR deprecates legacy Python 2 compatibility methods on bson.son.SON by emitting DeprecationWarnings and updates documentation/tests to steer users toward idiomatic Python 3 usage.

Changes:

  • Added DeprecationWarning emissions for SON.has_key, SON.iterkeys, and SON.itervalues.
  • Updated SON tests to stop using has_key and use the in operator instead.
  • Documented the deprecations and planned removal (PyMongo 5.0) in the changelog.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
bson/son.py Adds deprecation warnings to Python 2-era SON methods.
test/test_son.py Updates tests to use Python 3 membership syntax rather than has_key.
doc/changelog.rst Notes the SON method deprecations and planned removal timeline.

test/test_son.py Outdated
Comment on lines +147 to +148
def test_contains_has(self):
"""has_key and __contains__"""
"""key in SON and __contains__"""
Comment on lines +11 to +12
deprecated in favor of the standard dictionary methods ``in``, ``keys``, and
``values`` respectively.
@aclark4life aclark4life marked this pull request as draft March 17, 2026 18:54
@aclark4life aclark4life marked this pull request as ready for review March 17, 2026 19:17
@codecov-commenter
Copy link

codecov-commenter commented Mar 17, 2026

Codecov Report

❌ Patch coverage is 25.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.62%. Comparing base (13085ff) to head (554904d).

Files with missing lines Patch % Lines
bson/son.py 25.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2732      +/-   ##
==========================================
- Coverage   87.63%   87.62%   -0.02%     
==========================================
  Files         141      141              
  Lines       24133    24137       +4     
  Branches     4122     4122              
==========================================
+ Hits        21150    21151       +1     
- Misses       2093     2096       +3     
  Partials      890      890              
Flag Coverage Δ
auth-aws-rhel8-test-auth-aws-rapid-web-identity-python3.14-cov 35.09% <25.00%> (-0.01%) ⬇️
auth-aws-win64-test-auth-aws-rapid-web-identity-python3.14-cov 35.09% <25.00%> (-0.01%) ⬇️
auth-enterprise-macos-test-standard-auth-latest-python3.11-auth-ssl-sharded-cluster-cov 43.75% <25.00%> (?)
auth-enterprise-rhel8-test-standard-auth-latest-python3.11-auth-ssl-sharded-cluster-cov 43.74% <25.00%> (-0.01%) ⬇️
auth-enterprise-win64-test-standard-auth-latest-python3.11-auth-ssl-sharded-cluster-cov 43.78% <25.00%> (+0.02%) ⬆️
auth-oidc-local-ubuntu-22-test-auth-oidc-default 48.72% <25.00%> (+0.05%) ⬆️
compression-snappy-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.22% <25.00%> (-0.01%) ⬇️
compression-snappy-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.14% <25.00%> (-0.01%) ⬇️
compression-snappy-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 56.56% <25.00%> (-0.01%) ⬇️
compression-snappy-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.87% <25.00%> (-0.01%) ⬇️
compression-zlib-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.23% <25.00%> (+<0.01%) ⬆️
compression-zlib-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.14% <25.00%> (-0.01%) ⬇️
compression-zlib-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 56.56% <25.00%> (-0.01%) ⬇️
compression-zlib-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.89% <25.00%> (+0.01%) ⬆️
compression-zstd-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.23% <25.00%> (+<0.01%) ⬆️
compression-zstd-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.14% <25.00%> (-0.01%) ⬇️
compression-zstd-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 56.56% <25.00%> (-0.01%) ⬇️
compression-zstd-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.87% <25.00%> (-0.01%) ⬇️
compression-zstd-ubuntu-22-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.85% <25.00%> (-0.01%) ⬇️
coverage-report-coverage-report 87.59% <25.00%> (+0.06%) ⬆️
disable-test-commands-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.22% <25.00%> (-0.01%) ⬇️
disable-test-commands-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.14% <25.00%> (-0.01%) ⬇️
disable-test-commands-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 56.56% <25.00%> (-0.01%) ⬇️
disable-test-commands-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.86% <25.00%> (-0.01%) ⬇️
encryption-crypt_shared-macos-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.84% <25.00%> (?)
encryption-crypt_shared-macos-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.75% <25.00%> (?)
encryption-crypt_shared-macos-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.55% <25.00%> (?)
encryption-crypt_shared-rhel8-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.84% <25.00%> (-0.01%) ⬇️
encryption-crypt_shared-rhel8-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.62% <25.00%> (-0.01%) ⬇️
encryption-crypt_shared-rhel8-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.54% <25.00%> (+0.01%) ⬆️
encryption-crypt_shared-win64-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.71% <25.00%> (-0.01%) ⬇️
encryption-crypt_shared-win64-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.79% <25.00%> (+0.03%) ⬆️
encryption-crypt_shared-win64-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.63% <25.00%> (+0.02%) ⬆️
encryption-macos-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.83% <25.00%> (?)
encryption-macos-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.74% <25.00%> (?)
encryption-macos-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.55% <25.00%> (?)
encryption-pyopenssl-rhel8-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 53.51% <25.00%> (-0.01%) ⬇️
encryption-pyopenssl-rhel8-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 55.30% <25.00%> (-0.02%) ⬇️
encryption-pyopenssl-rhel8-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 55.24% <25.00%> (-0.01%) ⬇️
encryption-rhel8-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.82% <25.00%> (-0.01%) ⬇️
encryption-rhel8-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.62% <25.00%> (-0.02%) ⬇️
encryption-rhel8-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.54% <25.00%> (-0.02%) ⬇️
encryption-win64-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.72% <25.00%> (-0.06%) ⬇️
encryption-win64-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.80% <25.00%> (+0.12%) ⬆️
encryption-win64-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.60% <25.00%> (-0.02%) ⬇️
load-balancer-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 48.33% <25.00%> (-0.01%) ⬇️
mongodb-latest-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 56.96% <25.00%> (-0.01%) ⬇️
mongodb-latest-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 55.25% <25.00%> (-0.02%) ⬇️
mongodb-latest-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 59.13% <25.00%> (-0.01%) ⬇️
mongodb-latest-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 59.28% <25.00%> (-0.01%) ⬇️
mongodb-latest-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 57.08% <25.00%> (+<0.01%) ⬆️
mongodb-rapid-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 56.96% <25.00%> (-0.01%) ⬇️
mongodb-rapid-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 55.25% <25.00%> (-0.02%) ⬇️
mongodb-rapid-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 59.13% <25.00%> (-0.01%) ⬇️
mongodb-rapid-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 59.28% <25.00%> (-0.01%) ⬇️
mongodb-rapid-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 57.07% <25.00%> (-0.02%) ⬇️
mongodb-v4.2-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 54.64% <25.00%> (-0.03%) ⬇️
mongodb-v4.2-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 53.23% <25.00%> (+<0.01%) ⬆️
mongodb-v4.2-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 56.83% <25.00%> (-0.01%) ⬇️
mongodb-v4.2-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 56.95% <25.00%> (-0.01%) ⬇️
mongodb-v4.2-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 54.81% <25.00%> (-0.01%) ⬇️
mongodb-v4.4-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 55.06% <25.00%> (-0.02%) ⬇️
mongodb-v4.4-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 53.49% <25.00%> (+<0.01%) ⬆️
mongodb-v4.4-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 57.24% <25.00%> (-0.01%) ⬇️
mongodb-v4.4-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 57.32% <25.00%> (-0.01%) ⬇️
mongodb-v4.4-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 55.11% <25.00%> (-0.01%) ⬇️
mongodb-v5.0-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 55.26% <25.00%> (+<0.01%) ⬆️
mongodb-v5.0-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 53.66% <25.00%> (+<0.01%) ⬆️
mongodb-v5.0-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 57.43% <25.00%> (-0.01%) ⬇️
mongodb-v5.0-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 57.56% <25.00%> (-0.01%) ⬇️
mongodb-v5.0-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 55.35% <25.00%> (-0.01%) ⬇️
mongodb-v6.0-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 55.28% <25.00%> (+<0.01%) ⬆️
mongodb-v6.0-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 53.65% <25.00%> (-0.01%) ⬇️
mongodb-v6.0-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 57.45% <25.00%> (-0.01%) ⬇️
mongodb-v6.0-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 57.60% <25.00%> (-0.01%) ⬇️
mongodb-v6.0-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 55.40% <25.00%> (+0.01%) ⬆️
mongodb-v7.0-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 55.27% <25.00%> (-0.01%) ⬇️
mongodb-v7.0-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 53.64% <25.00%> (-0.01%) ⬇️
mongodb-v7.0-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 57.45% <25.00%> (-0.01%) ⬇️
mongodb-v7.0-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 57.59% <25.00%> (-0.01%) ⬇️
mongodb-v7.0-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 55.39% <25.00%> (-0.01%) ⬇️
mongodb-v8.0-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 56.95% <25.00%> (-0.02%) ⬇️
mongodb-v8.0-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 55.25% <25.00%> (-0.02%) ⬇️
mongodb-v8.0-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 59.13% <25.00%> (-0.01%) ⬇️
mongodb-v8.0-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 59.28% <25.00%> (-0.01%) ⬇️
mongodb-v8.0-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 57.08% <25.00%> (-0.01%) ⬇️
no-c-ext-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 56.44% <25.00%> (-0.01%) ⬇️
no-c-ext-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 58.36% <25.00%> (-0.01%) ⬇️
no-c-ext-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 57.78% <25.00%> (-0.01%) ⬇️
no-c-ext-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 56.08% <25.00%> (-0.01%) ⬇️
ocsp-rhel8-test-ocsp-ecdsa-valid-cert-server-staples-latest-python3.14-cov 34.06% <25.00%> (-0.01%) ⬇️
ocsp-rhel8-test-ocsp-rsa-valid-cert-server-staples-latest-python3.14-cov 34.06% <25.00%> (-0.02%) ⬇️
pyopenssl-macos-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.05% <25.00%> (-0.01%) ⬇️
pyopenssl-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.05% <25.00%> (-0.01%) ⬇️
pyopenssl-win64-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.00% <25.00%> (-0.01%) ⬇️
stable-api-accept-v2-rhel8-auth-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.22% <25.00%> (-0.01%) ⬇️
stable-api-accept-v2-rhel8-auth-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.87% <25.00%> (-0.01%) ⬇️
stable-api-require-v1-rhel8-auth-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.20% <25.00%> (-0.02%) ⬇️
stable-api-require-v1-rhel8-auth-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 56.43% <25.00%> (-0.01%) ⬇️
stable-api-require-v1-rhel8-auth-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.85% <25.00%> (-0.01%) ⬇️
storage-inmemory-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.24% <25.00%> (+<0.01%) ⬆️
storage-inmemory-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.87% <25.00%> (-0.01%) ⬇️
test-macos-arm64-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.20% <25.00%> (-0.01%) ⬇️
test-macos-arm64-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.14% <25.00%> (-0.01%) ⬇️
test-macos-arm64-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 56.56% <25.00%> (-0.02%) ⬇️
test-macos-arm64-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.83% <25.00%> (-0.01%) ⬇️
test-macos-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.21% <25.00%> (?)
test-macos-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.14% <25.00%> (?)
test-macos-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 56.56% <25.00%> (?)
test-macos-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.84% <25.00%> (?)
test-numpy-macos-arm64-test-numpy-python3.14-python3.14-cov 32.27% <25.00%> (-0.02%) ⬇️
test-numpy-macos-test-numpy-python3.14-python3.14-cov 32.27% <25.00%> (?)
test-numpy-rhel8-test-numpy-python3.14-python3.14-cov 32.27% <25.00%> (-0.01%) ⬇️
test-numpy-win32-test-numpy-python3.14-python3.14-cov 32.25% <25.00%> (+0.01%) ⬆️
test-numpy-win64-test-numpy-python3.14-python3.14-cov 32.25% <25.00%> (+0.01%) ⬆️
test-win32-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.06% <25.00%> (-0.01%) ⬇️
test-win32-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.09% <25.00%> (-0.01%) ⬇️
test-win32-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 56.49% <25.00%> (-0.01%) ⬇️
test-win32-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.70% <25.00%> (-0.01%) ⬇️
test-win64-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 55.07% <25.00%> (-0.01%) ⬇️
test-win64-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 57.09% <25.00%> (-0.01%) ⬇️
test-win64-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 56.49% <25.00%> (-0.01%) ⬇️
test-win64-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 54.71% <25.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@Jibola Jibola left a comment

Choose a reason for hiding this comment

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

LGTM

test/test_son.py Outdated
Comment on lines +153 to +154
self.assertTrue(2 in test_son, "'in' operator failed for key 2")
self.assertFalse(22 in test_son, "'in' operator succeeded when it shouldn't")
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
self.assertTrue(2 in test_son, "'in' operator failed for key 2")
self.assertFalse(22 in test_son, "'in' operator succeeded when it shouldn't")

The above line of assertIn already runs that validation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Different values. Line 153 is checking 2. Line 154 is checking 22.

Copy link
Contributor

@sleepyStick sleepyStick Mar 17, 2026

Choose a reason for hiding this comment

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

I think @Jibola was saying that like 153 does the same thing as line 151 and line 154 is the same as line 152. (and if so, I agree lol)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah! Good catch thanks

bson/son.py contains three methods that were added for Python 2 compatibility but are no longer needed
@aclark4life
Copy link
Contributor Author

@sleepyStick Sorry, I rebased can you approve again? Thanks

@aclark4life aclark4life requested a review from sleepyStick March 18, 2026 17:24
@aclark4life
Copy link
Contributor Author

And … sorry I guess I needed @Jibola ! Thanks all

@aclark4life aclark4life merged commit ec9d954 into mongodb:master Mar 18, 2026
87 of 89 checks passed
@aclark4life aclark4life deleted the PYTHON-5757 branch March 18, 2026 21:46
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.

5 participants