Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
bcbf5ed
expand example test
wingechr Jul 14, 2025
406af0e
update project
wingechr Dec 3, 2025
1952c4f
uv
wingechr Dec 3, 2025
baeaf42
ruff
wingechr Jan 14, 2026
e284483
reset
wingechr Mar 4, 2026
9f6715b
fix tests
wingechr Mar 4, 2026
129c2cb
fix doctest, docs
wingechr Mar 4, 2026
03693d4
codecov, badges
wingechr Mar 5, 2026
3ff6d98
license badge icon
wingechr Mar 5, 2026
f319044
reorder badges
wingechr Mar 5, 2026
bb51506
license badge link from dev branch
wingechr Mar 5, 2026
d638b1a
license badge link from dev branch
wingechr Mar 5, 2026
23dcdd1
ruff in pre-commit
wingechr Mar 5, 2026
ca0294b
use token for codecov
wingechr Mar 5, 2026
74a49da
storage base class
wingechr Jun 21, 2026
b4abb1e
Text utils, File storage class
wingechr Jun 21, 2026
89f576b
command line sript
wingechr Jun 21, 2026
e5b6b0d
webserver
wingechr Jun 21, 2026
f2d8188
http backend sorta works
wingechr Jun 21, 2026
a508528
sqk backend
wingechr Jun 21, 2026
4fc901c
fix tests and pre-commit
wingechr Jun 22, 2026
d7efa0f
primitive RDF metadata storage
wingechr Jun 22, 2026
29a81fb
removed context manager
wingechr Jun 22, 2026
7f9d235
infer storage class, handle relative file:// uris
wingechr Jun 22, 2026
8cca3c6
TestCliDataStorage
wingechr Jun 24, 2026
1db85a9
rename TestCliDataStorage to CliWrapperDataStorage
wingechr Jun 24, 2026
e331feb
migrate rdflib.Graph => rdflib.Dataset
wingechr Jun 24, 2026
6d8f83c
storage cli: location as optional argument
wingechr Jun 24, 2026
a4eb5d8
change argument order in staorage metadata
wingechr Jun 24, 2026
2b0aa0e
metadata values: try parse json on retrieve
wingechr Jun 24, 2026
bc46924
WIP
wingechr Jun 24, 2026
305077b
WIP
wingechr Jun 25, 2026
24112f5
WIP test_use_case_job_graph
wingechr Jun 25, 2026
6f08968
TIP function wrapper
wingechr Jun 25, 2026
e5fce2a
refactoring
wingechr Jun 25, 2026
19b4f04
cache via wrapped function
wingechr Jun 25, 2026
1d9ea99
names_get_argument_dict
wingechr Jun 25, 2026
80f47ac
attach jobs to storage
wingechr Jun 25, 2026
7295086
jobs with metadata
wingechr Jun 25, 2026
3d255ab
job transparent defaults
wingechr Jun 25, 2026
722523a
simplify jobs
wingechr Jun 25, 2026
703723e
job tied to storage with metadata
wingechr Jun 25, 2026
e329cc1
Job
wingechr Jun 25, 2026
3c965fd
WIP cache as class
wingechr Jun 25, 2026
eb9fb80
storage job without having to wrapp __call__
wingechr Jun 26, 2026
a891621
storage cache via Job
wingechr Jun 26, 2026
47010a9
fix defaults in names_get_argument_dict
wingechr Jun 26, 2026
d4c1bec
WIP
wingechr Jun 26, 2026
52e3b45
importer as jobs
wingechr Jun 26, 2026
6eb9b15
fix test (windows/linux) line ending
wingechr Jun 26, 2026
9c0b42e
uv lock,python14
wingechr Jun 26, 2026
77c72a4
updagred dependencies
wingechr Jun 26, 2026
278cee3
requires-python
wingechr Jun 26, 2026
474536c
WIP improve code coverage
wingechr Jun 26, 2026
e930b08
switch to CliRunner instead of subprocess
wingechr Jun 26, 2026
530684a
metadata json
wingechr Jun 27, 2026
6cf58f5
fix metadata query tests
wingechr Jun 27, 2026
658129a
job - check exist
wingechr Jun 27, 2026
0b42aa8
snakemake
wingechr Jun 27, 2026
da7887f
snakemake
wingechr Jun 27, 2026
7ede31a
Job.get_job_hashsum
wingechr Jun 27, 2026
d9a3528
test get_job_hashsum
wingechr Jun 27, 2026
da7e077
WIP example / test
wingechr Jun 28, 2026
1ca0c7a
WIP
wingechr Jun 28, 2026
e0a334a
WIP
wingechr Jun 29, 2026
ff16f8f
remove support for python3.10
wingechr Jul 1, 2026
d5643b9
fix tests
wingechr Jul 1, 2026
379b88d
remove support for python 3.14
wingechr Jul 1, 2026
a6c6c55
refactoring
wingechr Jul 1, 2026
7639315
add doctests
wingechr Jul 1, 2026
e607701
version: 0.14.0 → 0.15.0
wingechr Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.14.0
current_version = 0.15.0
commit = True
tag = True
message = version: {current_version} → {new_version}
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- dev

jobs:
docs:
Expand All @@ -14,6 +15,6 @@ jobs:
- uses: actions/setup-python@v5
- run: |
pip install uv
uv sync --only-group docs
uv sync --group=docs
- run: |
uv run mkdocs gh-deploy --force
5 changes: 3 additions & 2 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- run: |
pip install build
python -m build
pip install uv
- run: |
uv build
- uses: pypa/gh-action-pypi-publish@release/v1
with:
skip-existing: true
Expand Down
25 changes: 20 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,29 @@
strategy:
matrix:
os: [ubuntu-latest, windows-latest] # macos-latest
python-version: [3.9, 3.13]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: |
pip install tox
pip install uv
uv sync --group=test
- run: |
tox
uv run tox

codecov:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- run: |
pip install uv
uv sync --group=test
- run: |
uv run pytest --cov=datatools --cov-report=term-missing --cov-report=xml:coverage.xml
- uses: codecov/codecov-action@v4
with:
files: coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium test

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Comment on lines +24 to +38
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@ build
site
_archive
__pycache__
*.lock
.pytest_cache
coverage.xml
.coverage
htmlcov
.snakemake
.ruff_cache
39 changes: 19 additions & 20 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
exclude: ^.*(.min.js|.min.css)$
exclude: ^$
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
rev: v6.0.0
hooks:
- id: check-yaml
- id: check-case-conflict # checks for files that would conflict in case-insensitive filesystems.
- id: check-merge-conflict # checks for files that contain merge conflict strings.
- id: check-yaml # checks yaml files for parseable syntax.
args: ["--unsafe"] # because of tags in mkdocs.yml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 25.1.0
- id: detect-private-key # detects the presence of private keys.
- id: end-of-file-fixer # ensures that a file is either empty, or ends with one newline.
- id: fix-byte-order-marker # removes utf-8 byte order marker.
- id: mixed-line-ending # replaces or checks mixed line ending.
- id: requirements-txt-fixer # sorts entries in requirements.txt.
- id: trailing-whitespace # trims trailing whitespace.

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.9
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: 6.0.1
hooks:
- id: isort
args: ["--profile", "black", "--filter-files"]
- repo: https://github.com/pycqa/flake8
rev: 7.3.0
hooks:
- id: flake8
additional_dependencies:
- flake8-black>=0.1.1
args: ["--max-line-length=88", "--ignore=E20,W503,E704"] # black compatible
# Run the linter.
- id: ruff-check
args: [--fix]
# Run the formatter.
- id: ruff-format
51 changes: 51 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@

line-length = 88
exclude = ["**/migrations/*.py"]

[format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"


[lint]
select = [
"E", # pycodestyle
"F", # Pyflakes
"UP", # pyupgrade
"B", # flake8-bugbear: opinionated bug & design warnings
"SIM", # flake8-simplify
"I", # isort: imports
"S", # flake8-bandit: Security issues
"A", # flake8-builtins
"C4", # flake8-comprehensions
"D", # pydocstyle
]
ignore = [
"B017", # assert-raises-exception
"D105", # Missing docstring in magic method
"D107", # undocumented-public-init
"D202", # blank-line-after-function
"D203", # incorrect-blank-line-before-class
"D211", # blank-line-before-class
"D213", # multi-line-summary-second-line
"D400", # First line should end with a period
"D401", # non-imperative-mood
"D403", # first-word-uncapitalized
"D415", # missing-terminal-punctuation
"D412", # otherwise docstring tests will be badly formatted - we need empty line
#"S101", # assert
"S113", # request-without-timeout
"S310", # suspicious-url-open-usage
"S603", # subprocess-without-shell-equals-true
#"S608", # hardcoded-sql-expression
]


[lint.isort]
combine-as-imports = true
force-sort-within-sections = true

[lint.pydocstyle]
ignore-decorators = ["abc.abstractmethod"]
121 changes: 121 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
Creative Commons Legal Code

CC0 1.0 Universal

CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.

Statement of Purpose

The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").

Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.

For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.

1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:

i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.

2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.

3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.

4. Limitations and Disclaimers.

a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# README

[![github](https://img.shields.io/badge/GitHub-181717?style=flat&logo=github&logoColor=white)](https://github.com/wingechr/datatools)
[![docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue?style=?style=flat&logo=readthedocs&logoColor=white)](https://wingechr.github.io/datatools/)
[![pypi](https://img.shields.io/pypi/v/wingechr-datatools.svg?style=flat&logo=python&logoColor=white)](https://pypi.org/project/wingechr-datatools)
[![test](https://github.com/wingechr/datatools/actions/workflows/test.yml/badge.svg)](https://github.com/wingechr/datatools/actions/workflows/test.yml)
[![snyk](https://snyk.io/test/github/wingechr/datatools/badge.svg)](https://snyk.io/test/github/wingechr/datatools)
[![codecov](https://codecov.io/gh/wingechr/datatools/branch/dev/graph/badge.svg)](https://codecov.io/gh/wingechr/datatools)
[![license](https://img.shields.io/badge/License-CC0%201.0-lightgrey?style=flat&logo=creativecommons&logoColor=white)](https://github.com/wingechr/datatools/blob/dev/LICENSE)

## Installation

`pip install wingechr-datatools`
17 changes: 4 additions & 13 deletions datatools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
__version__ = "0.14.0"
"""data processing tools."""

from datatools import utils
from datatools.converter import Converter
from datatools.process import Function
from datatools.storage import Metadata, Resource, Storage
__version__ = "0.15.0"
__all__ = ["FileDataStorage"]

__all__ = [
"Storage",
"Resource",
"Metadata",
"Function",
"Converter",
"utils",
]
from datatools.storage.file import FileDataStorage
42 changes: 42 additions & 0 deletions datatools/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""datatools cmd entry point."""

import logging

import click
import coloredlogs

from datatools import __version__
from datatools.storage.__main__ import main as storage_main
from datatools.utils import wrap_exception

LOGLEVELS_COLORS = {
"debug": "blue",
"info": "green",
"warning": "yellow",
"error": "red",
}


@click.group()
# @click.pass_context
@click.version_option(version=__version__)
@click.option(
"--loglevel", "-l", type=click.Choice(LOGLEVELS_COLORS.keys()), default="info"
)
def main(loglevel: str) -> None:
"""TODO"""
coloredlogs.install(
level=getattr(logging, loglevel.upper()),
fmt="[%(asctime)s %(levelname)7s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
field_styles={k: {"color": "white"} for k in ["asctime", "levelname"]},
level_styles={k: {"color": v} for k, v in LOGLEVELS_COLORS.items()},
)
logging.debug("loglevel: %s", loglevel)


main.add_command(storage_main, name="storage")


if __name__ == "__main__":
wrap_exception(main)
Loading
Loading