Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic Tables.istable support #285

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

alyst
Copy link

@alyst alyst commented Mar 22, 2025

At the moment QuartoNotebookRunner.jl supports ojs_define(df::DataFrame) via the extension that requires both DataFrames.jl and Tables.jl.
Actually, Tables.jl are not necessary to support DataFrames, one can just use eachrow(df) instead of Tables.rows(df).

This PR adds _has_trait(trait, obj)/_ojs_convert(trait, obj) mechanism, and adds Val(:table) trait that
enables ojs_convert(df) for all types that support Tables.table interface (dropping DataFrames dependency).
The Tables.jl support is moved into the QuartoNotebookRunner directly:

  • support for tabular data is critical for ObservableJS
  • isrowtable(df) istable(df) is the generic way to check if the type supports Tables.jl, it is not possible to do it via the _ojs_convert() argument type constraints
  • adding trivial extensions for each of numerous packages that support Tables.jl is not reasonable.

@MichaelHatherly
Copy link
Collaborator

Thanks for opening this @alyst, this will be a nice improvement.

Tables cannot be added to the [deps] since we need to only be using stdlibs as direct dependencies. That is a requirement that will not be changing. This'll need to be done via [weakdeps], which is doable for what you're wanting to achieve here.

@alyst alyst force-pushed the all_tables_support branch from d7c0254 to f7ec21b Compare March 22, 2025 19:07
Alexey Stukalov added 2 commits March 22, 2025 12:16
- implement the generic _has_trait(trait, obj), _obj_convert(trait, obj)
  mechanism for potential future extensions
- QuartoNotebookWorkerDataFramesTablesExt: drop DataFrames dependency
@alyst alyst force-pushed the all_tables_support branch from f7ec21b to e93c017 Compare March 22, 2025 19:17
@alyst
Copy link
Author

alyst commented Mar 22, 2025

I've updated the PR, I have also added some comments/docstrings to clarify the ojs_define/ojs_convert mechanism.

@alyst alyst changed the title Generic rowtable support Generic Tables.istable support Mar 22, 2025
should lower the memory footprint.
@alyst alyst force-pushed the all_tables_support branch from e93c017 to 981aa7e Compare March 22, 2025 20:24
Comment on lines 29 to 54
# Internal function to check if the object supports a specific trait.
# QuartoNotebookWorker extensions that implement specific traits
# should override this function.
# The fallback implementation reports no trait support.
_has_trait(trait::Val, obj::Any) = false

# Trait-specific object conversion that is called when the object
# supports a specific trait (_has_trait(trait, obj) == true).
# QuartoNotebookWorker extensions that implement specific traits
# should override this function.
# The fallback implementation returns the object unchanged.
_ojs_convert(trait::Val, obj::Any) = obj

# The default object conversion function that is called when
# there is no more specific _ojs_convert(obj::T)
function _ojs_convert(obj::Any)
# check if the object implements any of the traits supported by extensions
if _has_trait(Val(:table), obj)
# if QuartoNotebookWorkerTablesExt is active and
# obj supports Tables.istable(obj) interface, do table-specific conversion
return _ojs_convert(Val(:table), obj)
else
# no specific trait support, no conversion by default
return obj
end
end
Copy link
Collaborator

Choose a reason for hiding this comment

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

It really doesn't need to be a generic trait mechanism at the moment, just the simple dispatches outlined in #286 is sufficient and preferable from my point of view. Adding Val-based trait-like code is more complex that this needs to be.

Copy link
Author

Choose a reason for hiding this comment

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

I've replaced trait-based approach with the one you suggest.

I have to say, whether _is_rows/__is_rows(nothing)/_rows/__rows(nothing) is more simple/clean than _has_trait(trait)/_ojs_convert(trait) is a matter of personal taste -- we are discussing just 4 lines of code.
What is more important, I think, is to document how that works, which I have tried to do for the functions around OJS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants