useful-views 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- useful_views-0.1.0/.gitattributes +4 -0
- useful_views-0.1.0/.github/workflows/ci.yml +91 -0
- useful_views-0.1.0/.github/workflows/docs.yml +110 -0
- useful_views-0.1.0/.github/workflows/release.yml +78 -0
- useful_views-0.1.0/.gitignore +8 -0
- useful_views-0.1.0/CHANGELOG.md +48 -0
- useful_views-0.1.0/CITATION.cff +22 -0
- useful_views-0.1.0/LICENSE +21 -0
- useful_views-0.1.0/PKG-INFO +568 -0
- useful_views-0.1.0/README.md +543 -0
- useful_views-0.1.0/docs/assets/site.css +22 -0
- useful_views-0.1.0/docs/useful-views-icon.svg +65 -0
- useful_views-0.1.0/docs/useful-views-logo-dark.svg +66 -0
- useful_views-0.1.0/docs/useful-views-logo.svg +66 -0
- useful_views-0.1.0/great-docs.yml +103 -0
- useful_views-0.1.0/pyproject.toml +52 -0
- useful_views-0.1.0/scripts/generate_docs.py +136 -0
- useful_views-0.1.0/skills/useful-views/SKILL.md +114 -0
- useful_views-0.1.0/src/useful_views/__init__.py +53 -0
- useful_views-0.1.0/src/useful_views/__main__.py +5 -0
- useful_views-0.1.0/src/useful_views/cli.py +393 -0
- useful_views-0.1.0/src/useful_views/cookbooks.py +229 -0
- useful_views-0.1.0/src/useful_views/errors.py +151 -0
- useful_views-0.1.0/src/useful_views/examples.py +221 -0
- useful_views-0.1.0/src/useful_views/lock.py +147 -0
- useful_views-0.1.0/src/useful_views/new.py +55 -0
- useful_views-0.1.0/src/useful_views/paths.py +216 -0
- useful_views-0.1.0/src/useful_views/project.py +216 -0
- useful_views-0.1.0/src/useful_views/py.typed +0 -0
- useful_views-0.1.0/src/useful_views/recipe.py +396 -0
- useful_views-0.1.0/src/useful_views/record.py +427 -0
- useful_views-0.1.0/src/useful_views/rulebook.py +94 -0
- useful_views-0.1.0/src/useful_views/rules.py +412 -0
- useful_views-0.1.0/src/useful_views/runner.py +570 -0
- useful_views-0.1.0/src/useful_views/status.py +288 -0
- useful_views-0.1.0/src/useful_views/syncing.py +519 -0
- useful_views-0.1.0/src/useful_views/templates/01_first_step.py +12 -0
- useful_views-0.1.0/src/useful_views/templates/AGENTS.md +21 -0
- useful_views-0.1.0/src/useful_views/templates/project_README.md +118 -0
- useful_views-0.1.0/src/useful_views/templates/recipe.toml +16 -0
- useful_views-0.1.0/tests/conftest.py +229 -0
- useful_views-0.1.0/tests/data/examples/pwt/README.md +63 -0
- useful_views-0.1.0/tests/data/examples/pwt/cookbook.json +56 -0
- useful_views-0.1.0/tests/data/examples/pwt/datapackage.json +482 -0
- useful_views-0.1.0/tests/data/examples/pwt/raw/pwt110_bra_deu_esp_usa.csv +169 -0
- useful_views-0.1.0/tests/data/examples/pwt/recipes/gdp_per_capita/01_derive_measures.py +27 -0
- useful_views-0.1.0/tests/data/examples/pwt/recipes/gdp_per_capita/recipe.toml +3 -0
- useful_views-0.1.0/tests/data/examples/pwt/recipes/pwt_panel/01_reshape_long.py +10 -0
- useful_views-0.1.0/tests/data/examples/pwt/recipes/pwt_panel/02_keep_core_variables.py +9 -0
- useful_views-0.1.0/tests/data/examples/pwt/recipes/pwt_panel/03_pivot_to_panel.py +13 -0
- useful_views-0.1.0/tests/data/examples/pwt/recipes/pwt_panel/recipe.toml +3 -0
- useful_views-0.1.0/tests/data/examples/pwt/useful-views/README.md +50 -0
- useful_views-0.1.0/tests/data/examples/pwt/useful-views/gdp-per-capita.parquet +0 -0
- useful_views-0.1.0/tests/data/examples/pwt/useful-views/pwt-panel.parquet +0 -0
- useful_views-0.1.0/tests/test_agent_surfaces.py +407 -0
- useful_views-0.1.0/tests/test_check_sync.py +895 -0
- useful_views-0.1.0/tests/test_cookbook.py +216 -0
- useful_views-0.1.0/tests/test_docs.py +36 -0
- useful_views-0.1.0/tests/test_edge_cases.py +327 -0
- useful_views-0.1.0/tests/test_example.py +208 -0
- useful_views-0.1.0/tests/test_formats.py +883 -0
- useful_views-0.1.0/tests/test_project.py +815 -0
- useful_views-0.1.0/tests/test_quickstart.py +82 -0
- useful_views-0.1.0/tests/test_reference.py +78 -0
- useful_views-0.1.0/tests/test_refusals.py +885 -0
- useful_views-0.1.0/tests/test_regressions.py +325 -0
- useful_views-0.1.0/tests/test_robustness.py +484 -0
- useful_views-0.1.0/tests/test_run.py +641 -0
- useful_views-0.1.0/user_guide/concepts/cookbook.md +180 -0
- useful_views-0.1.0/user_guide/concepts/projects.md +98 -0
- useful_views-0.1.0/user_guide/concepts/recipes.md +125 -0
- useful_views-0.1.0/user_guide/concepts/records.md +82 -0
- useful_views-0.1.0/user_guide/concepts/running.md +116 -0
- useful_views-0.1.0/user_guide/concepts/steps.md +179 -0
- useful_views-0.1.0/user_guide/guides/ai-tools.md +113 -0
- useful_views-0.1.0/user_guide/installation.md +120 -0
- useful_views-0.1.0/user_guide/quickstart.md +295 -0
- useful_views-0.1.0/user_guide/reference/check-findings.md +22 -0
- useful_views-0.1.0/user_guide/reference/cli.md +167 -0
- useful_views-0.1.0/user_guide/reference/environment.md +60 -0
- useful_views-0.1.0/user_guide/reference/rules.md +41 -0
- useful_views-0.1.0/uv.lock +2936 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# Runs on every push to main or dev, on every pull request, and by hand
|
|
4
|
+
# (Actions tab > CI > Run workflow).
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main, dev]
|
|
8
|
+
pull_request:
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: ci-${{ github.ref }}
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
test:
|
|
20
|
+
name: test (${{ matrix.os }}, Python ${{ matrix.python }})
|
|
21
|
+
runs-on: ${{ matrix.os }}
|
|
22
|
+
timeout-minutes: 30
|
|
23
|
+
strategy:
|
|
24
|
+
fail-fast: false
|
|
25
|
+
matrix:
|
|
26
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
27
|
+
python: ["3.11", "3.12", "3.13", "3.14"]
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v6
|
|
30
|
+
- uses: astral-sh/setup-uv@v6
|
|
31
|
+
- name: Install
|
|
32
|
+
run: uv sync --locked --python ${{ matrix.python }}
|
|
33
|
+
- name: Test
|
|
34
|
+
run: uv run --locked pytest -n auto
|
|
35
|
+
|
|
36
|
+
lowest-dependencies:
|
|
37
|
+
name: test (oldest supported pyarrow)
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
timeout-minutes: 30
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v6
|
|
42
|
+
- uses: astral-sh/setup-uv@v6
|
|
43
|
+
- name: Install with pyarrow 16
|
|
44
|
+
run: |
|
|
45
|
+
uv venv --python 3.11
|
|
46
|
+
echo "pyarrow==16.0.0" > constraints.txt
|
|
47
|
+
# The dev group's bounds (pyproject.toml), with pyarrow held at the oldest supported.
|
|
48
|
+
uv pip install -c constraints.txt -e . "pytest>=8" "pytest-xdist>=3" "polars>=1.20" "frictionless[pandas]>=5.18,<6"
|
|
49
|
+
- name: Test
|
|
50
|
+
run: .venv/bin/python -m pytest -n auto
|
|
51
|
+
|
|
52
|
+
package:
|
|
53
|
+
name: build and check the package
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
timeout-minutes: 15
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v6
|
|
58
|
+
- uses: astral-sh/setup-uv@v6
|
|
59
|
+
- name: Build
|
|
60
|
+
run: uv build
|
|
61
|
+
- name: Check metadata
|
|
62
|
+
run: uvx twine check --strict dist/*
|
|
63
|
+
- name: Install the wheel and build the real example with it
|
|
64
|
+
# Downloads the pinned example from GitHub, so it also checks the
|
|
65
|
+
# pinned tag and checksums, and that the wheel holds its templates.
|
|
66
|
+
run: |
|
|
67
|
+
uv venv --python 3.11 /tmp/wheel-env
|
|
68
|
+
uv pip install --python /tmp/wheel-env/bin/python dist/*.whl polars
|
|
69
|
+
cd /tmp
|
|
70
|
+
/tmp/wheel-env/bin/useful-views --version
|
|
71
|
+
/tmp/wheel-env/bin/useful-views example pwt smoke
|
|
72
|
+
/tmp/wheel-env/bin/useful-views -C smoke sync
|
|
73
|
+
/tmp/wheel-env/bin/useful-views -C smoke check
|
|
74
|
+
/tmp/wheel-env/bin/useful-views -C smoke cookbook
|
|
75
|
+
/tmp/wheel-env/bin/useful-views -C smoke cookbook --check
|
|
76
|
+
test -f smoke/AGENTS.md
|
|
77
|
+
|
|
78
|
+
# One check that is green only when every job above is, for branch
|
|
79
|
+
# protection to require (instead of naming each job of the matrix).
|
|
80
|
+
all-green:
|
|
81
|
+
name: all checks passed
|
|
82
|
+
if: always()
|
|
83
|
+
needs: [test, lowest-dependencies, package]
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
timeout-minutes: 5
|
|
86
|
+
steps:
|
|
87
|
+
- name: Fail unless every job passed
|
|
88
|
+
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')
|
|
89
|
+
run: exit 1
|
|
90
|
+
- name: Every job passed
|
|
91
|
+
run: echo "All jobs passed."
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
name: CI Docs
|
|
2
|
+
|
|
3
|
+
# Builds on every pull request (as a check, without publishing), and builds
|
|
4
|
+
# and publishes to GitHub Pages on every push to main. Also runs by hand
|
|
5
|
+
# (Actions tab > CI Docs > Run workflow).
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
pull_request:
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build-docs:
|
|
17
|
+
name: "Build Docs"
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
timeout-minutes: 30
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v6
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0 # Full history for accurate page timestamps
|
|
24
|
+
|
|
25
|
+
- uses: actions/setup-python@v6
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.11"
|
|
28
|
+
|
|
29
|
+
- name: Install package and dependencies
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install uv
|
|
32
|
+
uv sync --locked --group docs
|
|
33
|
+
|
|
34
|
+
- name: Check the generated reference pages are up to date
|
|
35
|
+
run: |
|
|
36
|
+
uv run python scripts/generate_docs.py
|
|
37
|
+
git diff --exit-code user_guide/reference
|
|
38
|
+
|
|
39
|
+
- name: Set up Quarto
|
|
40
|
+
uses: quarto-dev/quarto-actions/setup@v2
|
|
41
|
+
|
|
42
|
+
- name: Build docs
|
|
43
|
+
run: uv run --group docs great-docs build
|
|
44
|
+
|
|
45
|
+
- name: Save docs artifact
|
|
46
|
+
uses: actions/upload-artifact@v7
|
|
47
|
+
with:
|
|
48
|
+
name: docs-html
|
|
49
|
+
path: great-docs/_site
|
|
50
|
+
include-hidden-files: true
|
|
51
|
+
|
|
52
|
+
- name: How to preview this build locally
|
|
53
|
+
if: github.event_name == 'pull_request'
|
|
54
|
+
run: uv run --group docs great-docs ci notice --run ${{ github.run_id }} --pr ${{ github.event.number }}
|
|
55
|
+
|
|
56
|
+
- name: Upload build timings
|
|
57
|
+
uses: actions/upload-artifact@v7
|
|
58
|
+
with:
|
|
59
|
+
name: build-timings
|
|
60
|
+
path: great-docs/_site/build-timings.json
|
|
61
|
+
|
|
62
|
+
publish-docs:
|
|
63
|
+
name: "Publish Docs"
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
needs: "build-docs"
|
|
66
|
+
if: github.ref == 'refs/heads/main'
|
|
67
|
+
# One deployment at a time; a newer one waits instead of cancelling.
|
|
68
|
+
concurrency:
|
|
69
|
+
group: pages
|
|
70
|
+
cancel-in-progress: false
|
|
71
|
+
permissions:
|
|
72
|
+
pages: write
|
|
73
|
+
id-token: write
|
|
74
|
+
environment:
|
|
75
|
+
name: github-pages
|
|
76
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
77
|
+
steps:
|
|
78
|
+
- uses: actions/download-artifact@v7
|
|
79
|
+
with:
|
|
80
|
+
name: docs-html
|
|
81
|
+
path: great-docs/_site
|
|
82
|
+
|
|
83
|
+
- name: Upload Pages artifact
|
|
84
|
+
uses: actions/upload-pages-artifact@v5
|
|
85
|
+
with:
|
|
86
|
+
path: great-docs/_site
|
|
87
|
+
include-hidden-files: true
|
|
88
|
+
|
|
89
|
+
- name: Deploy to GitHub Pages
|
|
90
|
+
id: deployment
|
|
91
|
+
uses: actions/deploy-pages@v5
|
|
92
|
+
|
|
93
|
+
preview-docs:
|
|
94
|
+
name: "Preview Docs"
|
|
95
|
+
runs-on: ubuntu-latest
|
|
96
|
+
needs: "build-docs"
|
|
97
|
+
if: github.event_name == 'pull_request'
|
|
98
|
+
permissions:
|
|
99
|
+
pull-requests: write
|
|
100
|
+
steps:
|
|
101
|
+
# Post (and keep updated) a sticky PR comment with the local-preview
|
|
102
|
+
# command, pinned to this run so it reproduces the build under review.
|
|
103
|
+
# Runs the released great-docs via pipx (no install step needed); kept as
|
|
104
|
+
# its own minimal job so the docs build never holds a pull-requests:write
|
|
105
|
+
# token. continue-on-error so fork PRs (read-only token) don't fail the run.
|
|
106
|
+
- name: Post preview instructions to the PR
|
|
107
|
+
continue-on-error: true
|
|
108
|
+
run: pipx run great-docs ci pr-comment --run ${{ github.run_id }} --pr ${{ github.event.number }}
|
|
109
|
+
env:
|
|
110
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publishes a release to PyPI when a version tag is pushed:
|
|
4
|
+
#
|
|
5
|
+
# git tag v0.1.0 && git push origin v0.1.0
|
|
6
|
+
#
|
|
7
|
+
# Before the first release, PyPI must trust this workflow: on pypi.org,
|
|
8
|
+
# Your projects > Publishing > Add a new pending publisher, with owner
|
|
9
|
+
# jameshorine, repository useful-views, workflow release.yml and
|
|
10
|
+
# environment pypi. No password or API token is stored anywhere.
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
tags: ["v*"]
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
build:
|
|
20
|
+
name: Build and check
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
timeout-minutes: 15
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v6
|
|
25
|
+
- uses: astral-sh/setup-uv@v6
|
|
26
|
+
- name: The tag must match the version in pyproject.toml
|
|
27
|
+
run: |
|
|
28
|
+
version=$(uv run --no-project python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
|
|
29
|
+
if [ "v$version" != "$GITHUB_REF_NAME" ]; then
|
|
30
|
+
echo "Tag $GITHUB_REF_NAME does not match version $version in pyproject.toml"
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
- name: Build
|
|
34
|
+
run: uv build
|
|
35
|
+
- name: Check metadata
|
|
36
|
+
run: uvx twine check --strict dist/*
|
|
37
|
+
- uses: actions/upload-artifact@v7
|
|
38
|
+
with:
|
|
39
|
+
name: dist
|
|
40
|
+
path: dist/
|
|
41
|
+
|
|
42
|
+
publish:
|
|
43
|
+
name: Publish to PyPI
|
|
44
|
+
needs: build
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
timeout-minutes: 15
|
|
47
|
+
environment:
|
|
48
|
+
name: pypi
|
|
49
|
+
url: https://pypi.org/project/useful-views/
|
|
50
|
+
permissions:
|
|
51
|
+
id-token: write # Trusted Publishing: PyPI checks who is publishing
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/download-artifact@v7
|
|
54
|
+
with:
|
|
55
|
+
name: dist
|
|
56
|
+
path: dist/
|
|
57
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
58
|
+
|
|
59
|
+
github-release:
|
|
60
|
+
name: GitHub release
|
|
61
|
+
needs: publish
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
timeout-minutes: 10
|
|
64
|
+
permissions:
|
|
65
|
+
contents: write
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v6
|
|
68
|
+
- uses: actions/download-artifact@v7
|
|
69
|
+
with:
|
|
70
|
+
name: dist
|
|
71
|
+
path: dist/
|
|
72
|
+
- name: Create the release, with this version's CHANGELOG section as its notes
|
|
73
|
+
env:
|
|
74
|
+
GH_TOKEN: ${{ github.token }}
|
|
75
|
+
run: |
|
|
76
|
+
version="${GITHUB_REF_NAME#v}"
|
|
77
|
+
awk -v v="$version" '$0 ~ "^## "v" " {on=1; next} /^## / {on=0} on' CHANGELOG.md > notes.md
|
|
78
|
+
gh release create "$GITHUB_REF_NAME" dist/* --title "useful-views $version" --notes-file notes.md
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to useful-views are recorded here. Versions follow
|
|
4
|
+
[semantic versioning](https://semver.org/); while the version starts with
|
|
5
|
+
0, a minor release may change behaviour.
|
|
6
|
+
|
|
7
|
+
## 0.1.0 (2026-10-15)
|
|
8
|
+
|
|
9
|
+
The first release: the minimum version.
|
|
10
|
+
|
|
11
|
+
- A fixed project structure: `raw/`, `recipes/`, `work/`, `useful-views/`,
|
|
12
|
+
a generated `datapackage.json` and a generated catalog,
|
|
13
|
+
`useful-views/README.md`.
|
|
14
|
+
- `init`, `new_recipe`, `run`, `check` and `sync`, as Python functions and
|
|
15
|
+
as the `useful-views` command, and `root` (Python only). `init` also writes
|
|
16
|
+
an `AGENTS.md` for AI coding assistants, and refuses the home folder or the
|
|
17
|
+
top of a drive without `--force`.
|
|
18
|
+
- `example` downloads a ready-to-run example project from the
|
|
19
|
+
useful-views-data repository, pinned to a tag and checked by SHA-256.
|
|
20
|
+
- `check` reports what `run` and `sync` would refuse (`refused`, with the
|
|
21
|
+
rule number) and recipes changed since they last ran (`out-of-date`).
|
|
22
|
+
`sync` checks every recipe before changing anything and lists every
|
|
23
|
+
problem at once.
|
|
24
|
+
- `useful-views cookbook` writes `cookbook.json`, the ledger of the recipes a
|
|
25
|
+
project uses, in run order (format version 1; file hashes are planned);
|
|
26
|
+
`cookbook --check` verifies it in CI without needing the data, and `check`
|
|
27
|
+
reports `stale-cookbook` (and `stale-catalog` for a hand-edited catalog).
|
|
28
|
+
- For scripts and AI tools: `--json` on every command (with `warnings` and one
|
|
29
|
+
error shape), `-C <path>`, `useful-views rules` (and `useful_views.RULES`),
|
|
30
|
+
exit codes in `--help`, and errors that carry the recipe, rule, file and
|
|
31
|
+
step (`to_dict()`). Progress lines go to standard error.
|
|
32
|
+
- One command at a time: `run`, `sync` and `cookbook` hold a lock on the
|
|
33
|
+
project. On the command line, SIGTERM and SIGHUP stop the running step and
|
|
34
|
+
clean up as Ctrl-C does. `run` warns about recipes downstream of it, and a
|
|
35
|
+
`sync` that stops partway removes the views it left out of date.
|
|
36
|
+
- Recipes are folders with a `recipe.toml` and numbered Python step files;
|
|
37
|
+
every view records the recipe, inputs and steps that made it.
|
|
38
|
+
- `sync` makes the views match the recipe folders, like `uv sync`: it runs
|
|
39
|
+
what is missing or changed, upstream first, and removes what is no longer
|
|
40
|
+
declared.
|
|
41
|
+
- Schemas are read with pyarrow; the generated `datapackage.json` passes
|
|
42
|
+
`frictionless validate`.
|
|
43
|
+
- A documentation site built with great-docs: getting started, concepts
|
|
44
|
+
(projects, steps, recipes, running, records and the cookbook), a guide for
|
|
45
|
+
AI tools, a generated command-line and rules reference, an API reference
|
|
46
|
+
from the docstrings, and `llms.txt` and a hand-written `SKILL.md` for
|
|
47
|
+
coding agents.
|
|
48
|
+
- Tested on Python 3.11 to 3.14.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use useful-views in your research, please cite it as below."
|
|
3
|
+
type: software
|
|
4
|
+
title: "useful-views: Documented derived tables for data projects"
|
|
5
|
+
abstract: >-
|
|
6
|
+
A Python package that gives a data project a fixed structure, in
|
|
7
|
+
which every derived table (a "useful view") records the recipe, inputs and
|
|
8
|
+
steps that made it, in a standard Data Package.
|
|
9
|
+
authors:
|
|
10
|
+
- family-names: Horine
|
|
11
|
+
given-names: James
|
|
12
|
+
version: 0.1.0
|
|
13
|
+
date-released: "2026-10-15"
|
|
14
|
+
license: MIT
|
|
15
|
+
repository-code: "https://github.com/jameshorine/useful-views"
|
|
16
|
+
url: "https://jameshorine.github.io/useful-views/"
|
|
17
|
+
keywords:
|
|
18
|
+
- research data
|
|
19
|
+
- reproducibility
|
|
20
|
+
- data provenance
|
|
21
|
+
- data package
|
|
22
|
+
- python
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 James Horine
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|