pdfdancer-client-python 0.3.14__tar.gz → 3.0.2__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.
Files changed (102) hide show
  1. pdfdancer_client_python-3.0.2/.autosnap.toml +10 -0
  2. pdfdancer_client_python-3.0.2/.github/dependabot.yml +6 -0
  3. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/.github/workflows/ci.yml +47 -27
  4. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/.github/workflows/daily-tests.yml +36 -37
  5. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/.github/workflows/release.yml +10 -3
  6. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/.github/workflows/sdk-backward-compat.yml +12 -8
  7. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/.gitignore +3 -0
  8. pdfdancer_client_python-3.0.2/MANIFEST.in +1 -0
  9. pdfdancer_client_python-3.0.2/Makefile +80 -0
  10. {pdfdancer_client_python-0.3.14/src/pdfdancer_client_python.egg-info → pdfdancer_client_python-3.0.2}/PKG-INFO +194 -136
  11. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/README.md +192 -134
  12. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/docs/capabilities/CLEAR_CLIPPING.md +2 -4
  13. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/pyproject.toml +2 -6
  14. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer/__init__.py +97 -22
  15. pdfdancer_client_python-3.0.2/src/pdfdancer/_runtime_version.py +30 -0
  16. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer/_version.py +2 -2
  17. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer/image_builder.py +23 -3
  18. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer/models.py +240 -470
  19. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer/page_builder.py +6 -17
  20. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer/path_builder.py +127 -6
  21. pdfdancer_client_python-0.3.14/src/pdfdancer/pdfdancer_v1.py → pdfdancer_client_python-3.0.2/src/pdfdancer/pdfdancer_v2.py +934 -1308
  22. pdfdancer_client_python-3.0.2/src/pdfdancer/text_editing.py +1472 -0
  23. pdfdancer_client_python-3.0.2/src/pdfdancer/types.py +536 -0
  24. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2/src/pdfdancer_client_python.egg-info}/PKG-INFO +194 -136
  25. pdfdancer_client_python-3.0.2/src/pdfdancer_client_python.egg-info/SOURCES.txt +41 -0
  26. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer_client_python.egg-info/requires.txt +1 -1
  27. pdfdancer_client_python-0.3.14/.claude/commands/discuss.md +0 -4
  28. pdfdancer_client_python-0.3.14/.claude/commands/implement-new-api-features.md +0 -8
  29. pdfdancer_client_python-0.3.14/CLAUDE.md +0 -207
  30. pdfdancer_client_python-0.3.14/src/pdfdancer/_runtime_version.py +0 -25
  31. pdfdancer_client_python-0.3.14/src/pdfdancer/paragraph_builder.py +0 -554
  32. pdfdancer_client_python-0.3.14/src/pdfdancer/text_line_builder.py +0 -290
  33. pdfdancer_client_python-0.3.14/src/pdfdancer/types.py +0 -841
  34. pdfdancer_client_python-0.3.14/src/pdfdancer_client_python.egg-info/SOURCES.txt +0 -92
  35. pdfdancer_client_python-0.3.14/tests/__init__.py +0 -1
  36. pdfdancer_client_python-0.3.14/tests/conftest.py +0 -31
  37. pdfdancer_client_python-0.3.14/tests/e2e/__init__.py +0 -61
  38. pdfdancer_client_python-0.3.14/tests/e2e/pdf_assertions.py +0 -1784
  39. pdfdancer_client_python-0.3.14/tests/e2e/test_acroform.py +0 -100
  40. pdfdancer_client_python-0.3.14/tests/e2e/test_bezier_builder.py +0 -283
  41. pdfdancer_client_python-0.3.14/tests/e2e/test_clipping.py +0 -323
  42. pdfdancer_client_python-0.3.14/tests/e2e/test_context_manager.py +0 -439
  43. pdfdancer_client_python-0.3.14/tests/e2e/test_form_x_objects.py +0 -38
  44. pdfdancer_client_python-0.3.14/tests/e2e/test_image.py +0 -133
  45. pdfdancer_client_python-0.3.14/tests/e2e/test_image_transform.py +0 -684
  46. pdfdancer_client_python-0.3.14/tests/e2e/test_line.py +0 -140
  47. pdfdancer_client_python-0.3.14/tests/e2e/test_line_builder.py +0 -255
  48. pdfdancer_client_python-0.3.14/tests/e2e/test_new_pdf.py +0 -143
  49. pdfdancer_client_python-0.3.14/tests/e2e/test_page.py +0 -167
  50. pdfdancer_client_python-0.3.14/tests/e2e/test_paragraph.py +0 -717
  51. pdfdancer_client_python-0.3.14/tests/e2e/test_path.py +0 -128
  52. pdfdancer_client_python-0.3.14/tests/e2e/test_path_builder.py +0 -403
  53. pdfdancer_client_python-0.3.14/tests/e2e/test_path_builder_rectangle.py +0 -515
  54. pdfdancer_client_python-0.3.14/tests/e2e/test_path_comprehensive.py +0 -552
  55. pdfdancer_client_python-0.3.14/tests/e2e/test_path_group.py +0 -244
  56. pdfdancer_client_python-0.3.14/tests/e2e/test_pdfdancer.py +0 -55
  57. pdfdancer_client_python-0.3.14/tests/e2e/test_positioning.py +0 -2
  58. pdfdancer_client_python-0.3.14/tests/e2e/test_rectangle_builder.py +0 -449
  59. pdfdancer_client_python-0.3.14/tests/e2e/test_redact.py +0 -290
  60. pdfdancer_client_python-0.3.14/tests/e2e/test_singular_selection.py +0 -328
  61. pdfdancer_client_python-0.3.14/tests/e2e/test_snapshot.py +0 -295
  62. pdfdancer_client_python-0.3.14/tests/e2e/test_template_replace.py +0 -276
  63. pdfdancer_client_python-0.3.14/tests/e2e/test_template_replace_reflow_presets.py +0 -73
  64. pdfdancer_client_python-0.3.14/tests/e2e/test_text_line_edit.py +0 -270
  65. pdfdancer_client_python-0.3.14/tests/fixtures/Asimovian-Regular.ttf +0 -0
  66. pdfdancer_client_python-0.3.14/tests/fixtures/DancingScript-Regular.ttf +0 -0
  67. pdfdancer_client_python-0.3.14/tests/fixtures/Empty.pdf +0 -0
  68. pdfdancer_client_python-0.3.14/tests/fixtures/JetBrainsMono-Regular.ttf +0 -0
  69. pdfdancer_client_python-0.3.14/tests/fixtures/Roboto-Regular.ttf +0 -0
  70. pdfdancer_client_python-0.3.14/tests/fixtures/Showcase.pdf +0 -0
  71. pdfdancer_client_python-0.3.14/tests/fixtures/basic-paths.pdf +0 -0
  72. pdfdancer_client_python-0.3.14/tests/fixtures/form-xobject-example.pdf +0 -0
  73. pdfdancer_client_python-0.3.14/tests/fixtures/invisible-content-clipping-test.pdf +0 -0
  74. pdfdancer_client_python-0.3.14/tests/fixtures/logo-80.png +0 -0
  75. pdfdancer_client_python-0.3.14/tests/fixtures/mixed-form-types.pdf +0 -0
  76. pdfdancer_client_python-0.3.14/tests/fixtures/multi-paragraph-test.pdf +0 -0
  77. pdfdancer_client_python-0.3.14/tests/test_anonymous_token.py +0 -222
  78. pdfdancer_client_python-0.3.14/tests/test_fingerprint.py +0 -120
  79. pdfdancer_client_python-0.3.14/tests/test_models.py +0 -371
  80. pdfdancer_client_python-0.3.14/tests/test_openapi_compliance.py +0 -129
  81. pdfdancer_client_python-0.3.14/tests/test_path_models.py +0 -256
  82. pdfdancer_client_python-0.3.14/tests/test_pdf_object_equality.py +0 -320
  83. pdfdancer_client_python-0.3.14/tests/test_rate_limit.py +0 -82
  84. pdfdancer_client_python-0.3.14/tests/test_standard_fonts.py +0 -174
  85. pdfdancer_client_python-0.3.14/tests/test_version.py +0 -6
  86. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/.flake8 +0 -0
  87. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/.gitmodules +0 -0
  88. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/LICENSE +0 -0
  89. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/NOTICE +0 -0
  90. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/TODO.md +0 -0
  91. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/check.py +0 -0
  92. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/docs/capabilities/.gitkeep +0 -0
  93. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/media/logo-orange-512h.webp +0 -0
  94. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/media/logo-orange-60h.webp +0 -0
  95. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/media/logo-silver-512h.webp +0 -0
  96. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/media/logo-silver-60h.webp +0 -0
  97. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/setup.cfg +0 -0
  98. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer/exceptions.py +0 -0
  99. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer/fingerprint.py +0 -0
  100. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer_client_python.egg-info/dependency_links.txt +0 -0
  101. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/src/pdfdancer_client_python.egg-info/top_level.txt +0 -0
  102. {pdfdancer_client_python-0.3.14 → pdfdancer_client_python-3.0.2}/test.sh +0 -0
