GH-36730: [Python] Add support for Cython 3.0.0 - #36745

Closed
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3
Closed

GH-36730: [Python] Add support for Cython 3.0.0#36745
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3

Conversation

@kou

@koukou commented Jul 18, 2023

Copy link
Copy Markdown
Member

Rationale for this change

Cython 3.0.0 is the latest release. PyArrow should work with Cython 3.0.0.

What changes are included in this PR?

Are these changes tested?

Yes.

Are there any user-facing changes?

Yes.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #36730has been automatically assigned in GitHub to PR creator.

@kou
kou marked this pull request as ready for review July 18, 2023 09:31
@pitrou

Copy link
Copy Markdown
Member

This may fix the compilation error but there are other issues during tests (see macOS CI?).

@kou

kou commented Jul 18, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed CI failures.

@jorisvandenbossche

jorisvandenbossche commented Jul 19, 2023

Copy link
Copy Markdown
Member

@kou there were also some runtime errors in the minimal build that are caused by cython 3 (but it's strange that this is only failing in a single build). Based on your diff, I don't think that will already be fixed here, but let me run them to be sure.

@jorisvandenbossche

Copy link
Copy Markdown
Member

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: dba6bb4c1adcb233aabce3d595706b5fc104b660

Submitted crossbow builds: ursacomputing/crossbow @ actions-f3bbf75ac8

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@pitrou

Copy link
Copy Markdown
Member

Can this PR also undo the pinning on various Python builds?

@apacheapache deleted a comment from github-actionsBotJul 19, 2023
@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: 81493b1fa6e3db21630c29ccad0e92499a2a43ff

Submitted crossbow builds: ursacomputing/crossbow @ actions-492c6d5c7d

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed the generator related problem.
I'll rebase on main and unpin Cython version.

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

Hmm. Can we detect Cython version in .{pyx,pxi}?

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

I want to write something like the following:

diff --git a/python/pyarrow/scalar.pxi b/python/pyarrow/scalar.pxi
index f438c8847..61de38203 100644
--- a/python/pyarrow/scalar.pxi+++ b/python/pyarrow/scalar.pxi@@ -793,7 +793,10 @@ cdef class MapScalar(ListScalar):
"""
arr = self.values
if array is None:
- raise StopIteration+ if Cython.__version__ < '3.0.0':+ raise StopIteration+ else:+ return
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

@pitrou

Copy link
Copy Markdown
Member

There should not be any need to raise StopIteration.

Comment threadpython/pyarrow/ipc.pxi Outdated
Comment on lines +438 to +444
def __iter__(self):
while True:
yield self.read_next_message()
try:
yield self.read_next_message()
except StopIteration:
# For Cython >= 3.0.0
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know if it is this code that gives problems to be written in a way that works for both cython 0.29 and 3, but a potential different way of writing it:

def __iter__(self):
return self
def __next__(self):
return self.read_next_message()

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I'll try it.

@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Jul 20, 2023
if arr is None:
raise StopIteration
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you actually test these changes before pushing them?

You can't use yield in a __next__ function.
Either you write __iter__ as a generator (using yield), or you write a pair of __iter__ and __next__ functions (without yield). You can't mix the two styles.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And FWIW, for this case, I would leave the __iter__ as is (in the other cases such as RecordBatchReader, we already have a public "next" method that can just be called from __next__)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Sorry. I didn't test on local before I pushed a commit because I don't have enough time yesterday.

I reverted the __iter__ + __next__ change.

@lidavidmlidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Flight changes LGTM, thanks!

@github-actionsgithub-actionsBot added awaiting merge Awaiting merge and removed awaiting changes Awaiting changes labels Jul 20, 2023
@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels Jul 20, 2023
@github-actionsgithub-actionsBot added Component: Documentation awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jul 20, 2023
@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

@jorisvandenbossche Do you have any idea why the following failure was happen?

https://github.com/apache/arrow/actions/runs/5615711782/job/15216554355?pr=36745#step:6:6074

 =================================== FAILURES ===================================
_______________________ test_cloudpickle_dataset[False] ________________________
tempdir = PosixPath('/tmp/pytest-of-root/pytest-0/test_cloudpickle_dataset_False0')
datadir = PosixPath('/opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/data/parquet')
use_legacy_dataset = False
@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
> _assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1572: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1540: in _assert_dataset_is_picklable
assert is_pickleable(dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1538: in is_pickleable
return obj == pickler.loads(pickler.dumps(obj))
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:73: in dumps
cp.dump(obj)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <cloudpickle.cloudpickle_fast.CloudPickler object at 0x7f25aa27aa10>
obj = <pyarrow.parquet.core._ParquetDatasetV2 object at 0x7f25a9ec9690>
def dump(self, obj):
try:
> return Pickler.dump(self, obj)
E _pickle.PicklingError: Can't pickle <cyfunction ParquetFragmentScanOptions._reconstruct at 0x7f2660177140>: it's not the same object as pyarrow._dataset_parquet.ParquetFragmentScanOptions._reconstruct
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:632: PicklingError

@jorisvandenbossche

Copy link
Copy Markdown
Member

Not directly an idea. We use the same pattern in many other places. Can you try this patch:

--- a/python/pyarrow/_dataset_parquet.pyx+++ b/python/pyarrow/_dataset_parquet.pyx@@ -741,7 +741,7 @@ cdef class ParquetFragmentScanOptions(FragmentScanOptions):
thrift_string_size_limit=self.thrift_string_size_limit,
thrift_container_size_limit=self.thrift_container_size_limit,
)
- return type(self)._reconstruct, (kwargs,)+ return ParquetFragmentScanOptions._reconstruct, (kwargs,)

(in theory it shouldn't matter for python, but maybe cython 3 has a bug that treats this different)

@kou

kou commented Jul 21, 2023

Copy link
Copy Markdown
MemberAuthor

Thanks! I've pushed your patch.

@h-vetinari

Copy link
Copy Markdown
Contributor

If there are problems with compatibility between 0.29 and 3.0 (aside from the few intentional breaking changes), the Cython devs are usually quick to respond if you open an issue

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

The failing pickle test is only when using the cloudpickle module instead of the pickle5/pickle module. Perhaps they don't support cython3.0.0 yet? This is the only test in the entire codebase that tests cloudpickle.. not sure how important it is as a dependency to pyarrow.

@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
_assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)

@pitrou

Copy link
Copy Markdown
Member

Well, first, this PR should be rebased, because there are conflicts.

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

I did rebase/squash to test things out here: #37097

I wanted to experiment without polluting this PR. I can merge any fixes I find back into this PR.

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

Can we use #37097 instead of this?

@danepitkin

Copy link
Copy Markdown
Member

Can we use #37097 instead of this?

Sure!

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

I close this in favor of #37097.

@koukou closed this Aug 11, 2023
@kou
kou deleted the python-cython-3 branch April 3, 2026 00:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI][Python] Cython 3.0 seems to make our build of pyarrow fail

6 participants

@kou@pitrou@jorisvandenbossche@h-vetinari@danepitkin@lidavidm
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

GH-36730: [Python] Add support for Cython 3.0.0 - #36745

Closed
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3
Closed

GH-36730: [Python] Add support for Cython 3.0.0#36745
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3

Conversation

@kou

@koukou commented Jul 18, 2023

Copy link
Copy Markdown
Member

Rationale for this change

Cython 3.0.0 is the latest release. PyArrow should work with Cython 3.0.0.

What changes are included in this PR?

Are these changes tested?

Yes.

Are there any user-facing changes?

Yes.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #36730has been automatically assigned in GitHub to PR creator.

@kou
kou marked this pull request as ready for review July 18, 2023 09:31
@pitrou

Copy link
Copy Markdown
Member

This may fix the compilation error but there are other issues during tests (see macOS CI?).

@kou

kou commented Jul 18, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed CI failures.

@jorisvandenbossche

jorisvandenbossche commented Jul 19, 2023

Copy link
Copy Markdown
Member

@kou there were also some runtime errors in the minimal build that are caused by cython 3 (but it's strange that this is only failing in a single build). Based on your diff, I don't think that will already be fixed here, but let me run them to be sure.

@jorisvandenbossche

Copy link
Copy Markdown
Member

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: dba6bb4c1adcb233aabce3d595706b5fc104b660

Submitted crossbow builds: ursacomputing/crossbow @ actions-f3bbf75ac8

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@pitrou

Copy link
Copy Markdown
Member

Can this PR also undo the pinning on various Python builds?

@apacheapache deleted a comment from github-actionsBotJul 19, 2023
@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: 81493b1fa6e3db21630c29ccad0e92499a2a43ff

Submitted crossbow builds: ursacomputing/crossbow @ actions-492c6d5c7d

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed the generator related problem.
I'll rebase on main and unpin Cython version.

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

Hmm. Can we detect Cython version in .{pyx,pxi}?

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

I want to write something like the following:

diff --git a/python/pyarrow/scalar.pxi b/python/pyarrow/scalar.pxi
index f438c8847..61de38203 100644
--- a/python/pyarrow/scalar.pxi+++ b/python/pyarrow/scalar.pxi@@ -793,7 +793,10 @@ cdef class MapScalar(ListScalar):
"""
arr = self.values
if array is None:
- raise StopIteration+ if Cython.__version__ < '3.0.0':+ raise StopIteration+ else:+ return
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

@pitrou

Copy link
Copy Markdown
Member

There should not be any need to raise StopIteration.

Comment threadpython/pyarrow/ipc.pxi Outdated
Comment on lines +438 to +444
def __iter__(self):
while True:
yield self.read_next_message()
try:
yield self.read_next_message()
except StopIteration:
# For Cython >= 3.0.0
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know if it is this code that gives problems to be written in a way that works for both cython 0.29 and 3, but a potential different way of writing it:

def __iter__(self):
return self
def __next__(self):
return self.read_next_message()

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I'll try it.

@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Jul 20, 2023
if arr is None:
raise StopIteration
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you actually test these changes before pushing them?

You can't use yield in a __next__ function.
Either you write __iter__ as a generator (using yield), or you write a pair of __iter__ and __next__ functions (without yield). You can't mix the two styles.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And FWIW, for this case, I would leave the __iter__ as is (in the other cases such as RecordBatchReader, we already have a public "next" method that can just be called from __next__)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Sorry. I didn't test on local before I pushed a commit because I don't have enough time yesterday.

I reverted the __iter__ + __next__ change.

@lidavidmlidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Flight changes LGTM, thanks!

@github-actionsgithub-actionsBot added awaiting merge Awaiting merge and removed awaiting changes Awaiting changes labels Jul 20, 2023
@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels Jul 20, 2023
@github-actionsgithub-actionsBot added Component: Documentation awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jul 20, 2023
@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

@jorisvandenbossche Do you have any idea why the following failure was happen?

https://github.com/apache/arrow/actions/runs/5615711782/job/15216554355?pr=36745#step:6:6074

 =================================== FAILURES ===================================
_______________________ test_cloudpickle_dataset[False] ________________________
tempdir = PosixPath('/tmp/pytest-of-root/pytest-0/test_cloudpickle_dataset_False0')
datadir = PosixPath('/opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/data/parquet')
use_legacy_dataset = False
@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
> _assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1572: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1540: in _assert_dataset_is_picklable
assert is_pickleable(dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1538: in is_pickleable
return obj == pickler.loads(pickler.dumps(obj))
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:73: in dumps
cp.dump(obj)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <cloudpickle.cloudpickle_fast.CloudPickler object at 0x7f25aa27aa10>
obj = <pyarrow.parquet.core._ParquetDatasetV2 object at 0x7f25a9ec9690>
def dump(self, obj):
try:
> return Pickler.dump(self, obj)
E _pickle.PicklingError: Can't pickle <cyfunction ParquetFragmentScanOptions._reconstruct at 0x7f2660177140>: it's not the same object as pyarrow._dataset_parquet.ParquetFragmentScanOptions._reconstruct
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:632: PicklingError

@jorisvandenbossche

Copy link
Copy Markdown
Member

Not directly an idea. We use the same pattern in many other places. Can you try this patch:

--- a/python/pyarrow/_dataset_parquet.pyx+++ b/python/pyarrow/_dataset_parquet.pyx@@ -741,7 +741,7 @@ cdef class ParquetFragmentScanOptions(FragmentScanOptions):
thrift_string_size_limit=self.thrift_string_size_limit,
thrift_container_size_limit=self.thrift_container_size_limit,
)
- return type(self)._reconstruct, (kwargs,)+ return ParquetFragmentScanOptions._reconstruct, (kwargs,)

(in theory it shouldn't matter for python, but maybe cython 3 has a bug that treats this different)

@kou

kou commented Jul 21, 2023

Copy link
Copy Markdown
MemberAuthor

Thanks! I've pushed your patch.

@h-vetinari

Copy link
Copy Markdown
Contributor

If there are problems with compatibility between 0.29 and 3.0 (aside from the few intentional breaking changes), the Cython devs are usually quick to respond if you open an issue

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

The failing pickle test is only when using the cloudpickle module instead of the pickle5/pickle module. Perhaps they don't support cython3.0.0 yet? This is the only test in the entire codebase that tests cloudpickle.. not sure how important it is as a dependency to pyarrow.

@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
_assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)

@pitrou

Copy link
Copy Markdown
Member

Well, first, this PR should be rebased, because there are conflicts.

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

I did rebase/squash to test things out here: #37097

I wanted to experiment without polluting this PR. I can merge any fixes I find back into this PR.

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

Can we use #37097 instead of this?

@danepitkin

Copy link
Copy Markdown
Member

Can we use #37097 instead of this?

Sure!

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

I close this in favor of #37097.

@koukou closed this Aug 11, 2023
@kou
kou deleted the python-cython-3 branch April 3, 2026 00:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI][Python] Cython 3.0 seems to make our build of pyarrow fail

