dvc-utils 0.3.0__tar.gz → 0.3.1__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.
- dvc_utils-0.3.1/.github/workflows/ci.yml +74 -0
- dvc_utils-0.3.1/.gitmodules +3 -0
- {dvc_utils-0.3.0/src/dvc_utils.egg-info → dvc_utils-0.3.1}/PKG-INFO +10 -9
- {dvc_utils-0.3.0 → dvc_utils-0.3.1}/pyproject.toml +13 -8
- dvc_utils-0.3.1/pytest.ini +6 -0
- {dvc_utils-0.3.0 → dvc_utils-0.3.1}/src/dvc_utils/diff.py +2 -1
- dvc_utils-0.3.1/tests/__init__.py +0 -0
- dvc_utils-0.3.1/tests/test_diff_exit_codes.py +83 -0
- dvc_utils-0.3.1/uv.lock +2912 -0
- dvc_utils-0.3.0/PKG-INFO +0 -463
- dvc_utils-0.3.0/setup.cfg +0 -4
- dvc_utils-0.3.0/src/dvc_utils.egg-info/SOURCES.txt +0 -15
- dvc_utils-0.3.0/src/dvc_utils.egg-info/dependency_links.txt +0 -1
- dvc_utils-0.3.0/src/dvc_utils.egg-info/entry_points.txt +0 -3
- dvc_utils-0.3.0/src/dvc_utils.egg-info/requires.txt +0 -8
- dvc_utils-0.3.0/src/dvc_utils.egg-info/top_level.txt +0 -1
- {dvc_utils-0.3.0 → dvc_utils-0.3.1}/LICENSE +0 -0
- {dvc_utils-0.3.0 → dvc_utils-0.3.1}/README.md +0 -0
- {dvc_utils-0.3.0 → dvc_utils-0.3.1}/src/dvc_utils/__init__.py +0 -0
- {dvc_utils-0.3.0 → dvc_utils-0.3.1}/src/dvc_utils/cli.py +0 -0
- {dvc_utils-0.3.0 → dvc_utils-0.3.1}/src/dvc_utils/main.py +0 -0
- {dvc_utils-0.3.0 → dvc_utils-0.3.1}/src/dvc_utils/path.py +0 -0
- {dvc_utils-0.3.0 → dvc_utils-0.3.1}/src/dvc_utils/sync.py +0 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
name: Verify README examples, release to PyPI
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches: [ "main" ]
|
5
|
+
tags: [ "v**" ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ "main" ]
|
8
|
+
workflow_dispatch:
|
9
|
+
env:
|
10
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
11
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
12
|
+
jobs:
|
13
|
+
test:
|
14
|
+
name: Verify README examples
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
steps:
|
17
|
+
- uses: actions/checkout@v4
|
18
|
+
with:
|
19
|
+
fetch-depth: 0
|
20
|
+
submodules: true
|
21
|
+
- uses: astral-sh/setup-uv@v5
|
22
|
+
with:
|
23
|
+
enable-cache: true
|
24
|
+
- name: Set up Python 3.11
|
25
|
+
run: uv python install 3.11
|
26
|
+
- uses: dtolnay/rust-toolchain@stable
|
27
|
+
- uses: Swatinem/rust-cache@v2
|
28
|
+
- run: cargo install parquet2json
|
29
|
+
- name: Install dependencies
|
30
|
+
run: uv sync --extra ci --extra test
|
31
|
+
- name: Run pytest
|
32
|
+
run: |
|
33
|
+
source .venv/bin/activate
|
34
|
+
pytest
|
35
|
+
- name: '`dvc pull` test/data'
|
36
|
+
working-directory: test/data
|
37
|
+
run: |
|
38
|
+
source ../../.venv/bin/activate
|
39
|
+
dvc pull -r s3 -R -A
|
40
|
+
- name: Set up parquet-helpers
|
41
|
+
uses: actions/checkout@v4
|
42
|
+
with:
|
43
|
+
repository: ryan-williams/parquet-helpers
|
44
|
+
path: pqt
|
45
|
+
- name: Verify README examples
|
46
|
+
env:
|
47
|
+
# Evaluate README examples from within the `test/data` submodule
|
48
|
+
BMDF_WORKDIR: test/data
|
49
|
+
run: |
|
50
|
+
source .venv/bin/activate
|
51
|
+
export PATH="$PWD/pqt:$PATH"
|
52
|
+
. pqt/.pqt-rc
|
53
|
+
export SHELL
|
54
|
+
mdcmd
|
55
|
+
git diff --exit-code
|
56
|
+
release:
|
57
|
+
name: Release to PyPI
|
58
|
+
if: startsWith(github.ref, 'refs/tags/')
|
59
|
+
needs: test
|
60
|
+
runs-on: ubuntu-latest
|
61
|
+
steps:
|
62
|
+
- uses: actions/checkout@v4
|
63
|
+
- uses: astral-sh/setup-uv@v5
|
64
|
+
- name: Build package
|
65
|
+
run: uv build
|
66
|
+
- name: Publish to PyPI
|
67
|
+
run: uv publish --username __token__ --password ${{ secrets.PYPI_TOKEN }}
|
68
|
+
- name: Create GitHub Release
|
69
|
+
env:
|
70
|
+
GH_TOKEN: ${{ github.token }}
|
71
|
+
run: |
|
72
|
+
gh release create ${{ github.ref_name }} \
|
73
|
+
--title "${{ github.ref_name }}" \
|
74
|
+
--generate-notes
|
@@ -1,22 +1,23 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dvc-utils
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.1
|
4
4
|
Summary: CLI for diffing DVC-tracked files at two commits (or one commit vs. current worktree), optionally passing both through another command first
|
5
|
-
Author-email: Ryan Williams <ryan@runsascoded.com>
|
6
|
-
License: MIT
|
7
5
|
Project-URL: Homepage, https://github.com/runsascoded/dvc-utils
|
8
6
|
Project-URL: Author URL, https://github.com/ryan-williams
|
9
|
-
|
10
|
-
|
7
|
+
Author-email: Ryan Williams <ryan@runsascoded.com>
|
8
|
+
License: MIT
|
11
9
|
License-File: LICENSE
|
10
|
+
Requires-Python: >=3.9
|
12
11
|
Requires-Dist: click
|
13
|
-
Requires-Dist: dffs>=0.0.
|
12
|
+
Requires-Dist: dffs>=0.0.6
|
14
13
|
Requires-Dist: pyyaml
|
15
14
|
Requires-Dist: utz>=0.20.0
|
16
15
|
Provides-Extra: ci
|
17
|
-
Requires-Dist: bmdf==0.5.2; extra ==
|
18
|
-
Requires-Dist: dvc-s3; extra ==
|
19
|
-
|
16
|
+
Requires-Dist: bmdf==0.5.2; extra == 'ci'
|
17
|
+
Requires-Dist: dvc-s3; extra == 'ci'
|
18
|
+
Provides-Extra: test
|
19
|
+
Requires-Dist: pytest>=7.0.0; extra == 'test'
|
20
|
+
Description-Content-Type: text/markdown
|
20
21
|
|
21
22
|
# dvc-utils
|
22
23
|
Diff [DVC] files, optionally piping through other commands first.
|
@@ -1,10 +1,10 @@
|
|
1
1
|
[build-system]
|
2
|
-
requires = ["
|
3
|
-
build-backend = "
|
2
|
+
requires = ["hatchling"]
|
3
|
+
build-backend = "hatchling.build"
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "dvc-utils"
|
7
|
-
version = "0.3.
|
7
|
+
version = "0.3.1"
|
8
8
|
description = "CLI for diffing DVC-tracked files at two commits (or one commit vs. current worktree), optionally passing both through another command first"
|
9
9
|
readme = "README.md"
|
10
10
|
license = {text = "MIT"}
|
@@ -14,7 +14,7 @@ authors = [
|
|
14
14
|
requires-python = ">=3.9"
|
15
15
|
dependencies = [
|
16
16
|
"click",
|
17
|
-
"dffs>=0.0.
|
17
|
+
"dffs>=0.0.6",
|
18
18
|
"pyyaml",
|
19
19
|
"utz>=0.20.0",
|
20
20
|
]
|
@@ -24,6 +24,9 @@ ci = [
|
|
24
24
|
"bmdf==0.5.2",
|
25
25
|
"dvc-s3",
|
26
26
|
]
|
27
|
+
test = [
|
28
|
+
"pytest>=7.0.0",
|
29
|
+
]
|
27
30
|
|
28
31
|
[project.urls]
|
29
32
|
Homepage = "https://github.com/runsascoded/dvc-utils"
|
@@ -33,8 +36,10 @@ Homepage = "https://github.com/runsascoded/dvc-utils"
|
|
33
36
|
dvc-utils = "dvc_utils.main:main"
|
34
37
|
dvc-diff = "dvc_utils.diff:dvc_diff"
|
35
38
|
|
36
|
-
[
|
37
|
-
|
39
|
+
[dependency-groups]
|
40
|
+
dev = [
|
41
|
+
"pytest>=7.0.0",
|
42
|
+
]
|
38
43
|
|
39
|
-
[tool.
|
40
|
-
|
44
|
+
[tool.hatch.build.targets.wheel]
|
45
|
+
packages = ["src/dvc_utils"]
|
@@ -111,7 +111,7 @@ def dvc_diff(
|
|
111
111
|
cmds1 = [ shlex.split(cmd) for cmd in cmds1 ]
|
112
112
|
cmds2 = [ shlex.split(cmd) for cmd in cmds2 ]
|
113
113
|
|
114
|
-
join_pipelines(
|
114
|
+
returncode = join_pipelines(
|
115
115
|
base_cmd=['diff', *diff_args],
|
116
116
|
cmds1=cmds1,
|
117
117
|
cmds2=cmds2,
|
@@ -119,6 +119,7 @@ def dvc_diff(
|
|
119
119
|
shell=shell,
|
120
120
|
executable=shell_executable,
|
121
121
|
)
|
122
|
+
exit(returncode)
|
122
123
|
else:
|
123
124
|
res = process.run('diff', *diff_args, path1 or '/dev/null', path2 or '/dev/null', log=log, check=False)
|
124
125
|
exit(res.returncode)
|
File without changes
|
@@ -0,0 +1,83 @@
|
|
1
|
+
"""Tests for dvc-diff exit code handling."""
|
2
|
+
import pytest
|
3
|
+
import subprocess
|
4
|
+
from pathlib import Path
|
5
|
+
import tempfile
|
6
|
+
|
7
|
+
|
8
|
+
class TestDiffExitCodes:
|
9
|
+
"""Test that dvc-diff properly propagates exit codes from pipeline commands."""
|
10
|
+
|
11
|
+
def test_successful_pipeline_returns_zero(self, tmp_path):
|
12
|
+
"""Test that successful identical pipeline returns 0."""
|
13
|
+
# Create test files
|
14
|
+
file1 = tmp_path / "test1.txt"
|
15
|
+
file2 = tmp_path / "test2.txt"
|
16
|
+
file1.write_text("foo\nbar\n")
|
17
|
+
file2.write_text("foo\nbar\n")
|
18
|
+
|
19
|
+
# Run diff-x (not dvc-diff, but tests the same join_pipelines code)
|
20
|
+
result = subprocess.run(
|
21
|
+
["diff-x", "cat", str(file1), str(file2)],
|
22
|
+
capture_output=True,
|
23
|
+
)
|
24
|
+
assert result.returncode == 0
|
25
|
+
|
26
|
+
def test_diff_found_returns_one(self, tmp_path):
|
27
|
+
"""Test that differences found returns 1."""
|
28
|
+
file1 = tmp_path / "test1.txt"
|
29
|
+
file2 = tmp_path / "test2.txt"
|
30
|
+
file1.write_text("foo\n")
|
31
|
+
file2.write_text("bar\n")
|
32
|
+
|
33
|
+
result = subprocess.run(
|
34
|
+
["diff-x", "cat", str(file1), str(file2)],
|
35
|
+
capture_output=True,
|
36
|
+
)
|
37
|
+
assert result.returncode == 1
|
38
|
+
|
39
|
+
def test_pipeline_error_propagates(self, tmp_path):
|
40
|
+
"""Test that pipeline command errors propagate to exit code."""
|
41
|
+
file1 = tmp_path / "test1.txt"
|
42
|
+
file2 = tmp_path / "test2.txt"
|
43
|
+
file1.write_text("foo\n")
|
44
|
+
file2.write_text("bar\n")
|
45
|
+
|
46
|
+
# Use a command that will fail
|
47
|
+
result = subprocess.run(
|
48
|
+
["diff-x", "cat /nonexistent/file/that/does/not/exist ||", str(file1), str(file2)],
|
49
|
+
capture_output=True,
|
50
|
+
shell=False,
|
51
|
+
)
|
52
|
+
# Should return non-zero due to cat failing
|
53
|
+
assert result.returncode != 0
|
54
|
+
|
55
|
+
def test_false_command_propagates_error(self, tmp_path):
|
56
|
+
"""Test that 'false' command in pipeline propagates error."""
|
57
|
+
file1 = tmp_path / "test1.txt"
|
58
|
+
file2 = tmp_path / "test2.txt"
|
59
|
+
file1.write_text("foo\n")
|
60
|
+
file2.write_text("bar\n")
|
61
|
+
|
62
|
+
# Use 'false' which always returns 1
|
63
|
+
result = subprocess.run(
|
64
|
+
["diff-x", "cat", "false", str(file1), str(file2)],
|
65
|
+
capture_output=True,
|
66
|
+
)
|
67
|
+
# Should return non-zero due to false in pipeline
|
68
|
+
assert result.returncode != 0
|
69
|
+
|
70
|
+
def test_multi_stage_pipeline_error(self, tmp_path):
|
71
|
+
"""Test that errors in multi-stage pipelines are detected."""
|
72
|
+
file1 = tmp_path / "test1.txt"
|
73
|
+
file2 = tmp_path / "test2.txt"
|
74
|
+
file1.write_text("foo\nbar\n")
|
75
|
+
file2.write_text("bar\nfoo\n")
|
76
|
+
|
77
|
+
# Pipeline: sort (succeeds) | false (fails)
|
78
|
+
result = subprocess.run(
|
79
|
+
["diff-x", "-x", "sort", "-x", "false", str(file1), str(file2)],
|
80
|
+
capture_output=True,
|
81
|
+
)
|
82
|
+
# Should return non-zero due to false in pipeline
|
83
|
+
assert result.returncode != 0
|