Skip to main content

A suite of tests for inspection of tabular data.

Project description

Data Curation Workflows

authors: Ellery Galvin, Alexandra Provo
date updated: 2026-05-08
contact: ellery.galvin@colorado.edu, crdds@colorado.edu

Description

This project checks spreadsheet files (.csv, .tsv, and .xlsx) for common data curation issues.
Each test reports:

  • what failed,
  • where it failed, and
  • an example offending value.

Installation

pip install FAIRspreadsheets

Usage

import fair
suite = fair.Test_Suite("your_data.csv")
suite.run()
suite.report()
suite.save(format = "csv")

Call signatures

Test_Suite(wb_path, to_run=None, to_skip=None, config_path=None)

  • wb_path: path to the workbook

Which tests to run? Defaults to all. Else, specify one of

  • to_run: list of test names to run, lower case strings as below
  • to_skip: list of test names to skip, lower case strings as below

Extra arguments to replace defaults for tests (see below):

  • config_path: path to the config file, replaces defaults where specified

Test_Suite methods:

  • run(): runs the tests
  • report(): prints the results to the console
  • save(format = "json"): saves the results to a JSON file
  • save(format = "csv"): saves the results to a CSV file

Tests Implemented

File-level tests

  • file_name_length: filename length is within allowed bounds
  • file_name_whitespace: filename contains no whitespace
  • file_name_final: filename does not include the word final
  • file_name_word_separation: filename does not mix camelCase, underscores, and dashes
  • file_name_special_characters: filename has no disallowed special characters
  • file_encoding: text files decode cleanly in the configured encoding
  • file_delimiter: delimiter in .csv or .tsv file matches the extension

Sheet-level tests

  • sheet_empty: worksheet is not empty
  • sheet_name: sheet name contains no whitespace or disallowed special characters
  • sheet_upper_left_corner: table begins at upper-left (no leading blank rows/columns)
  • sheet_multi_table: sheet does not appear to contain multiple separate tables

Header-level tests

  • header_duplicates: duplicate header names are flagged
  • header_id: first header should not be exactly ID
  • header_length: header length is within allowed bounds
  • header_first_char: headers should not start with digits
  • header_space: headers should not contain spaces
  • header_untrimmed_white_space: leading/trailing whitespace in headers is flagged
  • header_word_separation: headers should not mix camelCase, underscores, and dashes
  • header_special_characters: headers should not contain disallowed special characters
  • header_date: date-like header names (for combined date fields) are flagged
  • header_mixed_datatypes: columns with mixed numeric/text values are flagged

Cell-level tests

  • cell_aggregate_row: aggregate-like summary row at bottom (e.g., total/sum) is flagged
  • cell_special_characters: disallowed special characters in cells are flagged
  • cell_untrimmed_white_space: leading/trailing whitespace is flagged
  • cell_newlines_tabs: tabs/newlines/vertical tabs in cells are flagged
  • cell_missing_value_text: text placeholders for missing values (NA, null, -, etc.) are flagged
  • cell_question_mark_only: cells equal to ? are flagged
  • cell_white_space_only: whitespace-only cells are flagged
  • cell_number_space: cells containing only digits+spaces are flagged
  • cell_dates: dates not matching required format are flagged
  • cell_scientific_notation: scientific notation in text cells is flagged
  • cell_units: values that combine number+unit in one cell (e.g., 10kg) are flagged

Options Configuration

Options are set in a JSON config file (see config.example.json).

Important conventions:

  • Top-level key = lower-case class name (for example cell_dates)
  • Option names = keyword-only __init__ args for that test
  • Only the tests and options below are accepted