6 participants

@kou@pitrou@jorisvandenbossche@h-vetinari@danepitkin@lidavidm
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

GH-36730: [Python] Add support for Cython 3.0.0 - #36745

Closed
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3
Closed

GH-36730: [Python] Add support for Cython 3.0.0#36745
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3

Conversation

@kou

@koukou commented Jul 18, 2023

Copy link
Copy Markdown
Member

Rationale for this change

Cython 3.0.0 is the latest release. PyArrow should work with Cython 3.0.0.

What changes are included in this PR?

Are these changes tested?

Yes.

Are there any user-facing changes?

Yes.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #36730has been automatically assigned in GitHub to PR creator.

@kou
kou marked this pull request as ready for review July 18, 2023 09:31
@pitrou

Copy link
Copy Markdown
Member

This may fix the compilation error but there are other issues during tests (see macOS CI?).

@kou

kou commented Jul 18, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed CI failures.

@jorisvandenbossche

jorisvandenbossche commented Jul 19, 2023

Copy link
Copy Markdown
Member

@kou there were also some runtime errors in the minimal build that are caused by cython 3 (but it's strange that this is only failing in a single build). Based on your diff, I don't think that will already be fixed here, but let me run them to be sure.

@jorisvandenbossche

Copy link
Copy Markdown
Member

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: dba6bb4c1adcb233aabce3d595706b5fc104b660

Submitted crossbow builds: ursacomputing/crossbow @ actions-f3bbf75ac8

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@pitrou

Copy link
Copy Markdown
Member

Can this PR also undo the pinning on various Python builds?

@apacheapache deleted a comment from github-actionsBotJul 19, 2023
@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: 81493b1fa6e3db21630c29ccad0e92499a2a43ff

Submitted crossbow builds: ursacomputing/crossbow @ actions-492c6d5c7d

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed the generator related problem.
I'll rebase on main and unpin Cython version.

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

Hmm. Can we detect Cython version in .{pyx,pxi}?

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

I want to write something like the following:

diff --git a/python/pyarrow/scalar.pxi b/python/pyarrow/scalar.pxi
index f438c8847..61de38203 100644
--- a/python/pyarrow/scalar.pxi+++ b/python/pyarrow/scalar.pxi@@ -793,7 +793,10 @@ cdef class MapScalar(ListScalar):
"""
arr = self.values
if array is None:
- raise StopIteration+ if Cython.__version__ < '3.0.0':+ raise StopIteration+ else:+ return
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

@pitrou

Copy link
Copy Markdown
Member

There should not be any need to raise StopIteration.

Comment threadpython/pyarrow/ipc.pxi Outdated
Comment on lines +438 to +444
def __iter__(self):
while True:
yield self.read_next_message()
try:
yield self.read_next_message()
except StopIteration:
# For Cython >= 3.0.0
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know if it is this code that gives problems to be written in a way that works for both cython 0.29 and 3, but a potential different way of writing it:

def __iter__(self):
return self
def __next__(self):
return self.read_next_message()

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I'll try it.

@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Jul 20, 2023
if arr is None:
raise StopIteration
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you actually test these changes before pushing them?

You can't use yield in a __next__ function.
Either you write __iter__ as a generator (using yield), or you write a pair of __iter__ and __next__ functions (without yield). You can't mix the two styles.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And FWIW, for this case, I would leave the __iter__ as is (in the other cases such as RecordBatchReader, we already have a public "next" method that can just be called from __next__)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Sorry. I didn't test on local before I pushed a commit because I don't have enough time yesterday.

I reverted the __iter__ + __next__ change.

@lidavidmlidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Flight changes LGTM, thanks!

@github-actionsgithub-actionsBot added awaiting merge Awaiting merge and removed awaiting changes Awaiting changes labels Jul 20, 2023
@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels Jul 20, 2023
@github-actionsgithub-actionsBot added Component: Documentation awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jul 20, 2023
@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

@jorisvandenbossche Do you have any idea why the following failure was happen?

https://github.com/apache/arrow/actions/runs/5615711782/job/15216554355?pr=36745#step:6:6074

 =================================== FAILURES ===================================
_______________________ test_cloudpickle_dataset[False] ________________________
tempdir = PosixPath('/tmp/pytest-of-root/pytest-0/test_cloudpickle_dataset_False0')
datadir = PosixPath('/opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/data/parquet')
use_legacy_dataset = False
@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
> _assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1572: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1540: in _assert_dataset_is_picklable
assert is_pickleable(dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1538: in is_pickleable
return obj == pickler.loads(pickler.dumps(obj))
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:73: in dumps
cp.dump(obj)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <cloudpickle.cloudpickle_fast.CloudPickler object at 0x7f25aa27aa10>
obj = <pyarrow.parquet.core._ParquetDatasetV2 object at 0x7f25a9ec9690>
def dump(self, obj):
try:
> return Pickler.dump(self, obj)
E _pickle.PicklingError: Can't pickle <cyfunction ParquetFragmentScanOptions._reconstruct at 0x7f2660177140>: it's not the same object as pyarrow._dataset_parquet.ParquetFragmentScanOptions._reconstruct
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:632: PicklingError

@jorisvandenbossche

Copy link
Copy Markdown
Member

Not directly an idea. We use the same pattern in many other places. Can you try this patch:

--- a/python/pyarrow/_dataset_parquet.pyx+++ b/python/pyarrow/_dataset_parquet.pyx@@ -741,7 +741,7 @@ cdef class ParquetFragmentScanOptions(FragmentScanOptions):
thrift_string_size_limit=self.thrift_string_size_limit,
thrift_container_size_limit=self.thrift_container_size_limit,
)
- return type(self)._reconstruct, (kwargs,)+ return ParquetFragmentScanOptions._reconstruct, (kwargs,)

(in theory it shouldn't matter for python, but maybe cython 3 has a bug that treats this different)

@kou

kou commented Jul 21, 2023

Copy link
Copy Markdown
MemberAuthor

Thanks! I've pushed your patch.

@h-vetinari

Copy link
Copy Markdown
Contributor

If there are problems with compatibility between 0.29 and 3.0 (aside from the few intentional breaking changes), the Cython devs are usually quick to respond if you open an issue

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

The failing pickle test is only when using the cloudpickle module instead of the pickle5/pickle module. Perhaps they don't support cython3.0.0 yet? This is the only test in the entire codebase that tests cloudpickle.. not sure how important it is as a dependency to pyarrow.

@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
_assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)

@pitrou

Copy link
Copy Markdown
Member

Well, first, this PR should be rebased, because there are conflicts.

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

I did rebase/squash to test things out here: #37097

I wanted to experiment without polluting this PR. I can merge any fixes I find back into this PR.

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

Can we use #37097 instead of this?

@danepitkin

Copy link
Copy Markdown
Member

Can we use #37097 instead of this?

Sure!

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

I close this in favor of #37097.

@koukou closed this Aug 11, 2023
@kou
kou deleted the python-cython-3 branch April 3, 2026 00:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI][Python] Cython 3.0 seems to make our build of pyarrow fail

6 participants

@kou@pitrou@jorisvandenbossche@h-vetinari@danepitkin@lidavidm
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

GH-36730: [Python] Add support for Cython 3.0.0 - #36745

Closed
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3
Closed

GH-36730: [Python] Add support for Cython 3.0.0#36745
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3

Conversation

@kou

@koukou commented Jul 18, 2023

Copy link
Copy Markdown
Member

Rationale for this change

Cython 3.0.0 is the latest release. PyArrow should work with Cython 3.0.0.

What changes are included in this PR?

Are these changes tested?

Yes.

Are there any user-facing changes?

Yes.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #36730has been automatically assigned in GitHub to PR creator.

@kou
kou marked this pull request as ready for review July 18, 2023 09:31
@pitrou

Copy link
Copy Markdown
Member

This may fix the compilation error but there are other issues during tests (see macOS CI?).

@kou

kou commented Jul 18, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed CI failures.

@jorisvandenbossche

jorisvandenbossche commented Jul 19, 2023

Copy link
Copy Markdown
Member

@kou there were also some runtime errors in the minimal build that are caused by cython 3 (but it's strange that this is only failing in a single build). Based on your diff, I don't think that will already be fixed here, but let me run them to be sure.

@jorisvandenbossche

Copy link
Copy Markdown
Member

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: dba6bb4c1adcb233aabce3d595706b5fc104b660

Submitted crossbow builds: ursacomputing/crossbow @ actions-f3bbf75ac8

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@pitrou

Copy link
Copy Markdown
Member

Can this PR also undo the pinning on various Python builds?

@apacheapache deleted a comment from github-actionsBotJul 19, 2023
@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: 81493b1fa6e3db21630c29ccad0e92499a2a43ff

Submitted crossbow builds: ursacomputing/crossbow @ actions-492c6d5c7d

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed the generator related problem.
I'll rebase on main and unpin Cython version.

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

Hmm. Can we detect Cython version in .{pyx,pxi}?

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

I want to write something like the following:

diff --git a/python/pyarrow/scalar.pxi b/python/pyarrow/scalar.pxi
index f438c8847..61de38203 100644
--- a/python/pyarrow/scalar.pxi+++ b/python/pyarrow/scalar.pxi@@ -793,7 +793,10 @@ cdef class MapScalar(ListScalar):
"""
arr = self.values
if array is None:
- raise StopIteration+ if Cython.__version__ < '3.0.0':+ raise StopIteration+ else:+ return
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

@pitrou

Copy link
Copy Markdown
Member

There should not be any need to raise StopIteration.

Comment threadpython/pyarrow/ipc.pxi Outdated
Comment on lines +438 to +444
def __iter__(self):
while True:
yield self.read_next_message()
try:
yield self.read_next_message()
except StopIteration:
# For Cython >= 3.0.0
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know if it is this code that gives problems to be written in a way that works for both cython 0.29 and 3, but a potential different way of writing it:

def __iter__(self):
return self
def __next__(self):
return self.read_next_message()

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I'll try it.

@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Jul 20, 2023
if arr is None:
raise StopIteration
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you actually test these changes before pushing them?

You can't use yield in a __next__ function.
Either you write __iter__ as a generator (using yield), or you write a pair of __iter__ and __next__ functions (without yield). You can't mix the two styles.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And FWIW, for this case, I would leave the __iter__ as is (in the other cases such as RecordBatchReader, we already have a public "next" method that can just be called from __next__)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Sorry. I didn't test on local before I pushed a commit because I don't have enough time yesterday.

I reverted the __iter__ + __next__ change.

@lidavidmlidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Flight changes LGTM, thanks!

@github-actionsgithub-actionsBot added awaiting merge Awaiting merge and removed awaiting changes Awaiting changes labels Jul 20, 2023
@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels Jul 20, 2023
@github-actionsgithub-actionsBot added Component: Documentation awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jul 20, 2023
@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

@jorisvandenbossche Do you have any idea why the following failure was happen?

https://github.com/apache/arrow/actions/runs/5615711782/job/15216554355?pr=36745#step:6:6074

 =================================== FAILURES ===================================
_______________________ test_cloudpickle_dataset[False] ________________________
tempdir = PosixPath('/tmp/pytest-of-root/pytest-0/test_cloudpickle_dataset_False0')
datadir = PosixPath('/opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/data/parquet')
use_legacy_dataset = False
@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
> _assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1572: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1540: in _assert_dataset_is_picklable
assert is_pickleable(dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1538: in is_pickleable
return obj == pickler.loads(pickler.dumps(obj))
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:73: in dumps
cp.dump(obj)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <cloudpickle.cloudpickle_fast.CloudPickler object at 0x7f25aa27aa10>
obj = <pyarrow.parquet.core._ParquetDatasetV2 object at 0x7f25a9ec9690>
def dump(self, obj):
try:
> return Pickler.dump(self, obj)
E _pickle.PicklingError: Can't pickle <cyfunction ParquetFragmentScanOptions._reconstruct at 0x7f2660177140>: it's not the same object as pyarrow._dataset_parquet.ParquetFragmentScanOptions._reconstruct
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:632: PicklingError

@jorisvandenbossche

Copy link
Copy Markdown
Member

Not directly an idea. We use the same pattern in many other places. Can you try this patch:

--- a/python/pyarrow/_dataset_parquet.pyx+++ b/python/pyarrow/_dataset_parquet.pyx@@ -741,7 +741,7 @@ cdef class ParquetFragmentScanOptions(FragmentScanOptions):
thrift_string_size_limit=self.thrift_string_size_limit,
thrift_container_size_limit=self.thrift_container_size_limit,
)
- return type(self)._reconstruct, (kwargs,)+ return ParquetFragmentScanOptions._reconstruct, (kwargs,)

(in theory it shouldn't matter for python, but maybe cython 3 has a bug that treats this different)

@kou

kou commented Jul 21, 2023

Copy link
Copy Markdown
MemberAuthor

Thanks! I've pushed your patch.

@h-vetinari

Copy link
Copy Markdown
Contributor

If there are problems with compatibility between 0.29 and 3.0 (aside from the few intentional breaking changes), the Cython devs are usually quick to respond if you open an issue

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

The failing pickle test is only when using the cloudpickle module instead of the pickle5/pickle module. Perhaps they don't support cython3.0.0 yet? This is the only test in the entire codebase that tests cloudpickle.. not sure how important it is as a dependency to pyarrow.

@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
_assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)

@pitrou

Copy link
Copy Markdown
Member

Well, first, this PR should be rebased, because there are conflicts.

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

I did rebase/squash to test things out here: #37097

I wanted to experiment without polluting this PR. I can merge any fixes I find back into this PR.

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

Can we use #37097 instead of this?

@danepitkin

Copy link
Copy Markdown
Member

Can we use #37097 instead of this?

Sure!

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

I close this in favor of #37097.

@koukou closed this Aug 11, 2023
@kou
kou deleted the python-cython-3 branch April 3, 2026 00:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI][Python] Cython 3.0 seems to make our build of pyarrow fail