@@ -0,0 +1,10 @@
1
+ check = "make check"
2
+ idle_seconds = 60
3
+ snapshot_mode = "both"
4
+ commit_mode = "checkpoint"
5
+ msg_source_cmd = 'gommit -A -n --diff-base "$AUTOSNAP_DIFF_BASE"'
6
+ log_max_bytes = 1048576
7
+
8
+ [watch]
9
+ mode = "recursive"
10
+ poll_interval = "5s"
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: monthly
@@ -9,8 +9,8 @@ on:
9
9
 
10
10
  jobs:
11
11
  test:
12
- # Quick minimal test on non-main branches
13
- if: github.ref != 'refs/heads/main'
12
+ # Run the minimal matrix for automatic non-main events.
13
+ if: github.event_name != 'workflow_dispatch' && github.ref != 'refs/heads/main'
14
14
  runs-on: ubuntu-latest
15
15
  permissions:
16
16
  contents: read
@@ -23,15 +23,15 @@ jobs:
23
23
  python-version: [ '3.12' ]
24
24
 
25
25
  steps:
26
- - uses: actions/checkout@v4
26
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
27
27
  with:
28
28
  submodules: true
29
29
 
30
30
  - name: Resolve API base URL
31
31
  id: resolve-api-base-url
32
- uses: actions/github-script@v7
32
+ uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
33
33
  with:
