Skip to main content

A data model linter

Project description


AstraLint

AstraLint is a Python linter for Space Physics data files, validating conformance to standards such as ISTP and PDS4.

๐Ÿš€ Try it online โ€” no installation required!

Overview

AstraLint validates data files against conformance suites using a codec-agnostic architecture:

  1. Codecs transform file formats (e.g., CDF) into a common abstract representation ( File)
  2. Suites define collections of validation rules (e.g., ISTP, PDS4)
  3. Rules check specific requirements, defined either in Python or YAML

Usage

# Lint a file against the default ISTP suite
astralint lint myfile.cdf

# Lint against a specific suite
astralint lint myfile.cdf --suite PDS4

# Select specific rules to run filtering by reference ID or name, regex supported
astralint lint myfile.cdf --suite ISTP --select "ISTP-MD-003" --select ".*GlobalAttributes"

# Ignore specific rules by reference ID or name, regex supported
astralint lint myfile.cdf --suite ISTP --ignore "ISTP-MD-00[0-9]" --ignore "MandatoryGlobalAttributes"

# List available suites
astralint list-suites

# Strict mode: exit with error on warnings too
astralint lint myfile.cdf --strict

AstraLint returns exit code 1 on validation errors (or warnings with --strict), making it suitable for CI/CD pipelines.

Configuration

AstraLint can be configured via pyproject.toml or .astralint.yaml. Configuration is loaded with the following precedence (highest to lowest):

  1. CLI arguments
  2. .astralint.yaml (project root)
  3. pyproject.toml [tool.astralint]
  4. Built-in defaults

Quick Start

# Generate a starter config file
astralint config init

# Validate your config file
astralint config validate

# Show resolved configuration (merged from all sources)
astralint config show

Example .astralint.yaml

suite: ISTP

select:
  - "MandatoryGlobalAttributes"
  - "ISTP-VAR-.*"

ignore:
  - "DeprecatedRule"

severity_overrides:
  ISTP-VAR-001: WARNING

extra_rules:
  - "./custom_rules/"

output:
  format: console
  verbose: false
  show_passed: true

Example pyproject.toml

[tool.astralint]
suite = "ISTP"
select = ["MandatoryGlobalAttributes"]

[tool.astralint.output]
format = "html"
verbose = true

๐Ÿ“– Full Configuration Reference โ†’

Architecture

flowchart TD
    subgraph Input["๐Ÿ“ฅ Input"]
        A[๐Ÿ“„ Data File]
    end
    
    subgraph Codecs["๐Ÿ”Œ Codecs (pluggable)"]
        B1[CDF Codec]
        B2[NetCDF Codec]
        B3[... more]
    end
    
    subgraph Core["โš™๏ธ Core"]
        C[๐Ÿ“ฆ Abstract File Model]
        D[๐Ÿ“‹ Conformance Suite]
        E[โœ… Rules & Assertions]
    end
    
    subgraph Suites["๐Ÿ“š Suites (pluggable)"]
        S1[ISTP]
        S2[PDS4]
        S3[... more]
    end
    
    subgraph Reports["๐Ÿ“Š Reports (pluggable)"]
        R1[Console]
        R2[JSON]
        R3[... more]
    end
    
    A --> B1 & B2 & B3
    B1 & B2 & B3 --> C
    C --> D
    S1 & S2 & S3 -.->|loads| D
    D --> E
    E --> R1 & R2 & R3
    
    style C fill:#fff3e0
    style Core fill:#f5f5f5,stroke:#999
    style Codecs fill:#e3f2fd,stroke:#1976d2
    style Suites fill:#fce4ec,stroke:#c2185b
    style Reports fill:#e8f5e9,stroke:#388e3c

File Model

The abstract File model is the core data structure that all codecs produce. Rules and assertions operate on this unified representation:

File
โ”œโ”€โ”€ compression: str                     # e.g., "gzip", "none"
โ”œโ”€โ”€ attributes: {name โ†’ Attribute}       # Global metadata
โ”‚   โ”œโ”€โ”€ "Project"      โ†’ Attribute
โ”‚   โ”œโ”€โ”€ "PI_name"      โ†’ Attribute
โ”‚   โ””โ”€โ”€ ...
โ””โ”€โ”€ variables: {name โ†’ Variable}         # Data variables
    โ”œโ”€โ”€ "Epoch" โ†’ Variable
    โ”‚   โ”œโ”€โ”€ name: str                    # "Epoch"
    โ”‚   โ”œโ”€โ”€ shape: [int]                 # e.g., [1440]
    โ”‚   โ”œโ”€โ”€ compression: str             # "gzip", "none"
    โ”‚   โ”œโ”€โ”€ data_type: DataType          # TT2000, FLOAT64, ...
    โ”‚   โ”œโ”€โ”€ record_variance: bool
    โ”‚   โ””โ”€โ”€ attributes: {name โ†’ Attribute}
    โ”‚       โ”œโ”€โ”€ "CATDESC"  โ†’ Attribute
    โ”‚       โ”œโ”€โ”€ "FILLVAL"  โ†’ Attribute
    โ”‚       โ””โ”€โ”€ ...
    โ”œโ”€โ”€ "Temperature" โ†’ Variable
    โ””โ”€โ”€ ...