6 participants

@kou@pitrou@jorisvandenbossche@h-vetinari@danepitkin@lidavidm
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

GH-36730: [Python] Add support for Cython 3.0.0 - #36745

Closed
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3
Closed

GH-36730: [Python] Add support for Cython 3.0.0#36745
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3

Conversation

@kou

@koukou commented Jul 18, 2023

Copy link
Copy Markdown
Member

Rationale for this change

Cython 3.0.0 is the latest release. PyArrow should work with Cython 3.0.0.

What changes are included in this PR?

Are these changes tested?

Yes.

Are there any user-facing changes?

Yes.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #36730has been automatically assigned in GitHub to PR creator.

@kou
kou marked this pull request as ready for review July 18, 2023 09:31
@pitrou

Copy link
Copy Markdown
Member

This may fix the compilation error but there are other issues during tests (see macOS CI?).

@kou

kou commented Jul 18, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed CI failures.

@jorisvandenbossche

jorisvandenbossche commented Jul 19, 2023

Copy link
Copy Markdown
Member

@kou there were also some runtime errors in the minimal build that are caused by cython 3 (but it's strange that this is only failing in a single build). Based on your diff, I don't think that will already be fixed here, but let me run them to be sure.

@jorisvandenbossche

Copy link
Copy Markdown
Member

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: dba6bb4c1adcb233aabce3d595706b5fc104b660

Submitted crossbow builds: ursacomputing/crossbow @ actions-f3bbf75ac8

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@pitrou

Copy link
Copy Markdown
Member

Can this PR also undo the pinning on various Python builds?

@apacheapache deleted a comment from github-actionsBotJul 19, 2023
@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: 81493b1fa6e3db21630c29ccad0e92499a2a43ff

Submitted crossbow builds: ursacomputing/crossbow @ actions-492c6d5c7d

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed the generator related problem.
I'll rebase on main and unpin Cython version.

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

Hmm. Can we detect Cython version in .{pyx,pxi}?

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

I want to write something like the following:

diff --git a/python/pyarrow/scalar.pxi b/python/pyarrow/scalar.pxi
index f438c8847..61de38203 100644
--- a/python/pyarrow/scalar.pxi+++ b/python/pyarrow/scalar.pxi@@ -793,7 +793,10 @@ cdef class MapScalar(ListScalar):
"""
arr = self.values
if array is None:
- raise StopIteration+ if Cython.__version__ < '3.0.0':+ raise StopIteration+ else:+ return
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

@pitrou

Copy link
Copy Markdown
Member

There should not be any need to raise StopIteration.

Comment threadpython/pyarrow/ipc.pxi Outdated
Comment on lines +438 to +444
def __iter__(self):
while True:
yield self.read_next_message()
try:
yield self.read_next_message()
except StopIteration:
# For Cython >= 3.0.0
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know if it is this code that gives problems to be written in a way that works for both cython 0.29 and 3, but a potential different way of writing it:

def __iter__(self):
return self
def __next__(self):
return self.read_next_message()

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I'll try it.

@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Jul 20, 2023
if arr is None:
raise StopIteration
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you actually test these changes before pushing them?

You can't use yield in a __next__ function.
Either you write __iter__ as a generator (using yield), or you write a pair of __iter__ and __next__ functions (without yield). You can't mix the two styles.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And FWIW, for this case, I would leave the __iter__ as is (in the other cases such as RecordBatchReader, we already have a public "next" method that can just be called from __next__)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Sorry. I didn't test on local before I pushed a commit because I don't have enough time yesterday.

I reverted the __iter__ + __next__ change.

@lidavidmlidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Flight changes LGTM, thanks!

@github-actionsgithub-actionsBot added awaiting merge Awaiting merge and removed awaiting changes Awaiting changes labels Jul 20, 2023
@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels Jul 20, 2023
@github-actionsgithub-actionsBot added Component: Documentation awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jul 20, 2023
@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

@jorisvandenbossche Do you have any idea why the following failure was happen?

https://github.com/apache/arrow/actions/runs/5615711782/job/15216554355?pr=36745#step:6:6074

 =================================== FAILURES ===================================
_______________________ test_cloudpickle_dataset[False] ________________________
tempdir = PosixPath('/tmp/pytest-of-root/pytest-0/test_cloudpickle_dataset_False0')
datadir = PosixPath('/opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/data/parquet')
use_legacy_dataset = False
@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
> _assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1572: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1540: in _assert_dataset_is_picklable
assert is_pickleable(dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1538: in is_pickleable
return obj == pickler.loads(pickler.dumps(obj))
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:73: in dumps
cp.dump(obj)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <cloudpickle.cloudpickle_fast.CloudPickler object at 0x7f25aa27aa10>
obj = <pyarrow.parquet.core._ParquetDatasetV2 object at 0x7f25a9ec9690>
def dump(self, obj):
try:
> return Pickler.dump(self, obj)
E _pickle.PicklingError: Can't pickle <cyfunction ParquetFragmentScanOptions._reconstruct at 0x7f2660177140>: it's not the same object as pyarrow._dataset_parquet.ParquetFragmentScanOptions._reconstruct
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:632: PicklingError

@jorisvandenbossche

Copy link
Copy Markdown
Member

Not directly an idea. We use the same pattern in many other places. Can you try this patch:

--- a/python/pyarrow/_dataset_parquet.pyx+++ b/python/pyarrow/_dataset_parquet.pyx@@ -741,7 +741,7 @@ cdef class ParquetFragmentScanOptions(FragmentScanOptions):
thrift_string_size_limit=self.thrift_string_size_limit,
thrift_container_size_limit=self.thrift_container_size_limit,
)
- return type(self)._reconstruct, (kwargs,)+ return ParquetFragmentScanOptions._reconstruct, (kwargs,)

(in theory it shouldn't matter for python, but maybe cython 3 has a bug that treats this different)

@kou

kou commented Jul 21, 2023

Copy link
Copy Markdown
MemberAuthor

Thanks! I've pushed your patch.

@h-vetinari

Copy link
Copy Markdown
Contributor

If there are problems with compatibility between 0.29 and 3.0 (aside from the few intentional breaking changes), the Cython devs are usually quick to respond if you open an issue

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

The failing pickle test is only when using the cloudpickle module instead of the pickle5/pickle module. Perhaps they don't support cython3.0.0 yet? This is the only test in the entire codebase that tests cloudpickle.. not sure how important it is as a dependency to pyarrow.

@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
_assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)

@pitrou

Copy link
Copy Markdown
Member

Well, first, this PR should be rebased, because there are conflicts.

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

I did rebase/squash to test things out here: #37097

I wanted to experiment without polluting this PR. I can merge any fixes I find back into this PR.

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

Can we use #37097 instead of this?

@danepitkin

Copy link
Copy Markdown
Member

Can we use #37097 instead of this?

Sure!

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

I close this in favor of #37097.

@koukou closed this Aug 11, 2023
@kou
kou deleted the python-cython-3 branch April 3, 2026 00:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI][Python] Cython 3.0 seems to make our build of pyarrow fail

6 participants

@kou@pitrou@jorisvandenbossche@h-vetinari@danepitkin@lidavidm
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

GH-36730: [Python] Add support for Cython 3.0.0 - #36745

Closed
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3
Closed

GH-36730: [Python] Add support for Cython 3.0.0#36745
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3

Conversation

@kou

@koukou commented Jul 18, 2023

Copy link
Copy Markdown
Member

Rationale for this change

Cython 3.0.0 is the latest release. PyArrow should work with Cython 3.0.0.

What changes are included in this PR?

Are these changes tested?

Yes.

Are there any user-facing changes?

Yes.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #36730has been automatically assigned in GitHub to PR creator.

@kou
kou marked this pull request as ready for review July 18, 2023 09:31
@pitrou

Copy link
Copy Markdown
Member

This may fix the compilation error but there are other issues during tests (see macOS CI?).

@kou

kou commented Jul 18, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed CI failures.

@jorisvandenbossche

jorisvandenbossche commented Jul 19, 2023

Copy link
Copy Markdown
Member

@kou there were also some runtime errors in the minimal build that are caused by cython 3 (but it's strange that this is only failing in a single build). Based on your diff, I don't think that will already be fixed here, but let me run them to be sure.

@jorisvandenbossche

Copy link
Copy Markdown
Member

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: dba6bb4c1adcb233aabce3d595706b5fc104b660

Submitted crossbow builds: ursacomputing/crossbow @ actions-f3bbf75ac8

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@pitrou

Copy link
Copy Markdown
Member

Can this PR also undo the pinning on various Python builds?

@apacheapache deleted a comment from github-actionsBotJul 19, 2023
@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: 81493b1fa6e3db21630c29ccad0e92499a2a43ff

Submitted crossbow builds: ursacomputing/crossbow @ actions-492c6d5c7d

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed the generator related problem.
I'll rebase on main and unpin Cython version.

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

Hmm. Can we detect Cython version in .{pyx,pxi}?

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

I want to write something like the following:

diff --git a/python/pyarrow/scalar.pxi b/python/pyarrow/scalar.pxi
index f438c8847..61de38203 100644
--- a/python/pyarrow/scalar.pxi+++ b/python/pyarrow/scalar.pxi@@ -793,7 +793,10 @@ cdef class MapScalar(ListScalar):
"""
arr = self.values
if array is None:
- raise StopIteration+ if Cython.__version__ < '3.0.0':+ raise StopIteration+ else:+ return
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

@pitrou

Copy link
Copy Markdown
Member

There should not be any need to raise StopIteration.

Comment threadpython/pyarrow/ipc.pxi Outdated
Comment on lines +438 to +444
def __iter__(self):
while True:
yield self.read_next_message()
try:
yield self.read_next_message()
except StopIteration:
# For Cython >= 3.0.0
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know if it is this code that gives problems to be written in a way that works for both cython 0.29 and 3, but a potential different way of writing it:

def __iter__(self):
return self
def __next__(self):
return self.read_next_message()

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I'll try it.

@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Jul 20, 2023
if arr is None:
raise StopIteration
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you actually test these changes before pushing them?

You can't use yield in a __next__ function.
Either you write __iter__ as a generator (using yield), or you write a pair of __iter__ and __next__ functions (without yield). You can't mix the two styles.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And FWIW, for this case, I would leave the __iter__ as is (in the other cases such as RecordBatchReader, we already have a public "next" method that can just be called from __next__)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Sorry. I didn't test on local before I pushed a commit because I don't have enough time yesterday.

I reverted the __iter__ + __next__ change.

@lidavidmlidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Flight changes LGTM, thanks!

@github-actionsgithub-actionsBot added awaiting merge Awaiting merge and removed awaiting changes Awaiting changes labels Jul 20, 2023
@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels Jul 20, 2023
@github-actionsgithub-actionsBot added Component: Documentation awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jul 20, 2023
@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

@jorisvandenbossche Do you have any idea why the following failure was happen?

https://github.com/apache/arrow/actions/runs/5615711782/job/15216554355?pr=36745#step:6:6074

 =================================== FAILURES ===================================
_______________________ test_cloudpickle_dataset[False] ________________________
tempdir = PosixPath('/tmp/pytest-of-root/pytest-0/test_cloudpickle_dataset_False0')
datadir = PosixPath('/opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/data/parquet')
use_legacy_dataset = False
@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
> _assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1572: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1540: in _assert_dataset_is_picklable
assert is_pickleable(dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1538: in is_pickleable
return obj == pickler.loads(pickler.dumps(obj))
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:73: in dumps
cp.dump(obj)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <cloudpickle.cloudpickle_fast.CloudPickler object at 0x7f25aa27aa10>
obj = <pyarrow.parquet.core._ParquetDatasetV2 object at 0x7f25a9ec9690>
def dump(self, obj):
try:
> return Pickler.dump(self, obj)
E _pickle.PicklingError: Can't pickle <cyfunction ParquetFragmentScanOptions._reconstruct at 0x7f2660177140>: it's not the same object as pyarrow._dataset_parquet.ParquetFragmentScanOptions._reconstruct
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:632: PicklingError

@jorisvandenbossche

Copy link
Copy Markdown
Member

Not directly an idea. We use the same pattern in many other places. Can you try this patch:

--- a/python/pyarrow/_dataset_parquet.pyx+++ b/python/pyarrow/_dataset_parquet.pyx@@ -741,7 +741,7 @@ cdef class ParquetFragmentScanOptions(FragmentScanOptions):
thrift_string_size_limit=self.thrift_string_size_limit,
thrift_container_size_limit=self.thrift_container_size_limit,
)
- return type(self)._reconstruct, (kwargs,)+ return ParquetFragmentScanOptions._reconstruct, (kwargs,)

(in theory it shouldn't matter for python, but maybe cython 3 has a bug that treats this different)

@kou

kou commented Jul 21, 2023

Copy link
Copy Markdown
MemberAuthor

Thanks! I've pushed your patch.

@h-vetinari

Copy link
Copy Markdown
Contributor

If there are problems with compatibility between 0.29 and 3.0 (aside from the few intentional breaking changes), the Cython devs are usually quick to respond if you open an issue

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

The failing pickle test is only when using the cloudpickle module instead of the pickle5/pickle module. Perhaps they don't support cython3.0.0 yet? This is the only test in the entire codebase that tests cloudpickle.. not sure how important it is as a dependency to pyarrow.

@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
_assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)

@pitrou

Copy link
Copy Markdown
Member

Well, first, this PR should be rebased, because there are conflicts.

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

I did rebase/squash to test things out here: #37097

I wanted to experiment without polluting this PR. I can merge any fixes I find back into this PR.

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

Can we use #37097 instead of this?

@danepitkin

Copy link
Copy Markdown
Member

Can we use #37097 instead of this?

Sure!

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

I close this in favor of #37097.

@koukou closed this Aug 11, 2023
@kou
kou deleted the python-cython-3 branch April 3, 2026 00:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI][Python] Cython 3.0 seems to make our build of pyarrow fail

