[ANN] Tables.jl 1.0 Release

Hello all,

A new 1.0 release was just registered in the General registry for the Tables.jl package.

The API has matured well over the last 1.5 years (since 2018 JuliaCon hackathon!), and we felt like it was time for an official 1.0 release. Highlights for 1.0 include:

  • A ton of new documentation, including walk-throughs of using the Tables.jl interface, implementing it, and even some tips on testing
  • Addition of Tables.Row and Tables.Columns convenience types for providing a ton of useful behaviors for objects returned from Tables.rows and Tables.columns, including iteration, indexing, property-access, and AbstractDict methods
  • Polish of Tables.jl API requirements: in particular, Tables.rows must now return any Tables.AbstractRow-compatible iterator, and Tables.columns must return a Tables.AbstractColumns-compatible object. The interfaces for both Tables.AbstractRow and Tables.AbstractColumns are synchronized for consistency, both just requiring Tables.getcolumn and Tables.columnnames to be implemented
  • The moving out of a few “table operations” to a new TableOperations.jl package, where this kind of functionality can incubate and evolve separately from the core Tables.jl APIs

In general, the changes should be relatively straightforward, so the upgrade guide is:

For source implementations:

  • If your table implemented Tables.rows, ensuring your row type implements the full Tables.AbstractRow interface, instead of just getproperty and propertynames; note that NamedTuples satisfy the interface by default (as they always have). For custom row types, you may consider subtyping Tables.AbstractRow to inherit a bunch of useful definitions (iteration, indexing, property-access, and AbstractDict methods)
  • If your table implements Tables.columns, ensuring the returned object satisfies the full Tables.AbstractColumns interface, instead of just getproperty and propertynames. For custom columns types, you may consider subtyping Tables.AbstractColumns to inherit the same kind of useful default behavior as Tables.AbstractRow
  • Depending on the nature of your table, you may consider implementing Tables.isrowtable to hook into some useful default definitions

For Tables.jl consumers (or sink functions):

  • Just note that by default, the “row” iterator returned by Tables.rows doesn’t require that the row be property-accessible anymore, but only requires that Tables.getcolumn and Tables.columnnames be defined.
  • You may consider using the new Tables.Row(row) wrapper struct that takes the new “minimal” Tables.jl row requirement, and wraps it in a struct that subtypes Tables.AbstractRow, meaning it makes any plain row useful by defining iteration, indexing, property-access, and AbstractDict methods. This allows any row to be treated w/ the same API you would use on a NamedTuple.
  • Note that Tables.eachcolumn used to allow passing varargs through the definition, but extra args should now be passed normally via closure; so the the old definition was Tables.eachcolumn(f, schema, row, args...) and now it’s just Tables.eachcolumn(f, schema, row)
  • There also used to be a definition for Tables.eachcolumn for columns objects (i.e. the result of calling Tables.columns(table)), but that’s been removed in favor of wrapping a columns object with Tables.Columns, which makes the object iterable, indexable, property-accessible, and support AbstractDict methods (similar to Tables.Row). So you can just replace Tables.eachcolumn(columns) with Tables.Columns(columns).
  • There’s a new, officially supported Tables.namedtupleiterator(table), in case that’s useful to anyone; it takes any Tables.jl input table source and will iterate full NamedTuple rows
  • AbstractDicts are now supported as “columns” objects (if they have a key type of Symbol, String, or Integer and a value type of <:AbstractVector), or as a “row” object; meaning a Vector{Dict} is a now a valid “table”

I think those are the major things to highlight; for more complete view of the package, interfaces, and APIs, check out the new docs, feel free to open an issue for anything confusing or concerning, or drop by the #data channel in the slack to ask questions or get some clarity. Also feel free to ping me (@quinnj) on any issues/pull requests and I’m happy to review and help people get some 1.0 goodness for their tables.

Happy tabling!