Skip to content

[SPARK-47909][PYTHON][CONNECT] Parent DataFrame class for Spark Connect and Spark Classic - #46129

Closed
HyukjinKwon wants to merge 1 commit into
apache:masterfrom
HyukjinKwon:SPARK-47909
Closed

[SPARK-47909][PYTHON][CONNECT] Parent DataFrame class for Spark Connect and Spark Classic#46129
HyukjinKwon wants to merge 1 commit into
apache:masterfrom
HyukjinKwon:SPARK-47909

Conversation

@HyukjinKwon

@HyukjinKwonHyukjinKwon commented Apr 19, 2024

Copy link
Copy Markdown
Member

What changes were proposed in this pull request?

This PR proposes to have a parent pyspark.sql.DataFrame class which pyspark.sql.connect.dataframe.DataFrame and pyspark.sql.classic.dataframe.DataFrame inherit.

Note that for backward compatibility concern, pyspark.sql.DataFrame(...) will return still a Spark Classic DataFrame.

Before

  1. pyspark.sql.DataFrame (Spark Claasic)

    • docstrings
    • Spark Classic logic
  2. pyspark.sql.connect.dataframe.DataFrame (Spark Connect)

    • Spark Connect logic
  3. Users can only see the type hints from pyspark.sql.DataFrame.

After

  1. pyspark.sql.DataFrame (Common)

    • docstrings
    • Support classmethod usages (dispatch to either Spark Connect or Spark Classic)
  2. pyspark.sql.classic.dataframe.DataFrame (Spark Classic)

    • Spark Classic logic
  3. pyspark.sql.connect.dataframe.DataFrame (Spark Connect)

    • Spark Connect logic
  4. Users can only see the type hints from pyspark.sql.DataFrame.

Why are the changes needed?

This fixes two issues in the current structure at Spark Connect:

Support usage of regular methods as class methods, e.g.,

frompyspark.sqlimportDataFramedf=spark.range(10)
DataFrame.union(df, df)

