pdfdancer-client-python 0.2.21__tar.gz → 0.2.22__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 (74) hide show
  1. pdfdancer_client_python-0.2.22/.flake8 +4 -0
  2. pdfdancer_client_python-0.2.22/.github/workflows/ci.yml +129 -0
  3. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/.gitignore +7 -0
  4. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/PKG-INFO +1 -1
  5. pdfdancer_client_python-0.2.22/check.py +4 -0
  6. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/pyproject.toml +8 -1
  7. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/__init__.py +34 -9
  8. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/exceptions.py +8 -1
  9. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/fingerprint.py +10 -10
  10. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/image_builder.py +13 -7
  11. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/models.py +159 -81
  12. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/page_builder.py +23 -16
  13. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/paragraph_builder.py +100 -48
  14. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/path_builder.py +82 -67
  15. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/pdfdancer_v1.py +1144 -476
  16. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer/types.py +116 -65
  17. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer_client_python.egg-info/PKG-INFO +1 -1
  18. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer_client_python.egg-info/SOURCES.txt +3 -0
  19. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/test.sh +230 -90
  20. pdfdancer_client_python-0.2.22/tests/__init__.py +1 -0
  21. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/conftest.py +1 -1
  22. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/__init__.py +14 -10
  23. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/pdf_assertions.py +277 -133
  24. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_acroform.py +1 -3
  25. pdfdancer_client_python-0.2.22/tests/e2e/test_bezier_builder.py +283 -0
  26. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_context_manager.py +131 -75
  27. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_form_x_objects.py +1 -4
  28. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_image.py +4 -18
  29. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_line.py +33 -13
  30. pdfdancer_client_python-0.2.22/tests/e2e/test_line_builder.py +255 -0
  31. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_new_pdf.py +31 -31
  32. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_page.py +15 -35
  33. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_paragraph.py +168 -110
  34. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_path.py +2 -9
  35. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_path_builder.py +118 -164
  36. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_path_builder_rectangle.py +123 -176
  37. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_path_comprehensive.py +77 -84
  38. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_pdfdancer.py +5 -3
  39. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_rectangle_builder.py +106 -161
  40. pdfdancer_client_python-0.2.22/tests/e2e/test_singular_selection.py +327 -0
  41. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_snapshot.py +83 -47
  42. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/test_anonymous_token.py +71 -61
  43. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/test_fingerprint.py +25 -19
  44. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/test_models.py +20 -5
  45. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/test_openapi_compliance.py +29 -8
  46. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/test_path_models.py +18 -37
  47. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/test_pdf_object_equality.py +70 -23
  48. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/test_standard_fonts.py +14 -4
  49. pdfdancer_client_python-0.2.21/.github/workflows/ci.yml +0 -41
  50. pdfdancer_client_python-0.2.21/tests/__init__.py +0 -1
  51. pdfdancer_client_python-0.2.21/tests/e2e/test_bezier_builder.py +0 -251
  52. pdfdancer_client_python-0.2.21/tests/e2e/test_line_builder.py +0 -255
  53. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/.claude/commands/discuss.md +0 -0
  54. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/CLAUDE.md +0 -0
  55. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/LICENSE +0 -0
  56. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/NOTICE +0 -0
  57. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/README.md +0 -0
  58. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/TODO.md +0 -0
  59. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/docs/openapi.yml +0 -0
  60. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/release.py +0 -0
  61. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/setup.cfg +0 -0
  62. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer_client_python.egg-info/dependency_links.txt +0 -0
  63. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer_client_python.egg-info/requires.txt +0 -0
  64. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/src/pdfdancer_client_python.egg-info/top_level.txt +0 -0
  65. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/e2e/test_positioning.py +0 -0
  66. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/fixtures/DancingScript-Regular.ttf +0 -0
  67. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/fixtures/Empty.pdf +0 -0
  68. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/fixtures/JetBrainsMono-Regular.ttf +0 -0
  69. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/fixtures/Showcase.pdf +0 -0
  70. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/fixtures/basic-paths.pdf +0 -0
  71. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/fixtures/form-xobject-example.pdf +0 -0
  72. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/fixtures/logo-80.png +0 -0
  73. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/tests/fixtures/mixed-form-types.pdf +0 -0
  74. {pdfdancer_client_python-0.2.21 → pdfdancer_client_python-0.2.22}/update-api-spec.sh +0 -0