34
- github-token: ${{ secrets.PROPAGATE_TOKEN }}
34
+ github-token: ${{ secrets.PROPAGATE_TOKEN || github.token }}
35
35
  script: |
36
36
  const fallbackUrl = 'https://api-staging.pdfdancer.com';
37
37
  const pr = context.payload.pull_request;
@@ -74,7 +74,7 @@ jobs:
74
74
  core.setOutput('base_url', urlMatch[1]);
75
75
 
76
76
  - name: Set up Python ${{ matrix.python-version }}
77
- uses: actions/setup-python@v5
77
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
78
78
  with:
79
79
  python-version: ${{ matrix.python-version }}
80
80
 
@@ -92,9 +92,11 @@ jobs:
92
92
 
93
93
  - name: Run tests
94
94
  run: |
95
- PDFDANCER_BASE_URL=${{ steps.resolve-api-base-url.outputs.base_url }} \
96
- PDFDANCER_API_TOKEN=42 \
97
- venv/bin/python -m pytest tests/ -v --maxfail=3
95
+ mkdir -p test-results
96
+ venv/bin/python -m pytest tests/ -v --maxfail=3 --junitxml=test-results/junit.xml
97
+ env:
98
+ PDFDANCER_BASE_URL: ${{ steps.resolve-api-base-url.outputs.base_url }}
99
+ PDFDANCER_API_TOKEN: 42
98
100
 
99
101
  - name: Build distribution packages
100
102
  run: venv/bin/python -m build
@@ -102,10 +104,21 @@ jobs:
102
104
  - name: Validate packages