6 participants

@kou@pitrou@jorisvandenbossche@h-vetinari@danepitkin@lidavidm
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

GH-36730: [Python] Add support for Cython 3.0.0 - #36745

Closed
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3
Closed

GH-36730: [Python] Add support for Cython 3.0.0#36745
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3

Conversation

@kou

@koukou commented Jul 18, 2023

Copy link
Copy Markdown
Member

Rationale for this change

Cython 3.0.0 is the latest release. PyArrow should work with Cython 3.0.0.

What changes are included in this PR?

Are these changes tested?

Yes.

Are there any user-facing changes?

Yes.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #36730has been automatically assigned in GitHub to PR creator.

@kou
kou marked this pull request as ready for review July 18, 2023 09:31
@pitrou

Copy link
Copy Markdown
Member

This may fix the compilation error but there are other issues during tests (see macOS CI?).

@kou

kou commented Jul 18, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed CI failures.

@jorisvandenbossche

jorisvandenbossche commented Jul 19, 2023

Copy link
Copy Markdown
Member

@kou there were also some runtime errors in the minimal build that are caused by cython 3 (but it's strange that this is only failing in a single build). Based on your diff, I don't think that will already be fixed here, but let me run them to be sure.

@jorisvandenbossche

Copy link
Copy Markdown
Member

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: dba6bb4c1adcb233aabce3d595706b5fc104b660

Submitted crossbow builds: ursacomputing/crossbow @ actions-f3bbf75ac8

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@pitrou

Copy link
Copy Markdown
Member

Can this PR also undo the pinning on various Python builds?

@apacheapache deleted a comment from github-actionsBotJul 19, 2023
@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: 81493b1fa6e3db21630c29ccad0e92499a2a43ff

Submitted crossbow builds: ursacomputing/crossbow @ actions-492c6d5c7d

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed the generator related problem.
I'll rebase on main and unpin Cython version.

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

Hmm. Can we detect Cython version in .{pyx,pxi}?

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

I want to write something like the following:

diff --git a/python/pyarrow/scalar.pxi b/python/pyarrow/scalar.pxi
index f438c8847..61de38203 100644
--- a/python/pyarrow/scalar.pxi+++ b/python/pyarrow/scalar.pxi@@ -793,7 +793,10 @@ cdef class MapScalar(ListScalar):
"""
arr = self.values
if array is None:
- raise StopIteration+ if Cython.__version__ < '3.0.0':+ raise StopIteration+ else:+ return
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

@pitrou

Copy link
Copy Markdown
Member

There should not be any need to raise StopIteration.

Comment threadpython/pyarrow/ipc.pxi Outdated
Comment on lines +438 to +444
def __iter__(self):
while True:
yield self.read_next_message()
try:
yield self.read_next_message()
except StopIteration:
# For Cython >= 3.0.0
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know if it is this code that gives problems to be written in a way that works for both cython 0.29 and 3, but a potential different way of writing it:

def __iter__(self):
return self
def __next__(self):
return self.read_next_message()

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I'll try it.

@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Jul 20, 2023
if arr is None:
raise StopIteration
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you actually test these changes before pushing them?

You can't use yield in a __next__ function.
Either you write __iter__ as a generator (using yield), or you write a pair of __iter__ and __next__ functions (without yield). You can't mix the two styles.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And FWIW, for this case, I would leave the __iter__ as is (in the other cases such as RecordBatchReader, we already have a public "next" method that can just be called from __next__)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Sorry. I didn't test on local before I pushed a commit because I don't have enough time yesterday.

I reverted the __iter__ + __next__ change.

@lidavidmlidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Flight changes LGTM, thanks!

@github-actionsgithub-actionsBot added awaiting merge Awaiting merge and removed awaiting changes Awaiting changes labels Jul 20, 2023
@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels Jul 20, 2023
@github-actionsgithub-actionsBot added Component: Documentation awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jul 20, 2023
@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

@jorisvandenbossche Do you have any idea why the following failure was happen?

https://github.com/apache/arrow/actions/runs/5615711782/job/15216554355?pr=36745#step:6:6074

 =================================== FAILURES ===================================
_______________________ test_cloudpickle_dataset[False] ________________________
tempdir = PosixPath('/tmp/pytest-of-root/pytest-0/test_cloudpickle_dataset_False0')
datadir = PosixPath('/opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/data/parquet')
use_legacy_dataset = False
@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
> _assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1572: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1540: in _assert_dataset_is_picklable
assert is_pickleable(dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1538: in is_pickleable
return obj == pickler.loads(pickler.dumps(obj))
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:73: in dumps
cp.dump(obj)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <cloudpickle.cloudpickle_fast.CloudPickler object at 0x7f25aa27aa10>
obj = <pyarrow.parquet.core._ParquetDatasetV2 object at 0x7f25a9ec9690>
def dump(self, obj):
try:
> return Pickler.dump(self, obj)
E _pickle.PicklingError: Can't pickle <cyfunction ParquetFragmentScanOptions._reconstruct at 0x7f2660177140>: it's not the same object as pyarrow._dataset_parquet.ParquetFragmentScanOptions._reconstruct
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:632: PicklingError

@jorisvandenbossche

Copy link
Copy Markdown
Member

Not directly an idea. We use the same pattern in many other places. Can you try this patch:

--- a/python/pyarrow/_dataset_parquet.pyx+++ b/python/pyarrow/_dataset_parquet.pyx@@ -741,7 +741,7 @@ cdef class ParquetFragmentScanOptions(FragmentScanOptions):
thrift_string_size_limit=self.thrift_string_size_limit,
thrift_container_size_limit=self.thrift_container_size_limit,
)
- return type(self)._reconstruct, (kwargs,)+ return ParquetFragmentScanOptions._reconstruct, (kwargs,)

(in theory it shouldn't matter for python, but maybe cython 3 has a bug that treats this different)

@kou

kou commented Jul 21, 2023

Copy link
Copy Markdown
MemberAuthor

Thanks! I've pushed your patch.

@h-vetinari

Copy link
Copy Markdown
Contributor

If there are problems with compatibility between 0.29 and 3.0 (aside from the few intentional breaking changes), the Cython devs are usually quick to respond if you open an issue

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

The failing pickle test is only when using the cloudpickle module instead of the pickle5/pickle module. Perhaps they don't support cython3.0.0 yet? This is the only test in the entire codebase that tests cloudpickle.. not sure how important it is as a dependency to pyarrow.

@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
_assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)

@pitrou

Copy link
Copy Markdown
Member

Well, first, this PR should be rebased, because there are conflicts.

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

I did rebase/squash to test things out here: #37097

I wanted to experiment without polluting this PR. I can merge any fixes I find back into this PR.

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

Can we use #37097 instead of this?

@danepitkin

Copy link
Copy Markdown
Member

Can we use #37097 instead of this?

Sure!

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

I close this in favor of #37097.

@koukou closed this Aug 11, 2023
@kou
kou deleted the python-cython-3 branch April 3, 2026 00:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI][Python] Cython 3.0 seems to make our build of pyarrow fail

6 participants

@kou@pitrou@jorisvandenbossche@h-vetinari@danepitkin@lidavidm
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

GH-36730: [Python] Add support for Cython 3.0.0 - #36745

Closed
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3
Closed

GH-36730: [Python] Add support for Cython 3.0.0#36745
kou wants to merge 12 commits into
apache:mainfrom
kou:python-cython-3

Conversation

@kou

@koukou commented Jul 18, 2023

Copy link
Copy Markdown
Member

Rationale for this change

Cython 3.0.0 is the latest release. PyArrow should work with Cython 3.0.0.

What changes are included in this PR?

Are these changes tested?

Yes.

Are there any user-facing changes?

Yes.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #36730has been automatically assigned in GitHub to PR creator.

@kou
kou marked this pull request as ready for review July 18, 2023 09:31
@pitrou

Copy link
Copy Markdown
Member

This may fix the compilation error but there are other issues during tests (see macOS CI?).

@kou

kou commented Jul 18, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed CI failures.

@jorisvandenbossche

jorisvandenbossche commented Jul 19, 2023

Copy link
Copy Markdown
Member

@kou there were also some runtime errors in the minimal build that are caused by cython 3 (but it's strange that this is only failing in a single build). Based on your diff, I don't think that will already be fixed here, but let me run them to be sure.

@jorisvandenbossche

Copy link
Copy Markdown
Member

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: dba6bb4c1adcb233aabce3d595706b5fc104b660

Submitted crossbow builds: ursacomputing/crossbow @ actions-f3bbf75ac8

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@pitrou

Copy link
Copy Markdown
Member

Can this PR also undo the pinning on various Python builds?

@apacheapache deleted a comment from github-actionsBotJul 19, 2023
@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

@github-actions crossbow submit example-python-minimal-build-fedora-conda

@github-actions

Copy link
Copy Markdown

Revision: 81493b1fa6e3db21630c29ccad0e92499a2a43ff

Submitted crossbow builds: ursacomputing/crossbow @ actions-492c6d5c7d

TaskStatus
example-python-minimal-build-fedora-condaGithub Actions

@kou

kou commented Jul 19, 2023

Copy link
Copy Markdown
MemberAuthor

I've fixed the generator related problem.
I'll rebase on main and unpin Cython version.

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

Hmm. Can we detect Cython version in .{pyx,pxi}?

@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

I want to write something like the following:

diff --git a/python/pyarrow/scalar.pxi b/python/pyarrow/scalar.pxi
index f438c8847..61de38203 100644
--- a/python/pyarrow/scalar.pxi+++ b/python/pyarrow/scalar.pxi@@ -793,7 +793,10 @@ cdef class MapScalar(ListScalar):
"""
arr = self.values
if array is None:
- raise StopIteration+ if Cython.__version__ < '3.0.0':+ raise StopIteration+ else:+ return
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

@pitrou

Copy link
Copy Markdown
Member

There should not be any need to raise StopIteration.

Comment threadpython/pyarrow/ipc.pxi Outdated
Comment on lines +438 to +444
def __iter__(self):
while True:
yield self.read_next_message()
try:
yield self.read_next_message()
except StopIteration:
# For Cython >= 3.0.0
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't know if it is this code that gives problems to be written in a way that works for both cython 0.29 and 3, but a potential different way of writing it:

def __iter__(self):
return self
def __next__(self):
return self.read_next_message()

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I'll try it.

@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting change review Awaiting change review labels Jul 20, 2023
if arr is None:
raise StopIteration
for k, v in zip(arr.field('key'), arr.field('value')):
yield (k.as_py(), v.as_py())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you actually test these changes before pushing them?

You can't use yield in a __next__ function.
Either you write __iter__ as a generator (using yield), or you write a pair of __iter__ and __next__ functions (without yield). You can't mix the two styles.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And FWIW, for this case, I would leave the __iter__ as is (in the other cases such as RecordBatchReader, we already have a public "next" method that can just be called from __next__)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Sorry. I didn't test on local before I pushed a commit because I don't have enough time yesterday.

I reverted the __iter__ + __next__ change.

@lidavidmlidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Flight changes LGTM, thanks!

@github-actionsgithub-actionsBot added awaiting merge Awaiting merge and removed awaiting changes Awaiting changes labels Jul 20, 2023
@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting merge Awaiting merge labels Jul 20, 2023
@github-actionsgithub-actionsBot added Component: Documentation awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jul 20, 2023
@kou

kou commented Jul 20, 2023

Copy link
Copy Markdown
MemberAuthor

@jorisvandenbossche Do you have any idea why the following failure was happen?

https://github.com/apache/arrow/actions/runs/5615711782/job/15216554355?pr=36745#step:6:6074

 =================================== FAILURES ===================================
_______________________ test_cloudpickle_dataset[False] ________________________
tempdir = PosixPath('/tmp/pytest-of-root/pytest-0/test_cloudpickle_dataset_False0')
datadir = PosixPath('/opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/data/parquet')
use_legacy_dataset = False
@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
> _assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1572: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1540: in _assert_dataset_is_picklable
assert is_pickleable(dataset)
opt/conda/envs/arrow/lib/python3.8/site-packages/pyarrow/tests/parquet/test_dataset.py:1538: in is_pickleable
return obj == pickler.loads(pickler.dumps(obj))
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:73: in dumps
cp.dump(obj)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <cloudpickle.cloudpickle_fast.CloudPickler object at 0x7f25aa27aa10>
obj = <pyarrow.parquet.core._ParquetDatasetV2 object at 0x7f25a9ec9690>
def dump(self, obj):
try:
> return Pickler.dump(self, obj)
E _pickle.PicklingError: Can't pickle <cyfunction ParquetFragmentScanOptions._reconstruct at 0x7f2660177140>: it's not the same object as pyarrow._dataset_parquet.ParquetFragmentScanOptions._reconstruct
opt/conda/envs/arrow/lib/python3.8/site-packages/cloudpickle/cloudpickle_fast.py:632: PicklingError

@jorisvandenbossche

Copy link
Copy Markdown
Member

Not directly an idea. We use the same pattern in many other places. Can you try this patch:

--- a/python/pyarrow/_dataset_parquet.pyx+++ b/python/pyarrow/_dataset_parquet.pyx@@ -741,7 +741,7 @@ cdef class ParquetFragmentScanOptions(FragmentScanOptions):
thrift_string_size_limit=self.thrift_string_size_limit,
thrift_container_size_limit=self.thrift_container_size_limit,
)
- return type(self)._reconstruct, (kwargs,)+ return ParquetFragmentScanOptions._reconstruct, (kwargs,)