@@ -0,0 +1,4 @@
1
+ [flake8]
2
+ max-line-length = 88
3
+ extend-ignore = E203, W503, E501
4
+ exclude = venv, build, dist, .git, __pycache__, *.egg-info
@@ -0,0 +1,129 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, staging, develop, development, dev ]
6
+ pull_request:
7
+ branches: [ main, staging, develop, development, dev ]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ test:
12
+ # Quick minimal test on non-main branches
13
+ if: github.ref != 'refs/heads/main'
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ python-version: [ '3.12' ]
19
+
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Set up Python ${{ matrix.python-version }}
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+
28
+ - name: Create virtual environment
29
+ run: python -m venv venv
30
+
31
+ - name: Install dependencies
32
+ run: |
33
+ venv/bin/pip install --upgrade pip
34
+ venv/bin/pip install -e ".[dev]"
35
+
36
+ - name: Run linter
37
+ run: |
38
+ venv/bin/python -m flake8 src/
39
+
40
+ - name: Run tests
41
+ run: |
42
+ PDFDANCER_BASE_URL=https://api-staging.pdfdancer.com \
43
+ PDFDANCER_TOKEN=42 \
44
+ venv/bin/python -m pytest tests/ -v --maxfail=3
45
+
46
+ - name: Build distribution packages
47
+ run: venv/bin/python -m build
48
+
49
+ - name: Validate packages
50
+ run: venv/bin/python -m twine check dist/*
51
+
52
+
53
+ test-full-matrix:
54
+ # Full matrix only on main
55
+ if: github.ref == 'refs/heads/main'
56
+ runs-on: ${{ matrix.os }}
57
+ strategy:
58
+ fail-fast: false
59
+ matrix:
60
+ os: [ ubuntu-latest, windows-latest ]
61
+ python-version: [ '3.10', '3.11', '3.12', '3.13' ]
62
+
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+
66
+ - name: Set up Python ${{ matrix.python-version }}
67
+ uses: actions/setup-python@v5
68
+ with:
69
+ python-version: ${{ matrix.python-version }}
70
+
71
+ - name: Create virtual environment (Unix)
72
+ if: runner.os != 'Windows'
73
+ run: python -m venv venv
74
+
75
+ - name: Install dependencies (Unix)
76
+ if: runner.os != 'Windows'
77
+ run: |
78
+ venv/bin/pip install --upgrade pip
79
+ venv/bin/pip install -e ".[dev]"
80
+
81
+ - name: Run linter (Unix)
82
+ if: runner.os != 'Windows'
83
+ run: |
84
+ venv/bin/python -m flake8 src/
85
+
86
+ - name: Run tests (Unix)
87
+ if: runner.os != 'Windows'
88
+ run: |
89
+ PDFDANCER_BASE_URL=https://api-staging.pdfdancer.com \
90
+ PDFDANCER_TOKEN=42 \
91
+ venv/bin/python -m pytest tests/ -v --maxfail=3
92
+
93
+ - name: Build & Validate (Unix)
94
+ if: runner.os != 'Windows'
95
+ run: |
96
+ venv/bin/python -m build
97
+ venv/bin/python -m twine check dist/*
98
+
99
+ - name: Create virtual environment (Windows)
100
+ if: runner.os == 'Windows'
101
+ shell: cmd
102
+ run: python -m venv venv
103
+
104
+ - name: Install dependencies (Windows)
105
+ if: runner.os == 'Windows'
106
+ shell: cmd
107
+ run: |
108
+ venv\Scripts\pip install --upgrade pip
109
+ venv\Scripts\pip install -e ".[dev]"
110
+
111
+ - name: Run linter (Windows)
112
+ if: runner.os == 'Windows'
113
+ run: |
114
+ venv\Scripts\python -m flake8 src/
115
+
116
+ - name: Run tests (Windows)
117
+ if: runner.os == 'Windows'
118
+ shell: cmd
119
+ run: |
120
+ set PDFDANCER_BASE_URL=https://api-staging.pdfdancer.com
121
+ set PDFDANCER_TOKEN=42
122
+ venv\Scripts\python -m pytest tests/ -v --maxfail=3
123
+
124
+ - name: Build & Validate (Windows)
125
+ if: runner.os == 'Windows'
126
+ shell: cmd
127
+ run: |
128
+ venv\Scripts\python -m build
129
+ venv\Scripts\python -m twine check dist/*
@@ -9,3 +9,10 @@ src/pdfdancer_client_python.egg-info
9
9
  /logs/
10
10
  /venv
11
11
  /venv-*
12
+
13
+ # Python cache
14
+ __pycache__/
15
+ *.py[cod]
16
+ *$py.class
17
+ *.so
18
+ .Python
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdfdancer-client-python
3
- Version: 0.2.21
3
+ Version: 0.2.22
4
4
  Summary: Python client for PDFDancer API
5
5
  Author-email: "The Famous Cat Ltd." <hi@thefamouscat.com>
6
6
  License:
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+
3
+
4
+ isort src/ tests/ && black src/ tests/ && flake8 src/
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pdfdancer-client-python"
7
- version = "0.2.21"
7
+ version = "0.2.22"
8
8
  description = "Python client for PDFDancer API"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -48,6 +48,9 @@ Repository = "https://github.com/MenschMachine/pdfdancer-client-python"
48
48
  [tool.setuptools.packages.find]
49
49
  where = ["src"]
50
50
 
51
+ [tool.isort]
52
+ profile = "black"
53
+
51
54
  [tool.black]
52
55
  line-length = 88
53
56
  target-version = ['py310']
@@ -55,3 +58,7 @@ target-version = ['py310']
55
58
  [tool.mypy]
56
59
  python_version = "3.10"
57
60
  strict = true
61
+
62
+ [tool.poetry.scripts]
63
+ lint = "bash -c 'flake8 src && mypy src'"
64
+ format = "bash -c 'black src && isort src'"
@@ -7,17 +7,41 @@ mirrors the Java client structure and functionality.
7
7
  """
8
8
 
9
9
  from .exceptions import (
10
- PdfDancerException, FontNotFoundException, ValidationException,
11
- HttpClientException, SessionException
10
+ FontNotFoundException,
11
+ HttpClientException,
12
+ PdfDancerException,
13
+ SessionException,
14
+ ValidationException,
12
15
  )
13
16
  from .models import (
14
- ObjectRef, Position, ObjectType, Font, Color, Image, BoundingRect, Paragraph, FormFieldRef, TextObjectRef,
15
- PageRef, PositionMode, ShapeType, Point, StandardFonts, PageSize, Orientation, TextStatus, FontRecommendation,
16
- FontType, PathSegment, Line, Bezier, Path
17
+ Bezier,
18
+ BoundingRect,
19
+ Color,
20
+ Font,
21
+ FontRecommendation,
22
+ FontType,
23
+ FormFieldRef,
24
+ Image,
25
+ Line,
26
+ ObjectRef,
27
+ ObjectType,
28
+ Orientation,
29
+ PageRef,
30
+ PageSize,
31
+ Paragraph,
32
+ Path,
33
+ PathSegment,
34
+ Point,
35
+ Position,
36
+ PositionMode,
37
+ ShapeType,
38
+ StandardFonts,
39
+ TextObjectRef,
40
+ TextStatus,
17
41
  )
18
- from .paragraph_builder import ParagraphBuilder
19
42
  from .page_builder import PageBuilder
20
- from .path_builder import PathBuilder, LineBuilder, BezierBuilder
43
+ from .paragraph_builder import ParagraphBuilder
44
+ from .path_builder import BezierBuilder, LineBuilder, PathBuilder
21
45
 
22
46
  __version__ = "1.0.0"
23
47
  __all__ = [
@@ -56,11 +80,12 @@ __all__ = [
56
80
  "ValidationException",
57
81
  "HttpClientException",
58
82
  "SessionException",
59
- "set_ssl_verify"
83
+ "set_ssl_verify",
60
84
  ]
61
85
 
62
- from .pdfdancer_v1 import PDFDancer
63
86
  from . import pdfdancer_v1
87
+ from .pdfdancer_v1 import PDFDancer
88
+
64
89
 
65
90
  def set_ssl_verify(enabled: bool) -> None:
66
91
  """
@@ -35,7 +35,12 @@ class HttpClientException(PdfDancerException):
35
35
  Wraps httpx exceptions and HTTP errors from the API.
36
36
  """
37
37
 
38
- def __init__(self, message: str, response: Optional[httpx.Response] = None, cause: Optional[Exception] = None):
38
+ def __init__(
39
+ self,
40
+ message: str,
41
+ response: Optional[httpx.Response] = None,
42
+ cause: Optional[Exception] = None,
43
+ ):
39
44
  super().__init__(message, cause)
40
45
  self.response = response
41
46
  self.status_code = response.status_code if response else None
@@ -46,6 +51,7 @@ class SessionException(PdfDancerException):
46
51
  Exception raised for session-related errors.
47
52
  Occurs when session creation fails or session is invalid.
48
53
  """
54
+
49
55
  pass
50
56
 
51
57
 
@@ -54,4 +60,5 @@ class ValidationException(PdfDancerException):
54
60
  Exception raised for input validation errors.
55
61
  Equivalent to IllegalArgumentException in the Java client.
56
62
  """
63
+
57
64
  pass
@@ -30,14 +30,14 @@ class Fingerprint:
30
30
  install_salt = cls._get_or_create_salt()
31
31
 
32
32
  fingerprint_data = (
33
- ip_hash +
34
- uid_hash +
35
- os_type +
36
- sdk_language +
37
- timezone +
38
- locale_str +
39
- domain_hash +
40
- install_salt
33
+ ip_hash
34
+ + uid_hash
35
+ + os_type
36
+ + sdk_language
37
+ + timezone
38
+ + locale_str
39
+ + domain_hash
40
+ + install_salt
41
41
  )
42
42
 
43
43
  return cls._hash(fingerprint_data)
@@ -63,7 +63,7 @@ class Fingerprint:
63
63
  """Get timezone name."""
64
64
  try:
65
65
  tz = datetime.now().astimezone().tzinfo
66
- timezone_name = getattr(tz, 'key', str(tz))
66
+ timezone_name = getattr(tz, "key", str(tz))
67
67
  return timezone_name
68
68
  except Exception:
69
69
  return "unknown"
@@ -118,4 +118,4 @@ class Fingerprint:
118
118
  Returns:
119
119
  Hexadecimal SHA256 hash
120
120
  """
121
- return hashlib.sha256(value.encode('utf-8')).hexdigest()
121
+ return hashlib.sha256(value.encode("utf-8")).hexdigest()
@@ -1,11 +1,17 @@
1
+ from __future__ import annotations
2
+
1
3
  from pathlib import Path
4
+ from typing import TYPE_CHECKING
5
+
6
+ from pdfdancer import Image, Position, ValidationException
2
7
 
3
- from pdfdancer import ValidationException, Image, Position
8
+ if TYPE_CHECKING:
9
+ from .pdfdancer_v1 import PDFDancer
4
10
 
5
11
 
6
12
  class ImageBuilder:
7
13
 
8
- def __init__(self, client: 'PDFDancer'):
14
+ def __init__(self, client: "PDFDancer"):
9
15
  """
10
16
  Initialize the image builder with a client reference.
11
17
 
@@ -18,11 +24,11 @@ class ImageBuilder:
18
24
  self._client = client
19
25
  self._image = Image()
20
26
 
21
- def from_file(self, img_path: Path) -> 'ImageBuilder':
27
+ def from_file(self, img_path: Path) -> "ImageBuilder":
22
28
  self._image.data = img_path.read_bytes()
23
29
  return self
24
30
 
25
- def at(self, page, x, y) -> 'ImageBuilder':
31
+ def at(self, page, x, y) -> "ImageBuilder":
26
32
  self._image.position = Position.at_page_coordinates(page, x, y)
27
33
  return self
28
34
 
@@ -33,7 +39,7 @@ class ImageBuilder:
33
39
 
34
40
  class ImageOnPageBuilder:
35
41
 
36
- def __init__(self, client: 'PDFDancer', page_index: int):
42
+ def __init__(self, client: "PDFDancer", page_index: int):
37
43
  """
38
44
  Initialize the image builder with a client reference.
39
45
 
@@ -47,11 +53,11 @@ class ImageOnPageBuilder:
47
53
  self._image = Image()
48
54
  self._page_index = page_index
49
55
 
50
- def from_file(self, img_path: Path) -> 'ImageOnPageBuilder':
56
+ def from_file(self, img_path: Path) -> "ImageOnPageBuilder":
51
57
  self._image.data = img_path.read_bytes()
52
58
  return self
53
59
 
54
- def at(self, x, y) -> 'ImageOnPageBuilder':
60
+ def at(self, x, y) -> "ImageOnPageBuilder":
55
61
  self._image.position = Position.at_page_coordinates(self._page_index, x, y)
56
62
  return self
57
63