How to Add Support for a New Library¶
This page is the checklist to add support for a new optional library (a "backend", such as
NumPy, PyTorch or pandas) to
coola. A backend is supported by several packages, each with its own
registry, and it is easy to add the equality support and forget the others.
To teach coola about one of your own classes, without changing coola, see
How to Add Support for a New Type instead.
In this page, <pkg> is the name of the library, e.g. pandas.
1. Declare the optional dependency¶
- Add the extra to
[project.optional-dependencies]ofpyproject.toml, e.g.<pkg> = ["<pkg>>=1.0"]. Theallextra, the CI jobs that test each dependency with its supported versions, anddev/config/package_versions.json(updated by a bot) follow from it. - Create
src/coola/utils/imports/<pkg>.py, copied frompandas.py. It definescheck_<pkg>,is_<pkg>_available,<pkg>_availableandraise_<pkg>_missing_error. Decorateis_<pkg>_availablewithavailability_cache(not withfunctools.cache), so thatclear_availability_cachesknows about it. Export the four names insrc/coola/utils/imports/__init__.py. - Create
src/coola/utils/fallback/<pkg>.py, copied frompandas.py: a fake module with fake classes that raiseMissingPackageError, used when the library is not installed. It must have every attribute of the library that is used in an annotation or aclass X(Base[pkg.Type])statement, because these are evaluated when the module is imported. - Add the marks for the tests to
src/coola/testing/fixtures.py, and the two names to__all__:
<pkg>_available, <pkg>_not_available = requires(is_<pkg>_available(), "<pkg>")
2. Equality¶
- Create
src/coola/equality/handler/<pkg>.pywith the handler that compares two objects (followpandas.pyornumpy.py). It must honorconfig.equal_nan,config.atolandconfig.rtolwhen the library supports them, and report the difference withreport_differencewhenconfig.show_differenceisTrue. Export it inequality/handler/__init__.py. - Create
src/coola/equality/tester/<pkg>.py. A tester is aBaseChainEqualityTesterthat implements_create_handler(the chain, usuallySameObjectHandler,SameTypeHandler, some checks such as the dtype or the shape, and the handler of step 1) and, for an optional library,_check_dependencies. Export it inequality/tester/__init__.py. - Register the tester in
equality/tester/interface.py: add a_get_<pkg>_equality_testersfunction, guarded byis_<pkg>_available(), and call it in_register_default_equality_testers. - Document the behavior of the library in the table "Behavior by type".
3. The other packages¶
Decide for each package whether the library needs an entry, and write the decision down in the pull request.
| Package | What to do | Default |
|---|---|---|
coola.summary |
Add a BaseMetadataSummarizer in summary/<pkg>.py that describes the metadata (shape, dtype, columns) in _describe, export it, and register it in summary/interface.py (_get_<pkg>_summarizers). |
Without it, the summary is the str of the object, which can be very long. |
coola.hashing |
Nothing by default: there is no canonical byte form for arrays and data frames. Document how to register a hasher with register_hashers. |
The type is not hashable. |
coola.recursive |
Nothing: the objects of the library are leaves, passed to the function. | Leaf. |
coola.iterator |
Nothing: the objects are leaves, and are not expanded. | Leaf. |
coola.random |
If the library has a global random number generator, add a BaseRandomManager in random/<pkg>.py, and register it in random/interface.py. |
Not managed. |
coola.reducer |
If the library can compute statistics, add a BaseBasicReducer in reducer/<pkg>.py. Its results must agree with NativeReducer (see tests/unit/reducer/test_consistency.py). |
Not supported. |
4. Tests and documentation¶
- Write the unit tests next to the existing ones, with the mark of step 1
(
@<pkg>_available), and an import guard for the library as in the other test files. Test with and without the library: the CI runs the tests with the required dependencies only. - Every new public class and function must be in the
__all__of its module and of its package:tests/unit/test_public_api.pychecks it. - Check that importing
cooladoes not import the library: the imports of the library are guarded byis_<pkg>_available()and the fallback module. - Update the user guide pages of the packages you touched, and the "Supported Types" list of
docs/docs/uguide/equality.md.
Summary of the files¶
| Step | Files |
|---|---|
| Dependency | pyproject.toml, utils/imports/<pkg>.py, utils/imports/__init__.py, utils/fallback/<pkg>.py, testing/fixtures.py |
| Equality | equality/handler/<pkg>.py, equality/handler/__init__.py, equality/tester/<pkg>.py, equality/tester/__init__.py, equality/tester/interface.py |
| Summary | summary/<pkg>.py, summary/__init__.py, summary/interface.py |
| Others (optional) | random/<pkg>.py, random/interface.py, reducer/<pkg>.py |
| Tests and docs | tests/unit/..., docs/docs/uguide/*.md |