Skip to content

bulkcopy_arrow() / bulkcopy()` broken in 1.16.0 #855

Open

Description

@sanjaywa

Title

bulkcopy_arrow() / bulkcopy() broken in 1.16.0: AttributeError: module 'mssql_py_core' has no attribute 'PyCoreConnection'

Description

After upgrading from 1.15.0 to 1.16.0, any call to cursor.bulkcopy_arrow(...) (and presumably cursor.bulkcopy(...), which shares the same pycore connection path) fails immediately with:

AttributeError: module 'mssql_py_core' has no attribute 'PyCoreConnection'

Full traceback:

File ".../site-packages/mssql_python/cursor.py", line 3764, in bulkcopy_arrow
    pycore_connection = mssql_py_core.PyCoreConnection(
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'mssql_py_core' has no attribute 'PyCoreConnection'

This reproduces on a clean pip install mssql-python==1.16.0 with no other code changes — the exact same script works correctly against 1.15.0.

Root cause

This looks like a packaging regression from the 1.16.0 change that split the Rust runtime out into a separate version-matched mssql-python-rs package (per the 1.16.0 release notes).

On Windows, after pip install mssql-python==1.16.0, the compiled extension lands at:

site-packages/mssql_py_core/mssql_py_core.pyd

There is no __init__.py inside site-packages/mssql_py_core/. As a result, import mssql_py_core resolves to an empty implicit namespace package (PEP 420) rather than loading the compiled extension — so mssql_py_core.PyCoreConnection doesn't exist at that path.

The compiled extension itself is fine and fully functional — it just needs to be imported one level deeper:

import mssql_py_core.mssql_py_core as core
print([a for a in dir(core) if "Connection" in a])
# -> ['PyAsyncConnection', 'PyCoreConnection']

But mssql_python/cursor.py's bulkcopy_arrow (and likely bulkcopy) does a plain top-level import mssql_py_core and then calls mssql_py_core.PyCoreConnection(...) directly, which hits the empty namespace package instead of the real module.

Likely fix: either (a) add an __init__.py to the mssql_py_core package in the mssql-python-rs wheel that re-exports from the nested mssql_py_core.mssql_py_core extension module, or (b) update mssql-python's internal imports to reference mssql_py_core.mssql_py_core explicitly.

Environment

  • mssql-python: 1.16.0 (regression; works correctly on 1.15.0)
  • mssql-python-rs: 0.3.0
  • mssql-python-odbc: 18.6.2.2
  • Python: 3.11.0
  • OS: Windows 10/11 (Windows-10-10.0.26200-SP0), x86_64
  • Install method: pip install mssql-python==1.16.0 (clean upgrade from 1.15.0 in an existing venv)

Reproduction steps

pip install mssql-python==1.16.0
python -c "
import mssql_python
cn = mssql_python.connect('SERVER=...;DATABASE=...;Trusted_Connection=yes;')
cur = cn.cursor()
cur.bulkcopy_arrow('some_table', some_pyarrow_record_batch_reader)
"

Minimal repro of the underlying import issue (no SQL Server connection needed):

import mssql_py_core
print(mssql_py_core.__file__)          # None -- confirms empty namespace package
print(hasattr(mssql_py_core, "PyCoreConnection"))  # False

import mssql_py_core.mssql_py_core as core
print(core.__file__)                   # points to the real .pyd
print(hasattr(core, "PyCoreConnection"))  # True

Expected behavior

import mssql_py_core should expose PyCoreConnection (and PyAsyncConnection) at the top level, as it presumably did before the 1.16.0 packaging split, so bulkcopy_arrow()/bulkcopy() work without modification.

Actual behavior

bulkcopy_arrow() / bulkcopy() are completely broken on 1.16.0 for Windows installs via pip, with no workaround short of pinning back to 1.15.0.

Impact

This blocks all bulk-copy / Arrow bulk-load workflows on 1.16.0. We've rolled back to 1.15.0 in the meantime.

Activity

  1. github-actions commented on Oct 21, 2026

    @github-actions

    Hi sanjaywa, thank you for opening this issue!

    Our team will review it shortly. We aim to triage all new issues within 24-48 hours and get back to you.

    If you have additional information to share, please feel free to update the issue.

    Thank you for your patience!

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage neededFor new issues, not triaged yet.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions