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:
- Codecs transform file formats (e.g., CDF) into a common abstract representation (
File) - Suites define collections of validation rules (e.g., ISTP, PDS4)
- 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):
- CLI arguments
.astralint.yaml(project root)pyproject.toml[tool.astralint]- 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
โโโ filename: str # File name or identifier
โโโ extension: str # File extension (e.g., "cdf")
โโโ 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)
- ISTP - ISTP Metadata Guidelines
- PDS4 - Planetary Data System v4
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(file_url_or_bytes: str | bytes) -> File | None:
# Transform your file format into the abstract File model
...
For remote files, AstraLint provides a get_remote_file function that handles downloading remote files and is_remote_file checks if a file is remote.
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file astralint-0.4.4.tar.gz.
File metadata
- Download URL: astralint-0.4.4.tar.gz
- Upload date:
- Size: 712.1 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3af29a1b2ff22c5cb0adaf5842a0f27e6a4b5890470e7b59a5075be66c3dc3ca
|
|
| MD5 |
98bc3f7672a5fda996cba27ae4b615a0
|
|
| BLAKE2b-256 |
1c46c1869cd7ed8ce2f5aaa417245292c883c110bc9304ddb0a2a3584fe0b3b5
|
File details
Details for the file astralint-0.4.4-py3-none-any.whl.
File metadata
- Download URL: astralint-0.4.4-py3-none-any.whl
- Upload date:
- Size: 55.8 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c79b292cb4b6ff90275c02439cb453fc46b43a4acbda9fe528aaf8542cd0543
|
|
| MD5 |
212f8a563ae598ce2e62caae1c046a9f
|
|
| BLAKE2b-256 |
6ddc2ab1c13f4c62e617219a8b02d0e299baadd1a94c44bbaed0fe538ddaaeeb
|