Before

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../spark/python/pyspark/sql/dataframe.py", line 4809, in union
return DataFrame(self._jdf.union(other._jdf), self.sparkSession)
^^^^^^^^^
File "/.../spark/python/pyspark/sql/connect/dataframe.py", line 1724, in __getattr__
raise PySparkAttributeError(
pyspark.errors.exceptions.base.PySparkAttributeError: [JVM_ATTRIBUTE_NOT_SUPPORTED] Attribute `_jdf` is not supported in Spark Connect as it depends on the JVM. If you need to use this attribute, do not use Spark Connect when creating your session. Visit https://spark.apache.org/docs/latest/sql-getting-started.html#starting-point-sparksession for creating regular Spark Session in detail.

After

DataFrame[id: bigint]

Supports isinstance call

frompyspark.sqlimportDataFrameisinstance(spark.range(1), DataFrame)

Before

False

After

True

Does this PR introduce any user-facing change?

Yes, as described above.

How was this patch tested?

Manually tested, and CI should verify them.

Was this patch authored or co-authored using generative AI tooling?

No.

@HyukjinKwon

Copy link
Copy Markdown
MemberAuthor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we can move such complex preprocessing to the superclasses later

Comment threadpython/pyspark/sql/classic/dataframe.py Outdated
Comment threadpython/pyspark/sql/connect/dataframe.py Outdated
@HyukjinKwon

Copy link
Copy Markdown
MemberAuthor

Will fix up the tests soon.

Comment threadpython/pyspark/sql/dataframe.py Outdated
Comment threadpython/pyspark/sql/utils.py Outdated

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 guess we can leave it as-is? And the following changes?

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.

this was the way MyPy least complained IIRC. Let me take a look again ..

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.

Seems like the arguments cannot be more specific type, and return types can't be wider types (https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides). So it complains about the argument.

Let me just keep them all as parent dataframe for simplicity because those types aren't user-facing anyway.

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.

Here is one example of the error:

python/pyspark/sql/classic/dataframe.py:276: error: Argument 1 of "exceptAll" is incompatible with supertype "DataFrame"; supertype defines the argument type as "DataFrame" [override]

Comment threadpython/pyspark/sql/connect/dataframe.py Outdated
Comment threadpython/pyspark/sql/classic/dataframe.py Outdated
Comment threadpython/pyspark/sql/classic/dataframe.py Outdated
Comment threadpython/pyspark/sql/classic/dataframe.py Outdated
Comment threadpython/pyspark/sql/classic/dataframe.py Outdated
Comment threadpython/pyspark/sql/classic/dataframe.py Outdated
Comment on lines 507 to 509

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'm wondering if we need @overload definitions in the subclasses?

@HyukjinKwonHyukjinKwonApr 20, 2024

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.

I initially added, and removed it back because MyPy complains too much. I will take another look.

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.

Seems like by right we should redefine the overloads here (python/mypy#5146, python/mypy#10699). However, we're using pyspark.sql.DataFrame type hints even within our codebase .. so I think it's better to don't have them defined here for now.

@HyukjinKwon

HyukjinKwon commented Apr 21, 2024

Copy link
Copy Markdown
MemberAuthor

Should be ready for a look. All tests passed. I squashed/rebased the commits.

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.

This might be a breaking change if somebody inherits pyspark.sql.DataFrame before, and it has it's own __init__. However, __init__ is not really an API, and users shouldn't really customize/use/invoke them directly.

@HyukjinKwon

Copy link
Copy Markdown
MemberAuthor

Merged to master.

I will followup if there are more comments to address.

@dongjoon-hyundongjoon-hyun 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.

Can we have a different name than classic?

@dongjoon-hyun

Copy link
Copy Markdown
Member

classic sounds like a too limited wording because it has no clear meaning and not-extensible in a long-term perspective.

HyukjinKwon added a commit that referenced this pull request Apr 23, 2024
…c` references
### What changes were proposed in this pull request?
This PR is a followup of #46129 that moves `pyspark.classic` references to the actual test methods so they are not references during `pyspark-connect` only test (that does not have `pyspark.classic` package).
### Why are the changes needed?
To recover the CI: https://github.com/apache/spark/actions/runs/8789489804/job/24119356874
### Does this PR introduce _any_ user-facing change?
No, test-only.
### How was this patch tested?
Manually
### Was this patch authored or co-authored using generative AI tooling?
No.
Closes#46171 from HyukjinKwon/SPARK-47909-followup.
Authored-by: Hyukjin Kwon <gurwls223@apache.org>
Signed-off-by: Hyukjin Kwon <gurwls223@apache.org>
HyukjinKwon added a commit that referenced this pull request Apr 23, 2024
… Classic
### What changes were proposed in this pull request?
Same as #46129 but for `Column` class.
### Why are the changes needed?
Same as #46129
### Does this PR introduce _any_ user-facing change?
Same as #46129
### How was this patch tested?
Manually tested, and CI should verify them.
### Was this patch authored or co-authored using generative AI tooling?
No.
Closes#46155 from HyukjinKwon/SPARK-47933.
Authored-by: Hyukjin Kwon <gurwls223@apache.org>
Signed-off-by: Hyukjin Kwon <gurwls223@apache.org>
ianmcook added a commit to ianmcook/spark that referenced this pull request May 9, 2024
HyukjinKwon pushed a commit that referenced this pull request Jun 3, 2024
…and Spark Classic
### What changes were proposed in this pull request?
Parent Window class for Spark Connect and Spark Classic
### Why are the changes needed?
Same as #46129
### Does this PR introduce _any_ user-facing change?
Same as #46129
### How was this patch tested?
CI
### Was this patch authored or co-authored using generative AI tooling?
NO
Closes#46841 from zhengruifeng/py_parent_window.
Authored-by: Ruifeng Zheng <ruifengz@apache.org>
Signed-off-by: Hyukjin Kwon <gurwls223@apache.org>
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.

4 participants

@HyukjinKwon@dongjoon-hyun@ueshin@zhengruifeng