Skip to main content

A suite of tests for inspection of tabular data .

Project description

Data Curation Workflows

authors: Ellery Galvin
date: 2026-03-24
contact: ellery.galvin@colorado.edu, crdds@colorado.edu

Description

This project checks tabular datasets (.csv and .xlsx) for common curation issues.
Each test reports:

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

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

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

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_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

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

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.1.tar.gz (40.9 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.1-py3-none-any.whl (22.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for fairspreadsheets-0.0.1.tar.gz
Algorithm Hash digest
SHA256 7a582d16dccf64e58e60c9ec9a8805e199a1a66c88aa6e6bb494234e61f676e4
MD5 d9bbfc3b00db06b053d358fa467d2bbe
BLAKE2b-256 174793148c88c6d0a1e7969587697cb5052b71cb6fbd8c94ba702bdf90a9adf5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for fairspreadsheets-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3ccad1705327ddd7a55be002605e4fceea6d51377fc53ad96c692909ca5333fe
MD5 befe7679d6466e1eb9b0288f60679e76
BLAKE2b-256 3fce7b4457e5f2de9239e38dbeb74b3fc46f38ffccbcc13b65b727c8113fab9a

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