File-level options

  • file_name_length
    • min_length (int, default 5): minimum allowed filename length
    • max_length (int, default 32): maximum allowed filename length
  • file_name_special_characters
    • special_char_pattern (regex string, default [!@#$%^&*()+=\[\]{};:'"|\\,<>\?/]): disallowed characters
  • file_encoding
    • valid_encoding (string, default utf-8): expected text encoding for CSV-like files
  • file_delimiter
    • valid_delimiter_pairs (list of tuples, default [(",",".csv"),("\t",".tsv")]): expected pairings of delimiters and file extensions. Note: currently not possible to configure this in a JSON config file since JSON does not allow tuples

Sheet-level options

  • sheet_name
    • special_char_pattern (regex string, default [!@#$%^&*()+=\[\]{};:'"|\\,<>\?/]): disallowed characters

Header-level options

  • header_length
    • min_length (int, default 1): minimum header length
    • max_length (int, default 24): maximum header length
  • header_special_characters
    • special_char_pattern (regex string, default [!@#$%^&*()+=\[\]{};:'"|\\,<>\?/]): disallowed characters
  • header_date
    • date_keywords (list of strings, default ["date", "datetime", "timestamp"]): keywords used to detect date-like headers

Cell-level options

  • cell_aggregate_row
    • aggregate_words (list of strings, default ["total","sum","average","count","min","max"]): terms used to detect summary rows
  • cell_special_characters
    • default_pattern (regex string): disallowed chars for normal columns
    • url_pattern (regex string, default ^https?://): validation pattern for URL columns
    • free_text_pattern (regex string): disallowed chars for free-text columns
    • url_columns (list of strings, default []): columns validated with url_pattern
    • free_text_columns (list of strings, default []): columns validated with free_text_pattern
    • skip_columns (list of strings, default []): columns skipped by this test
  • cell_dates
    • date_columns (list of strings, default []): explicit date columns
    • auto_detect_columns (bool, default false): infer likely date columns automatically
    • format_code (string, default %Y/%m/%d): required datetime.strptime date format
    • date_column_threshold (float 0..1, default 0.8): fraction of parseable values needed to auto-mark a column as date-like
  • cell_units
    • unit_abbreviations (list of strings): unit suffixes used to detect values like 12kg

Tests without options should be configured with an empty object or omitted.

Output Specification

Only failed (or not-completed) tests appear in saved output. Passing tests are omitted.

JSON output (results/<input_base>_<YYYY-MM-DD_HH-MM-SS>.json)

  • Root object: keys are sheet names, plus file for file-level failures
  • Value per sheet: object keyed by test name
  • Value per test:
    • message: failure/not-completed message
    • issues: object of location -> example
  • For JSON compatibility, non-string issue keys (such as tuple coordinates) are stringified.

CSV output (results/<input_base>_<YYYY-MM-DD_HH-MM-SS>.csv)

Columns are exactly:

  • path: input workbook path
  • sheet: sheet name (file for file-level tests)
  • test_name: lower-case test class name
  • message: failure/not-completed message
  • location: issue key (string form)
  • example: issue value

Each row corresponds to one issue entry from one failed test.

For Developers

Directory contents

  • .gitignore excludes the data directory from version control, and other files
  • config.example.json is an example configuration for test options
  • demo.xlsx is a file on which to test detectors.py
  • detectors.py is the main module that implements a series of automated tests for data curation workflows
  • pyproject.toml is the specification for the PyPI package
  • LICENSE contains the licensing information for this software

Architecture overview

  • Test_Suite discovers concrete tests automatically from subclasses of Test
  • Tests are grouped by level using class name prefixes: file_, sheet_, header_, cell_
  • Dependencies are declared via Has_Dependency; the suite executes tests in dependency-safe order
  • Each test writes failures into self.issues, then calls Test.validate(...) to set status/message
  • trimmed_results() filters outputs to failed/not-completed tests only

How to add a new test safely

  1. Choose the right base class:
    • file checks: inherit File
    • sheet checks: inherit Sheet
    • header checks: inherit Header
    • cell checks: inherit Cell
  2. Name the class with underscores (example Cell_My_New_Check).
    The runtime test key becomes lower-case class name (cell_my_new_check).
  3. Put user-configurable settings in keyword-only args:
    • use def __init__(self, *, ...)
    • validate types/ranges in __init__
  4. Implement validate(...) and populate self.issues as:
    • key: location (header name, tuple coordinate, filename, etc.)
    • value: offending example/value
  5. End validation with Test.validate(self, fail_message, pass_message) so status/message are consistent.
  6. If your test depends on another test, add Has_Dependency.__init__(self, DependencyClass) and use dependency outputs in validate.
  7. Add documentation:
    • include the new test in the test list above
    • add config options under the correct section (if any)
    • update config.example.json with sensible defaults

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fairspreadsheets-0.0.5.tar.gz (51.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fairspreadsheets-0.0.5-py3-none-any.whl (23.8 kB view details)

Uploaded Python 3

File details

Details for the file fairspreadsheets-0.0.5.tar.gz.

File metadata

  • Download URL: fairspreadsheets-0.0.5.tar.gz
  • Upload date:
  • Size: 51.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.32.3

File hashes

Hashes for fairspreadsheets-0.0.5.tar.gz
Algorithm Hash digest
SHA256 c43d56803b4517a9243b0e85a63d80a490450fceafc5c273a27e8b78435d1238
MD5 3b5d7c82518375bed477de1560b06430
BLAKE2b-256 1b5eeced85a7e342e068a49cd74d9db83bed884129ae1aabae2e58ab12877ef7

See more details on using hashes here.

File details

Details for the file fairspreadsheets-0.0.5-py3-none-any.whl.

File metadata

File hashes

Hashes for fairspreadsheets-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 5596441f239c14ac86b5ddac000b6cc5ccdc07d5f266f3e8f589cb26646a5889
MD5 88da4595efac730919df5f6a4a59993b
BLAKE2b-256 576b3859a537046de4277b2e251747339ff1920a2265952646ea444fad3c8e70

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page