Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
84 changes: 19 additions & 65 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,29 @@ name: CI

on:
pull_request:
push:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref_type != 'tag' }}
cancel-in-progress: true

env:
OPENAI_API_KEY: ""
ANTHROPIC_API_KEY: ""

jobs:
test:
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: ["3.11", "3.12", "3.13"]
python-version: ["3.11", "3.13"]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install Poppler on Ubuntu
if: runner.os == 'Linux'
- name: Install Poppler
run: sudo apt-get update && sudo apt-get install --yes poppler-utils
- name: Install Poppler on macOS
if: runner.os == 'macOS'
run: brew install poppler
- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
Expand All @@ -40,76 +34,36 @@ jobs:
run: uv sync --all-groups --frozen
- name: Run tests
run: uv run --frozen pytest -q

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.13"
enable-cache: true
- name: Sync locked dependencies
run: uv sync --all-groups --frozen
- name: Run Ruff
run: uv run --frozen ruff check .
- name: Check formatting
run: uv run --frozen ruff format --check .
- name: Run ty
run: uv run --frozen ty check src tests benchmarks scripts examples
- name: Check patch whitespace
run: git diff --check
run: uv run --frozen ty check src tests

build:
runs-on: ubuntu-latest
needs: test
needs: [test, lint]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.13"
enable-cache: true
- name: Build checked distributions
- name: Build and inspect
run: |
uv build
uv run --frozen python scripts/check_release_artifacts.py dist
- name: Upload checked distributions
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-dists
path: |
dist/*.whl
dist/*.tar.gz
dist/SHA256SUMS
if-no-files-found: error
retention-days: 7

artifact-smoke:
runs-on: ${{ matrix.os }}
needs: build
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install Poppler on Ubuntu
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install --yes poppler-utils
- name: Install Poppler on macOS
if: runner.os == 'macOS'
run: brew install poppler
- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.13"
- name: Download checked distributions
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-dists
path: dist
- name: Verify checksums and artifact contracts
run: python scripts/check_release_artifacts.py dist --verify-checksums
- name: Smoke wheel and source distribution independently
shell: bash
run: |
wheel="$(find dist -maxdepth 1 -name '*.whl' -print -quit)"
sdist="$(find dist -maxdepth 1 -name '*.tar.gz' -print -quit)"
python -m venv "$RUNNER_TEMP/wheel-env"
"$RUNNER_TEMP/wheel-env/bin/pip" install "$wheel"
"$RUNNER_TEMP/wheel-env/bin/python" scripts/release_smoke.py \
"$RUNNER_TEMP/wheel-smoke" --version 0.1.0
python -m venv "$RUNNER_TEMP/sdist-env"
"$RUNNER_TEMP/sdist-env/bin/pip" install "$sdist"
"$RUNNER_TEMP/sdist-env/bin/python" scripts/release_smoke.py \
"$RUNNER_TEMP/sdist-smoke" --version 0.1.0
16 changes: 15 additions & 1 deletion src/opendocs/parsers/pdf/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,11 @@ def _tables(
page: Any,
words: Sequence[PdfWord],
transform: CoordinateTransform,
*,
settings: dict[str, str] | None = None,
) -> tuple[list[Any], bool]:
try:
raw_tables = page.find_tables()
raw_tables = page.find_tables(settings) if settings is not None else page.find_tables()
except (
AttributeError,
KeyError,
Expand Down Expand Up @@ -355,6 +357,18 @@ def _analyze_page(page: Any, page_number: int) -> PageFacts:
all_tables, table_failed = _tables(page, words, geometry)
_enforce_wire_budget(words, all_tables)
accepted_tables = select_canonical_tables(all_tables)
if not accepted_tables:
strict_tables, strict_failed = _tables(
page,
words,
geometry,
settings={"vertical_strategy": "lines_strict", "horizontal_strategy": "lines_strict"},
)
if strict_tables:
_enforce_wire_budget(words, strict_tables)
accepted_tables = select_canonical_tables(strict_tables)
all_tables = strict_tables
table_failed = table_failed or strict_failed
if not accepted_tables:
heuristic_table = detect_heuristic_table(words)
if heuristic_table is not None:
Expand Down
32 changes: 13 additions & 19 deletions tests/test_workflow_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,57 +34,51 @@ def _assert_remote_actions_are_pinned(path: Path) -> None:
assert all(PINNED_ACTION.fullmatch(line) for line in action_lines)


def test_ci_covers_the_release_blocking_os_and_python_matrix() -> None:
def test_ci_covers_the_min_and_max_python_versions() -> None:
jobs = _jobs(CI_PATH)
test_job = jobs["test"]
strategy = cast(dict[str, object], test_job["strategy"])
matrix = cast(dict[str, list[str]], strategy["matrix"])

assert matrix["os"] == ["ubuntu-latest", "macos-latest"]
assert matrix["python-version"] == ["3.11", "3.12", "3.13"]
assert test_job["runs-on"] == "${{ matrix.os }}"
assert "os" not in matrix
assert matrix["python-version"] == ["3.11", "3.13"]
assert test_job["runs-on"] == "ubuntu-latest"


def test_ci_installs_poppler_and_keeps_all_public_gates() -> None:
source = CI_PATH.read_text(encoding="utf-8")

assert "sudo apt-get install --yes poppler-utils" in source
assert "brew install poppler" in source
for command in (
"pytest -q",
"ruff check .",
"ruff format --check .",
"ty check src tests benchmarks scripts examples",
"ty check src tests",
"scripts/check_release_artifacts.py dist",
"scripts/check_release_artifacts.py dist --verify-checksums",
"scripts/release_smoke.py",
):
assert command in source
assert 'OPENAI_API_KEY: ""' in source
assert 'ANTHROPIC_API_KEY: ""' in source


def test_ci_builds_once_and_smokes_the_same_artifact_on_both_operating_systems() -> None:
def test_ci_builds_once_and_lint_is_separate_from_test() -> None:
jobs = _jobs(CI_PATH)
source = CI_PATH.read_text(encoding="utf-8")
smoke = jobs["artifact-smoke"]
strategy = cast(dict[str, object], smoke["strategy"])
matrix = cast(dict[str, list[str]], strategy["matrix"])

assert source.count("uv build") == 1
assert matrix["os"] == ["ubuntu-latest", "macos-latest"]
assert smoke["needs"] == "build"
assert source.count("name: release-dists") == 2
assert "dist/*.whl" in source
assert "dist/*.tar.gz" in source
assert "dist/SHA256SUMS" in source
assert "lint" in jobs
assert jobs["lint"]["runs-on"] == "ubuntu-latest"
assert jobs["build"]["needs"] == ["test", "lint"]
assert "ruff check ." in source
assert "ruff format --check ." in source
assert "ty check src tests" in source


def test_ci_cancels_superseded_non_tag_runs_and_pins_actions() -> None:
workflow = _workflow(CI_PATH)
concurrency = cast(dict[str, str], workflow["concurrency"])

assert concurrency["cancel-in-progress"] == "${{ github.ref_type != 'tag' }}"
assert concurrency["cancel-in-progress"] == "true"
_assert_remote_actions_are_pinned(CI_PATH)


Expand Down