Attribute
โ”œโ”€โ”€ name: str
โ”œโ”€โ”€ data_type: [DataType]                # List of data types
โ””โ”€โ”€ shape: [int]                         # Attribute dimensions

DataType = CHAR | UINT8 | UINT16 | UINT32 | UINT64
         | INT8 | INT16 | INT32 | INT64
         | FLOAT32 | FLOAT64
         | TT2000 | CDFEPOCH | CDFEPOCH16

Path Navigation

Rules use /-separated paths with regex support to navigate the model:

Path Example Description
attributes Global attributes dictionary
attributes/Project Specific global attribute
variables All variables dictionary
variables/Epoch Specific variable
variables/.*/attributes Attributes of all variables
variables/Epoch/data_type Data type of a specific variable
variables/Epoch/shape/0 First dimension of variable shape
attributes/Project/data_type/0 First data type of attribute

Lists are accessed using numeric indices: path/to/list/0, path/to/list/1, etc.

Defining Rules in YAML

Rules can be defined declaratively in YAML files. Example from MandatoryAttributes.yaml:

name: MandatoryGlobalAttributes
description: "All mandatory global attributes must be present"
url: "https://..."
reference: "ISTP-MD-003"
severity: ERROR
suite: ISTP

assertions:
  - path: "attributes"
    check: contains_keys
    keys:
      - Data_type
      - Logical_source
      - PI_name
    message: "Missing mandatory global attribute: {key}"

  - path: "variables/.*/attributes"
    check: contains_keys
    keys: [ CATDESC, FIELDNAM, FILLVAL ]
    message: "Variable missing required attribute: {key}"

Available Assertions

Category Checks
Existence exists, not_exists
Value comparison, range, is_type
String matches
Collection contains_keys, in, not_in, length, not_empty, requires, array_shape
Relationship reference_variable
Combinators all_of, any_of, not

๐Ÿ“– Full Assertions Reference โ†’

Supported File Formats

Format Extension Library
CDF .cdf pycdfpp

Available Conformance Suites (WIP/Demo)

Extending AstraLint

Adding a New Codec

Create a new codec in src/astralint/codecs/:

from astralint.base import Codec, File, classproperty


class MyCodec(Codec):
    @classproperty
    def supported_extensions(cls) -> list[str]:
        return ["ext"]

    @staticmethod
    def load(path: str) -> File:
        # Transform your file format into the abstract File model
        ...

Adding a New Assertion Type

Create a new assertion in src/astralint/base/yaml_rules/assertions/:

from typing import Literal, Any
from .base import BaseAssertion, resolve_path, ValidationResult, File


class MyAssertion(BaseAssertion):
    check: Literal["my_check"] = "my_check"

    # Add custom fields as needed, they will be populated from the YAML rule definition
    # e.g., expected_value: Any

    def single_assertion(self, file: File, path: str, value: Any) -> ValidationResult:
        # Implement your validation logic here, this method will be called for each path/value pair that matches the base assertion's path pattern
        # path is the resolved path in the File model, value is the value at that path
        ...

Project Docs

For how to install uv and Python, see installation.md.

For development workflows, see development.md.

For instructions on publishing to PyPI, see publishing.md.


This project was built from simple-modern-uv.

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

astralint-0.2.1.tar.gz (695.3 kB view details)

Uploaded Source

Built Distribution

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

astralint-0.2.1-py3-none-any.whl (36.7 kB view details)

Uploaded Python 3

File details

Details for the file astralint-0.2.1.tar.gz.

File metadata

  • Download URL: astralint-0.2.1.tar.gz
  • Upload date:
  • Size: 695.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for astralint-0.2.1.tar.gz
Algorithm Hash digest
SHA256 4944989e8a29b9dc00037932bd5bb203d5a2e657b11be651bb5cff9da313322c
MD5 d2371eacd95bc52c28123f9dfbe628d1
BLAKE2b-256 1640a88ff430b60205129a7059081cb964a8b26abbd6474d01bf1378800fa79c

See more details on using hashes here.

File details

Details for the file astralint-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: astralint-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 36.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for astralint-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 442f4d24031bdf772fc34fb56ac00ccc2b31604f08fc8243e5fe023631a0055d
MD5 e33b24115c721a8853ffa21771d40229
BLAKE2b-256 7c515b4c10310b9e16bc82aec1aa88ef095f4a28e5c630579c386706d7d0667c

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