(in theory it shouldn't matter for python, but maybe cython 3 has a bug that treats this different)

@kou

kou commented Jul 21, 2023

Copy link
Copy Markdown
MemberAuthor

Thanks! I've pushed your patch.

@h-vetinari

Copy link
Copy Markdown
Contributor

If there are problems with compatibility between 0.29 and 3.0 (aside from the few intentional breaking changes), the Cython devs are usually quick to respond if you open an issue

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

The failing pickle test is only when using the cloudpickle module instead of the pickle5/pickle module. Perhaps they don't support cython3.0.0 yet? This is the only test in the entire codebase that tests cloudpickle.. not sure how important it is as a dependency to pyarrow.

@pytest.mark.pandas
@parametrize_legacy_dataset
def test_cloudpickle_dataset(tempdir, datadir, use_legacy_dataset):
cp = pytest.importorskip('cloudpickle')
dataset = _make_dataset_for_pickling(tempdir, use_legacy_dataset)
_assert_dataset_is_picklable(
dataset, pickler=cp, use_legacy_dataset=use_legacy_dataset)

@pitrou

Copy link
Copy Markdown
Member

Well, first, this PR should be rebased, because there are conflicts.

@danepitkin

danepitkin commented Aug 10, 2023

Copy link
Copy Markdown
Member

I did rebase/squash to test things out here: #37097

I wanted to experiment without polluting this PR. I can merge any fixes I find back into this PR.

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

Can we use #37097 instead of this?

@danepitkin

Copy link
Copy Markdown
Member

Can we use #37097 instead of this?

Sure!

@kou

kou commented Aug 11, 2023

Copy link
Copy Markdown
MemberAuthor

I close this in favor of #37097.

@koukou closed this Aug 11, 2023
@kou
kou deleted the python-cython-3 branch April 3, 2026 00:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI][Python] Cython 3.0 seems to make our build of pyarrow fail

6 participants

@kou@pitrou@jorisvandenbossche@h-vetinari@danepitkin@lidavidm