103
105
  run: venv/bin/python -m twine check dist/*
104
106
 
107
+ - name: Upload test results
108
+ if: failure()
109
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
110
+ with:
111
+ name: test-results-python-${{ matrix.python-version }}
112
+ path: |
113
+ test-results/
114
+ .pytest_cache/
115
+ if-no-files-found: ignore
116
+ retention-days: 7
117
+
105
118
 
106
119
  test-full-matrix:
107
- # Full matrix only on main
108
- if: github.ref == 'refs/heads/main'
120
+ # Run the full matrix on main and for every manual dispatch.
121
+ if: github.event_name == 'workflow_dispatch' || github.ref == 'refs/heads/main'
109
122
  runs-on: ${{ matrix.os }}
110
123
  permissions:
111
124
  contents: read
@@ -119,20 +132,12 @@ jobs:
119
132
  python-version: [ '3.10', '3.11', '3.12', '3.13' ]
120
133
 
121
134
  steps:
122
- - uses: actions/checkout@v4
135
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
123
136
  with:
124
137
  submodules: true
125
138
 
126
- - name: Resolve API base URL
127
- id: resolve-api-base-url
128
- uses: actions/github-script@v7
129
- with:
130
- github-token: ${{ secrets.PROPAGATE_TOKEN }}
131
- script: |
132
- core.setOutput('base_url', 'https://api-staging.pdfdancer.com');
133
-
134
139
  - name: Set up Python ${{ matrix.python-version }}
135
- uses: actions/setup-python@v5
140
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
136
141
  with:
137
142
  python-version: ${{ matrix.python-version }}
138
143
 
@@ -154,9 +159,11 @@ jobs:
154
159
  - name: Run tests (Unix)
155
160
  if: runner.os != 'Windows'
156
161
  run: |
157
- PDFDANCER_BASE_URL=${{ steps.resolve-api-base-url.outputs.base_url }} \
158
- PDFDANCER_API_TOKEN=42 \
159
- venv/bin/python -m pytest tests/ -v --maxfail=3
162
+ mkdir -p test-results
163
+ venv/bin/python -m pytest tests/ -v --maxfail=3 --junitxml=test-results/junit.xml
164
+ env:
165
+ PDFDANCER_BASE_URL: https://api-staging.pdfdancer.com
166
+ PDFDANCER_API_TOKEN: 42
160
167
 
161
168
  - name: Build & Validate (Unix)
162
169
  if: runner.os != 'Windows'
@@ -185,9 +192,11 @@ jobs:
185
192
  if: runner.os == 'Windows'
186
193
  shell: cmd
187
194
  run: |
188
- set PDFDANCER_BASE_URL=${{ steps.resolve-api-base-url.outputs.base_url }}
189
- set PDFDANCER_API_TOKEN=42
190
- venv\Scripts\python -m pytest tests/ -v --maxfail=3
195
+ if not exist test-results mkdir test-results
196
+ venv\Scripts\python -m pytest tests/ -v --maxfail=3 --junitxml=test-results/junit.xml
197
+ env:
198
+ PDFDANCER_BASE_URL: https://api-staging.pdfdancer.com
199
+ PDFDANCER_API_TOKEN: 42
191
200
 
192
201
  - name: Build & Validate (Windows)
193
202
  if: runner.os == 'Windows'
@@ -195,3 +204,14 @@ jobs:
195
204
  run: |
196
205
  venv\Scripts\python -m build
197
206
  venv\Scripts\python -m twine check dist/*
207
+
208
+ - name: Upload test results
209
+ if: failure()
210
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
211
+ with:
212
+ name: test-results-${{ matrix.os }}-python-${{ matrix.python-version }}
213
+ path: |
214
+ test-results/
215
+ .pytest_cache/
216
+ if-no-files-found: ignore
217
+ retention-days: 7
@@ -2,12 +2,14 @@ name: Daily Tests
2
2
 
3
3
  on:
4
4
  schedule:
5
- # Run daily at 9:00 PM UTC
5
+ # Run daily at 10:40 UTC
6
6
  - cron: '40 10 * * *'
7
7
  workflow_dispatch: # Allow manual triggering
8
8
 
9
9
  jobs:
10
10
  daily-test:
11
+ permissions:
12
+ contents: read
11
13
  runs-on: ${{ matrix.os }}
12
14
  strategy:
13
15
  fail-fast: false
@@ -17,12 +19,12 @@ jobs:
17
19
  python-version: [ '3.10', '3.11', '3.12', '3.13' ]
18
20
 
19
21
  steps:
20
- - uses: actions/checkout@v4
22
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
21
23
  with:
22
24
  submodules: true
23
25
 
24
26
  - name: Set up Python ${{ matrix.python-version }}
25
- uses: actions/setup-python@v5
27
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
26
28
  with:
27
29
  python-version: ${{ matrix.python-version }}
28
30
 
@@ -44,9 +46,11 @@ jobs:
44
46
  - name: Run tests (Unix)
45
47
  if: runner.os != 'Windows'
46
48
  run: |
47
- PDFDANCER_BASE_URL=https://api-staging.pdfdancer.com \
48
- PDFDANCER_TOKEN=42 \
49
- venv/bin/python -m pytest tests/ -v --maxfail=3
49
+ mkdir -p test-results
50
+ venv/bin/python -m pytest tests/ -v --maxfail=3 --junitxml=test-results/junit.xml
51
+ env:
52
+ PDFDANCER_BASE_URL: https://api-staging.pdfdancer.com
53
+ PDFDANCER_API_TOKEN: 42
50
54
 
51
55
  - name: Build & Validate (Unix)
52
56
  if: runner.os != 'Windows'
@@ -75,9 +79,11 @@ jobs:
75
79
  if: runner.os == 'Windows'
76
80
  shell: cmd
77
81
  run: |
78
- set PDFDANCER_BASE_URL=https://api-staging.pdfdancer.com
79
- set PDFDANCER_TOKEN=42
80
- venv\Scripts\python -m pytest tests/ -v --maxfail=3
82
+ if not exist test-results mkdir test-results
83
+ venv\Scripts\python -m pytest tests/ -v --maxfail=3 --junitxml=test-results/junit.xml
84
+ env:
85
+ PDFDANCER_BASE_URL: https://api-staging.pdfdancer.com
86
+ PDFDANCER_API_TOKEN: 42
81
87
 
82
88
  - name: Build & Validate (Windows)
83
89
  if: runner.os == 'Windows'
@@ -86,34 +92,27 @@ jobs:
86
92
  venv\Scripts\python -m build
87
93
  venv\Scripts\python -m twine check dist/*
88
94
 
89
- notify-on-failure:
95
+ - name: Upload test results
96
+ if: failure()
97
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
98
+ with:
99
+ name: test-results-${{ matrix.os }}-python-${{ matrix.python-version }}
100
+ path: |
101
+ test-results/
102
+ .pytest_cache/
103
+ if-no-files-found: ignore
104
+ retention-days: 7
105
+
106
+ notify:
90
107
  needs: daily-test
91
108
  runs-on: ubuntu-latest
92
- if: failure()
109
+ if: always() && needs.daily-test.result == 'failure'
110
+ permissions:
111
+ contents: read
93
112
  steps:
94
- - name: Create issue on failure
95
- uses: actions/github-script@v7
96
- with:
97
- script: |
98
- const title = `Daily Tests Failed - ${new Date().toISOString().split('T')[0]}`;
99
- const body = `The daily test run has failed. Please check the workflow run for details.\n\n[Workflow Run](${context.payload.repository.html_url}/actions/runs/${context.runId})`;
100
-
101
- // Check if an issue already exists
102
- const issues = await github.rest.issues.listForRepo({
103
- owner: context.repo.owner,
104
- repo: context.repo.repo,
105
- state: 'open',
106
- labels: 'daily-test-failure'
107
- });
108
-
109
- const existingIssue = issues.data.find(issue => issue.title === title);
110
-
111
- if (!existingIssue) {
112
- await github.rest.issues.create({
113
- owner: context.repo.owner,
114
- repo: context.repo.repo,
115
- title: title,
116
- body: body,
117
- labels: ['daily-test-failure', 'automated']
118
- });
119
- }
113
+ - name: Summarize failure
114
+ run: |
115
+ echo "## Daily Tests Failed" >> "$GITHUB_STEP_SUMMARY"
116
+ echo "" >> "$GITHUB_STEP_SUMMARY"
117
+ echo "Python SDK daily tests failed on $(date -u +%F)." >> "$GITHUB_STEP_SUMMARY"
118
+ echo "[Open workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> "$GITHUB_STEP_SUMMARY"
@@ -6,19 +6,20 @@ on:
6
6
  - 'v*'
7
7
 
8
8
  permissions:
9
+ contents: write
9
10
  id-token: write
10
11
 
11
12
  jobs:
12
13
  release:
13
14
  runs-on: ubuntu-latest
14
15
  steps:
15
- - uses: actions/checkout@v4
16
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
16
17
  with:
17
18
  fetch-depth: 0
18
19
  submodules: true
19
20
 
20
21
  - name: Set up Python 3.12
21
- uses: actions/setup-python@v5
22
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
22
23
  with:
23
24
  python-version: '3.12'
24
25
 
@@ -46,4 +47,10 @@ jobs:
46
47
  run: python -m twine check dist/*
47
48
 
48
49
  - name: Publish to PyPI
49
- uses: pypa/gh-action-pypi-publish@release/v1
50
+ uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
51
+
52
+ - name: Create GitHub Release
53
+ uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
54
+ with:
55
+ generate_release_notes: true
56
+ files: dist/*
@@ -11,11 +11,14 @@ on:
11
11
  required: true
12
12
  type: string
13
13
  sdk_token:
14
- description: 'API token for testing'
14
+ description: 'Non-secret test token; never enter production credentials'
15
15
  required: true
16
16
  type: string
17
17
  default: '42'
18
18
 
19
+ permissions:
20
+ contents: read
21
+
19
22
  jobs:
20
23
  get-tags:
21
24
  runs-on: ubuntu-latest
@@ -47,14 +50,15 @@ jobs:
47
50
 
48
51
  steps:
49
52
  - name: Checkout SDK at ${{ matrix.tag }}
50
- uses: actions/checkout@v4
53
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
51
54
  with:
52
55
  repository: MenschMachine/pdfdancer-client-python
53
56
  ref: ${{ matrix.tag }}
54
57
  path: sdk
58
+ submodules: true
55
59
 
56
60
  - name: Set up Python
57
- uses: actions/setup-python@v5
61
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
58
62
  with:
59
63
  python-version: '3.12'
60
64
 
@@ -69,20 +73,20 @@ jobs:
69
73
  - name: Run e2e tests
70
74
  working-directory: sdk
71
75
  run: |
72
- PDFDANCER_BASE_URL=${{ github.event.client_payload.api_url || inputs.api_url }} \
73
- PDFDANCER_API_TOKEN=${{ github.event.client_payload.sdk_token || inputs.sdk_token }} \
74
76
  ../venv/bin/python -m pytest -v -x \
75
77
  -k "not test_redact_multiple_paths and not test_context_manager_vs_manual_apply" \
76
78
  --junitxml=test-results.xml
77
79
  env:
78
- PYTHONWARNINGS: "ignore:Unverified HTTPS request"
80
+ PDFDANCER_BASE_URL: ${{ github.event.client_payload.api_url || inputs.api_url }}
81
+ PDFDANCER_API_TOKEN: ${{ github.event.client_payload.sdk_token || inputs.sdk_token }}
79
82
 
80
83
  - name: Upload test results
81
84
  if: failure()
82
- uses: actions/upload-artifact@v4
85
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
83
86
  with:
84
87
  name: test-results-${{ matrix.tag }}
85
88
  path: |
86
89
  sdk/test-results.xml
87
90
  sdk/.pytest_cache/
88
- retention-days: 7
91
+ if-no-files-found: ignore
92
+ retention-days: 7
@@ -21,3 +21,6 @@ __pycache__/
21
21
  .env
22
22
  .propagate*md
23
23
  /.last-message.txt
24
+
25
+ # Auto-generated by setuptools_scm
26
+ src/pdfdancer/_version.py
@@ -0,0 +1 @@
1
+ prune tests
@@ -0,0 +1,80 @@
1
+ BASE_PYTHON ?= python
2
+ VENV ?= venv
3
+ TEST_PATH ?= tests
4
+ PYTEST_ARGS ?= -v
5
+
6
+ ifeq ($(OS),Windows_NT)
7
+ VENV_PYTHON := $(VENV)/Scripts/python.exe
8
+ else
9
+ VENV_PYTHON := $(VENV)/bin/python
10
+ endif
11
+
12
+ PYTHON ?= $(VENV_PYTHON)
13
+
14
+ CODE_DIRS := src tests
15
+ FIXTURE_DIR := tests/fixtures
16
+ UNIT_TEST_ARGS := --ignore=tests/e2e
17
+
18
+ .DEFAULT_GOAL := help
19
+
20
+ .PHONY: help venv install install-dev format format-check lint typecheck quality \
21
+ test test-unit test-e2e coverage check build check-dist package clean
22
+
23
+ help: ## Show available targets and configurable variables
24
+ @awk 'BEGIN {FS = ":.*## "; printf "Usage: make <target> [BASE_PYTHON=python] [VENV=venv] [PYTHON=<venv-python>] [TEST_PATH=tests] [PYTEST_ARGS=\"-v\"]\n\nTargets:\n"} /^[a-zA-Z0-9_-]+:.*## / {printf " %-14s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
25
+
26
+ venv: $(VENV_PYTHON) ## Create the project virtual environment
27
+
28
+ $(VENV_PYTHON):
29
+ $(BASE_PYTHON) -m venv $(VENV)
30
+ $(VENV_PYTHON) -m pip install --upgrade pip
31
+
32
+ install: venv ## Install the package in editable mode
33
+ $(PYTHON) -m pip install -e .
34
+
35
+ install-dev: venv ## Install the package and development dependencies in editable mode
36
+ $(PYTHON) -m pip install -e ".[dev]"
37
+
38
+ format: ## Format source code and tests with Black and isort
39
+ $(PYTHON) -m black --extend-exclude '(^|/)tests/fixtures/' $(CODE_DIRS)
40
+ $(PYTHON) -m isort --skip $(FIXTURE_DIR) $(CODE_DIRS)
41
+
42
+ format-check: ## Check formatting without changing files
43
+ $(PYTHON) -m black --check --extend-exclude '(^|/)tests/fixtures/' $(CODE_DIRS)
44
+ $(PYTHON) -m isort --check-only --skip $(FIXTURE_DIR) $(CODE_DIRS)
45
+
46
+ lint: ## Lint source code and tests with Flake8
47
+ $(PYTHON) -m flake8 --exclude=$(FIXTURE_DIR) $(CODE_DIRS)
48
+
49
+ typecheck: ## Type-check the package with mypy
50
+ $(PYTHON) -m mypy src
51
+
52
+ quality: format-check lint typecheck ## Run all non-mutating code-quality checks
53
+
54
+ test: ## Run all tests; override TEST_PATH or PYTEST_ARGS as needed
55
+ $(PYTHON) -m pytest $(TEST_PATH) $(PYTEST_ARGS)
56
+
57
+ test-unit: ## Run tests that do not require the PDFDancer API
58
+ $(PYTHON) -m pytest tests $(UNIT_TEST_ARGS) $(PYTEST_ARGS)
59
+
60
+ test-e2e: ## Run API-dependent end-to-end tests
61
+ $(PYTHON) -m pytest tests/e2e $(PYTEST_ARGS)
62
+
63
+ coverage: ## Run all tests and report package coverage
64
+ $(PYTHON) -m pytest $(TEST_PATH) $(PYTEST_ARGS) --cov=pdfdancer --cov-report=term-missing
65
+
66
+ check: quality test-unit ## Run the local pre-commit checks
67
+
68
+ build: ## Build the wheel and source distribution
69
+ $(PYTHON) -m build
70
+
71
+ check-dist: ## Validate existing distribution artifacts with Twine
72
+ $(PYTHON) -m twine check dist/*
73
+
74
+ package: clean ## Clean, build, and validate distribution artifacts
75
+ $(MAKE) build
76
+ $(MAKE) check-dist
77
+
78
+ clean: ## Remove generated build, test, coverage, and Python cache artifacts
79
+ $(RM) -r build dist .pytest_cache .mypy_cache .coverage htmlcov src/*.egg-info
80
+ find src tests -type d -name __pycache__ -prune -exec $(RM) -r {} +