docpull 6.3.0__tar.gz → 6.4.0__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.
- {docpull-6.3.0/src/docpull.egg-info → docpull-6.4.0}/PKG-INFO +6 -2
- {docpull-6.3.0 → docpull-6.4.0}/README.md +5 -1
- {docpull-6.3.0 → docpull-6.4.0}/pyproject.toml +1 -1
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/__init__.py +9 -1
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/cli.py +3 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/__init__.py +3 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/brand.py +23 -9
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/common.py +74 -1
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/policy_pack.py +16 -7
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/product.py +165 -37
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/styleguide.py +14 -7
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/visuals.py +6 -2
- docpull-6.4.0/src/docpull/context_packs/website.py +1238 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/workflow_cli.py +44 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/contracts.py +141 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/mcp/server.py +35 -1
- docpull-6.4.0/src/docpull/schemas/website-snapshot.v1.schema.json +567 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/surface.py +8 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/workflows.py +36 -1
- {docpull-6.3.0 → docpull-6.4.0/src/docpull.egg-info}/PKG-INFO +6 -2
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull.egg-info/SOURCES.txt +4 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_ci_policy.py +3 -5
- docpull-6.4.0/tests/test_local_pack_workflows.py +151 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_release_a_plus_check_script.py +6 -14
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_surface_contract.py +0 -32
- docpull-6.4.0/tests/test_website_snapshot.py +352 -0
- {docpull-6.3.0 → docpull-6.4.0}/LICENSE +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/setup.cfg +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/__main__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/accounting.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/acquisition_workflows.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/agent_publish.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/auth_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/basis.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/benchmark.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/cache/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/cache/frontier.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/cache/manager.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/cache/streaming_dedup.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/change_events.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_aliases.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_ci.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/_legacy_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/dataset.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/feed.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/openapi.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/package.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/paper.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/relationship.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/repo.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/schema_extract.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/search.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/standards.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/transcript.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/typed.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/typed_models.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/context_packs/wiki.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/contracts_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/article_cleanup.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/chunking.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/ensemble.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/extractor.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/filings.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/markdown.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/protocols.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/special_cases.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/conversion/trafilatura_extractor.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/core/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/core/fetcher.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/_fetch.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/composite.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/contracts.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/crawler.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/filters.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/link_extractors/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/link_extractors/enhanced.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/link_extractors/protocols.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/link_extractors/static.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/protocols.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery/sitemap.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/discovery_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/doctor.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/document_parse.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/document_worker.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/eval_grade.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/evidence.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/evidence_pack.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/export_formats.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/exports.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/fixtures/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/fixtures/parallel-search-extract.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/free_core.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/free_core_smoke.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/graph.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/hosted.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/http/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/http/client.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/http/protocols.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/http/rate_limiter.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/judge.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/local_workflows.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/mcp/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/mcp/sources.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/mcp/tools.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/metadata_extractor.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/models/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/models/config.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/models/document.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/models/events.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/models/profiles.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/models/run.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/models/schema.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/monitor.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/native_integrations.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/output_contract.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pack_reader.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pack_tools.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/parallel_workflows.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/parity.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/parity_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/passk.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/base.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/manifest.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/chunk.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/convert.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/dedup.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/fetch.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/metadata.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/render.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/save.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/save_json.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/save_ndjson.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/save_okf.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/save_sqlite.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/pipeline/steps/validate.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/policy.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/policy_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/project.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/provider_adapters.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/provider_capabilities.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/provider_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/provider_keys.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/provider_probes.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/py.typed +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/redaction.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/rendering.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/artifact-manifest.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/basis.v2.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/change-event.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/citation-map.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/document.v3.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/intelligence-bundle.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/pack.v3.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/provenance.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/relationship-pack.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/rights.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/run-identity.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/workflow-request.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/schemas/workflow-result.v1.schema.json +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/scraper.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/security/__init__.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/security/download_policy.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/security/robots.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/security/url_validator.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/server.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/share.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/skill_export.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/source_scoring.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull/time_utils.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull.egg-info/dependency_links.txt +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull.egg-info/entry_points.txt +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull.egg-info/requires.txt +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/src/docpull.egg-info/top_level.txt +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_accounting.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_acquisition_workflows.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_auth_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_basis.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_benchmark.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_cache_conditional_get.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_chunking.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_claim_audit_script.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_context_ci.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_context_packs.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_conversion.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_convert_step_new.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_discovery.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_discovery_contracts.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_doctor.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_document_parse.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_document_record.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_evidence_pack.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_exports.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_extractor_ensemble.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_feed_pack.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_free_core.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_frontier_resume.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_graph.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_hosted.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_http_efficiency.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_import_efficiency.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_integration.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_judge.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_link_extractors.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_live_web_smoke.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_local_workflows.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_mcp_server.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_mcp_tools.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_metadata_extractor.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_monitor.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_naming.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_native_integrations.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_openapi_pack.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_optional_extras_installed.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_output_contract.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_outputs_e2e.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_pack_server.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_pack_tools.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_parallel_workflows.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_parity_workflows.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_passk.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_pipeline.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_policy.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_policy_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_project.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_provider_adapters.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_provider_cli.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_provider_keys.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_provider_probes.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_public_feature_smoke.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_rate_limiter.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_real_feature_smoke_script.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_real_site_regressions.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_relationship_workflow.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_rendering.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_reproducible_release_build.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_save_ndjson.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_save_sqlite.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_security_hardening.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_share.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_source_scoring.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_special_cases.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_time_utils.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_trafilatura_extractor.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_typed_knowledge_packs.py +0 -0
- {docpull-6.3.0 → docpull-6.4.0}/tests/test_workflow_contracts.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docpull
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.4.0
|
|
4
4
|
Summary: Declare, sync, diff, and lock context dependencies for AI agents
|
|
5
5
|
Author-email: Zachary Roth <support@raintree.technology>
|
|
6
6
|
Maintainer-email: Raintree Technology <support@raintree.technology>
|
|
@@ -307,6 +307,7 @@ docpull standards-pack rfc:9110 -o packs/standard
|
|
|
307
307
|
docpull dataset-pack ./metrics.csv -o packs/dataset
|
|
308
308
|
docpull dataset-pack 'https://data.example.org/rows.json?$limit=100' -o packs/dataset
|
|
309
309
|
docpull relationship-pack example.com --subject "Example Brand" -o packs/relationships
|
|
310
|
+
docpull website-pack example.com -o packs/website
|
|
310
311
|
docpull transcript-pack ./meeting.vtt -o packs/transcript
|
|
311
312
|
docpull wiki-pack wiki:Web_scraping -o packs/wiki
|
|
312
313
|
docpull brand-pack example.com -o packs/brand
|
|
@@ -320,6 +321,9 @@ docpull export packs/docs --format openai-vector-jsonl -o exports/openai.jsonl
|
|
|
320
321
|
docpull export packs/docs --format cursor-rules -o .cursor/rules --skill-name docs
|
|
321
322
|
```
|
|
322
323
|
|
|
324
|
+
The canonical baseline-aware website acquisition contract is documented in
|
|
325
|
+
[Website snapshots](docs/website-snapshot.md).
|
|
326
|
+
|
|
323
327
|
Use `docpull ci --prepare` to validate a project or standalone pack in CI.
|
|
324
328
|
|
|
325
329
|
Install optional extras as needed:
|
|
@@ -772,7 +776,7 @@ part of the package release contract.
|
|
|
772
776
|
`docpull parse`, `docpull openapi-pack`, `docpull feed-pack`,
|
|
773
777
|
`docpull paper-pack`, `docpull repo-pack`, `docpull package-pack`,
|
|
774
778
|
`docpull standards-pack`, `docpull dataset-pack`, `docpull transcript-pack`,
|
|
775
|
-
`docpull wiki-pack`, `docpull brand-pack`, `docpull product-pack`,
|
|
779
|
+
`docpull wiki-pack`, `docpull website-pack`, `docpull brand-pack`, `docpull product-pack`,
|
|
776
780
|
`docpull styleguide-pack`, `docpull image-pack`, `docpull policy-pack`,
|
|
777
781
|
`docpull pack validate`,
|
|
778
782
|
`docpull pack audit`, `docpull export`,
|
|
@@ -183,6 +183,7 @@ docpull standards-pack rfc:9110 -o packs/standard
|
|
|
183
183
|
docpull dataset-pack ./metrics.csv -o packs/dataset
|
|
184
184
|
docpull dataset-pack 'https://data.example.org/rows.json?$limit=100' -o packs/dataset
|
|
185
185
|
docpull relationship-pack example.com --subject "Example Brand" -o packs/relationships
|
|
186
|
+
docpull website-pack example.com -o packs/website
|
|
186
187
|
docpull transcript-pack ./meeting.vtt -o packs/transcript
|
|
187
188
|
docpull wiki-pack wiki:Web_scraping -o packs/wiki
|
|
188
189
|
docpull brand-pack example.com -o packs/brand
|
|
@@ -196,6 +197,9 @@ docpull export packs/docs --format openai-vector-jsonl -o exports/openai.jsonl
|
|
|
196
197
|
docpull export packs/docs --format cursor-rules -o .cursor/rules --skill-name docs
|
|
197
198
|
```
|
|
198
199
|
|
|
200
|
+
The canonical baseline-aware website acquisition contract is documented in
|
|
201
|
+
[Website snapshots](docs/website-snapshot.md).
|
|
202
|
+
|
|
199
203
|
Use `docpull ci --prepare` to validate a project or standalone pack in CI.
|
|
200
204
|
|
|
201
205
|
Install optional extras as needed:
|
|
@@ -648,7 +652,7 @@ part of the package release contract.
|
|
|
648
652
|
`docpull parse`, `docpull openapi-pack`, `docpull feed-pack`,
|
|
649
653
|
`docpull paper-pack`, `docpull repo-pack`, `docpull package-pack`,
|
|
650
654
|
`docpull standards-pack`, `docpull dataset-pack`, `docpull transcript-pack`,
|
|
651
|
-
`docpull wiki-pack`, `docpull brand-pack`, `docpull product-pack`,
|
|
655
|
+
`docpull wiki-pack`, `docpull website-pack`, `docpull brand-pack`, `docpull product-pack`,
|
|
652
656
|
`docpull styleguide-pack`, `docpull image-pack`, `docpull policy-pack`,
|
|
653
657
|
`docpull pack validate`,
|
|
654
658
|
`docpull pack audit`, `docpull export`,
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "docpull"
|
|
7
|
-
version = "6.
|
|
7
|
+
version = "6.4.0"
|
|
8
8
|
dynamic = []
|
|
9
9
|
description = "Declare, sync, diff, and lock context dependencies for AI agents"
|
|
10
10
|
readme = {file = "README.md", content-type = "text/markdown"}
|
|
@@ -15,7 +15,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
15
15
|
|
|
16
16
|
from .surface import PUBLIC_SDK_EXPORTS
|
|
17
17
|
|
|
18
|
-
__version__ = "6.
|
|
18
|
+
__version__ = "6.4.0"
|
|
19
19
|
|
|
20
20
|
_LAZY_EXPORTS: dict[str, tuple[str, str]] = {
|
|
21
21
|
**{
|
|
@@ -41,9 +41,11 @@ _LAZY_EXPORTS: dict[str, tuple[str, str]] = {
|
|
|
41
41
|
"build_repo_pack",
|
|
42
42
|
"build_standards_pack",
|
|
43
43
|
"build_styleguide_pack",
|
|
44
|
+
"build_website_pack",
|
|
44
45
|
"build_transcript_pack",
|
|
45
46
|
"build_wiki_pack",
|
|
46
47
|
"capture_screenshot_pack",
|
|
48
|
+
"validate_website_snapshot_pack",
|
|
47
49
|
)
|
|
48
50
|
},
|
|
49
51
|
**{
|
|
@@ -59,6 +61,8 @@ _LAZY_EXPORTS: dict[str, tuple[str, str]] = {
|
|
|
59
61
|
"SourceAuthority",
|
|
60
62
|
"WorkflowRequest",
|
|
61
63
|
"WorkflowResult",
|
|
64
|
+
"WebsiteSnapshot",
|
|
65
|
+
"WebsiteSnapshotDocument",
|
|
62
66
|
"bundled_schema_path",
|
|
63
67
|
"write_contract_schemas",
|
|
64
68
|
)
|
|
@@ -198,8 +202,10 @@ if TYPE_CHECKING:
|
|
|
198
202
|
build_standards_pack,
|
|
199
203
|
build_styleguide_pack,
|
|
200
204
|
build_transcript_pack,
|
|
205
|
+
build_website_pack,
|
|
201
206
|
build_wiki_pack,
|
|
202
207
|
capture_screenshot_pack,
|
|
208
|
+
validate_website_snapshot_pack,
|
|
203
209
|
)
|
|
204
210
|
from .contracts import (
|
|
205
211
|
ArtifactManifest,
|
|
@@ -210,6 +216,8 @@ if TYPE_CHECKING:
|
|
|
210
216
|
RelationshipCandidate,
|
|
211
217
|
RelationshipPack,
|
|
212
218
|
SourceAuthority,
|
|
219
|
+
WebsiteSnapshot,
|
|
220
|
+
WebsiteSnapshotDocument,
|
|
213
221
|
WorkflowRequest,
|
|
214
222
|
WorkflowResult,
|
|
215
223
|
bundled_schema_path,
|
|
@@ -1661,6 +1661,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1661
1661
|
return run_monitor_cli(raw_argv[1:])
|
|
1662
1662
|
if raw_argv and raw_argv[0] in {
|
|
1663
1663
|
"brand-pack",
|
|
1664
|
+
"website-pack",
|
|
1664
1665
|
"product-pack",
|
|
1665
1666
|
"styleguide-pack",
|
|
1666
1667
|
"image-pack",
|
|
@@ -1676,9 +1677,11 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1676
1677
|
run_relationship_pack_cli,
|
|
1677
1678
|
run_screenshot_pack_cli,
|
|
1678
1679
|
run_styleguide_pack_cli,
|
|
1680
|
+
run_website_pack_cli,
|
|
1679
1681
|
)
|
|
1680
1682
|
|
|
1681
1683
|
workflow_runners = {
|
|
1684
|
+
"website-pack": run_website_pack_cli,
|
|
1682
1685
|
"brand-pack": run_brand_pack_cli,
|
|
1683
1686
|
"product-pack": run_product_pack_cli,
|
|
1684
1687
|
"styleguide-pack": run_styleguide_pack_cli,
|
|
@@ -25,6 +25,8 @@ _LAZY_EXPORTS = {
|
|
|
25
25
|
**{name: (".transcript", name) for name in ("async_build_transcript_pack", "build_transcript_pack")},
|
|
26
26
|
**{name: (".wiki", name) for name in ("async_build_wiki_pack", "build_wiki_pack")},
|
|
27
27
|
"capture_screenshot_pack": (".visuals", "capture_screenshot_pack"),
|
|
28
|
+
"build_website_pack": (".website", "build_website_pack"),
|
|
29
|
+
"validate_website_snapshot_pack": (".website", "validate_website_snapshot_pack"),
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
__all__ = list(PUBLIC_CONTEXT_PACK_EXPORTS)
|
|
@@ -59,6 +61,7 @@ if TYPE_CHECKING:
|
|
|
59
61
|
from .styleguide import build_styleguide_pack
|
|
60
62
|
from .transcript import async_build_transcript_pack, build_transcript_pack
|
|
61
63
|
from .visuals import build_image_pack, capture_screenshot_pack
|
|
64
|
+
from .website import build_website_pack, validate_website_snapshot_pack
|
|
62
65
|
from .wiki import async_build_wiki_pack, build_wiki_pack
|
|
63
66
|
|
|
64
67
|
|
|
@@ -29,6 +29,7 @@ from .common import (
|
|
|
29
29
|
homepage_url_for_domain,
|
|
30
30
|
is_free_or_disposable_email_domain,
|
|
31
31
|
likely_internal_pages,
|
|
32
|
+
pages_from_local_pack,
|
|
32
33
|
public_url,
|
|
33
34
|
quote_markdown,
|
|
34
35
|
resolve_url,
|
|
@@ -92,7 +93,14 @@ def build_brand_pack(
|
|
|
92
93
|
max_pages: int = MAX_BRAND_PAGES,
|
|
93
94
|
) -> dict[str, Any]:
|
|
94
95
|
"""Build a local brand profile from public website evidence."""
|
|
95
|
-
|
|
96
|
+
local_pages = pages_from_local_pack(domain_or_url)
|
|
97
|
+
domain = (
|
|
98
|
+
domain_from_input(local_pages[0].url)
|
|
99
|
+
if local_pages
|
|
100
|
+
else _resolve_brand_domain(domain_or_url, email=email, allow_free_email=allow_free_email)
|
|
101
|
+
)
|
|
102
|
+
if not domain:
|
|
103
|
+
raise ContextPackError("Could not resolve a domain from local brand-pack evidence.")
|
|
96
104
|
policy = ensure_policy_for_domain(policy, domain)
|
|
97
105
|
output_dir = output_dir.resolve()
|
|
98
106
|
run = ContextPackRun(
|
|
@@ -101,14 +109,20 @@ def build_brand_pack(
|
|
|
101
109
|
policy=policy,
|
|
102
110
|
input_value=email or domain_or_url,
|
|
103
111
|
)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
if local_pages is not None:
|
|
113
|
+
pages = local_pages[:max_pages]
|
|
114
|
+
if not pages:
|
|
115
|
+
raise ContextPackError("Local brand-pack input contains no readable documents.")
|
|
116
|
+
download_assets = False
|
|
117
|
+
else:
|
|
118
|
+
home_url = homepage_url_for_domain(domain)
|
|
119
|
+
home_pages = fetch_pages_blocking([home_url], run=run, max_pages=1)
|
|
120
|
+
if not home_pages:
|
|
121
|
+
raise ContextPackError(f"Could not fetch homepage for {domain}.")
|
|
122
|
+
candidate_urls = likely_internal_pages(home_pages[0], domain, max_pages=max_pages)
|
|
123
|
+
pages = fetch_pages_blocking(candidate_urls, run=run, max_pages=max_pages)
|
|
124
|
+
if not pages:
|
|
125
|
+
pages = home_pages
|
|
112
126
|
|
|
113
127
|
profile = _extract_brand_profile(pages, domain=domain, name_hint=name, ticker=ticker)
|
|
114
128
|
assets = _extract_brand_assets(
|
|
@@ -40,6 +40,7 @@ from ..models.document import DocumentRecord
|
|
|
40
40
|
from ..models.events import SkipReason
|
|
41
41
|
from ..models.run import RunIdentity
|
|
42
42
|
from ..output_contract import OUTPUT_CONTRACT_SCHEMA_VERSION, write_raw_contract_sidecars
|
|
43
|
+
from ..pack_reader import PackReadError, load_pack, resolve_pack_path
|
|
43
44
|
from ..pack_tools import build_citation_map
|
|
44
45
|
from ..policy import PolicyConfig, policy_domain_matches
|
|
45
46
|
from ..security.download_policy import SafeDownloadPolicy, UnsafeDownloadError, content_type_base
|
|
@@ -118,6 +119,8 @@ class PageSnapshot:
|
|
|
118
119
|
metadata: dict[str, Any]
|
|
119
120
|
extraction: dict[str, Any]
|
|
120
121
|
source_type: str | None = None
|
|
122
|
+
etag: str | None = None
|
|
123
|
+
last_modified: str | None = None
|
|
121
124
|
|
|
122
125
|
|
|
123
126
|
@dataclass(frozen=True)
|
|
@@ -214,6 +217,9 @@ class ContextPackRun:
|
|
|
214
217
|
http_request_count: int = 0
|
|
215
218
|
cache_hit_count: int = 0
|
|
216
219
|
progress_events: list[dict[str, Any]] = field(default_factory=list)
|
|
220
|
+
fetch_output_dir: Path | None = None
|
|
221
|
+
cache_dir: Path | None = None
|
|
222
|
+
unchanged_urls: set[str] = field(default_factory=set)
|
|
217
223
|
|
|
218
224
|
def __post_init__(self) -> None:
|
|
219
225
|
self.progress("run", "started", message=f"Started {self.workflow}", timestamp=self.started_at)
|
|
@@ -444,10 +450,17 @@ async def fetch_pages(
|
|
|
444
450
|
run.progress("acquisition", "started", total=len(selected), message="Acquiring source pages")
|
|
445
451
|
config = DocpullConfig(url=selected[0], profile=ProfileName.CUSTOM)
|
|
446
452
|
config.network.log_retry_warnings = False
|
|
453
|
+
if run.fetch_output_dir is not None:
|
|
454
|
+
config.output.directory = run.fetch_output_dir
|
|
455
|
+
if run.cache_dir is not None:
|
|
456
|
+
config.cache.enabled = True
|
|
457
|
+
config.cache.directory = run.cache_dir
|
|
458
|
+
config.cache.ttl_days = None
|
|
459
|
+
config.cache.skip_unchanged = True
|
|
447
460
|
snapshots: list[PageSnapshot] = []
|
|
448
461
|
async with Fetcher(config) as fetcher:
|
|
449
462
|
for index, url in enumerate(selected, start=1):
|
|
450
|
-
ctx = await fetcher.fetch_one(url, save=
|
|
463
|
+
ctx = await fetcher.fetch_one(url, save=run.fetch_output_dir is not None)
|
|
451
464
|
run.http_request_count += 1
|
|
452
465
|
if ctx.error:
|
|
453
466
|
run.errors.append(
|
|
@@ -462,6 +475,10 @@ async def fetch_pages(
|
|
|
462
475
|
)
|
|
463
476
|
continue
|
|
464
477
|
if ctx.should_skip:
|
|
478
|
+
if ctx.skip_code == SkipReason.CACHE_UNCHANGED:
|
|
479
|
+
run.cache_hit_count += 1
|
|
480
|
+
run.unchanged_urls.add(public_url(url))
|
|
481
|
+
continue
|
|
465
482
|
if ctx.skip_code in {
|
|
466
483
|
SkipReason.HTTP_ERROR,
|
|
467
484
|
SkipReason.ROBOTS_DISALLOWED,
|
|
@@ -503,6 +520,8 @@ async def fetch_pages(
|
|
|
503
520
|
metadata=dict(ctx.metadata or {}),
|
|
504
521
|
extraction=dict(ctx.extraction_info or {}),
|
|
505
522
|
source_type=ctx.source_type,
|
|
523
|
+
etag=getattr(ctx, "etag", None),
|
|
524
|
+
last_modified=getattr(ctx, "last_modified", None),
|
|
506
525
|
)
|
|
507
526
|
)
|
|
508
527
|
run.progress(
|
|
@@ -531,6 +550,60 @@ def fetch_pages_blocking(
|
|
|
531
550
|
return asyncio.run(fetch_pages(urls, run=run, max_pages=max_pages))
|
|
532
551
|
|
|
533
552
|
|
|
553
|
+
def pages_from_local_pack(value: str | Path) -> list[PageSnapshot] | None:
|
|
554
|
+
"""Load an existing DocPull pack without permitting any network fallback."""
|
|
555
|
+
|
|
556
|
+
path = Path(value).expanduser()
|
|
557
|
+
if not path.exists():
|
|
558
|
+
return None
|
|
559
|
+
try:
|
|
560
|
+
pack = load_pack(path)
|
|
561
|
+
except PackReadError as err:
|
|
562
|
+
raise ContextPackError(f"Could not read local DocPull pack {path}: {err}") from err
|
|
563
|
+
raw_by_identity: dict[tuple[str, str], str] = {}
|
|
564
|
+
website_metadata_by_identity: dict[tuple[str, str], dict[str, Any]] = {}
|
|
565
|
+
records_path = path.resolve() / "documents.ndjson"
|
|
566
|
+
if records_path.is_file():
|
|
567
|
+
for line in records_path.read_text(encoding="utf-8").splitlines():
|
|
568
|
+
if not line.strip():
|
|
569
|
+
continue
|
|
570
|
+
try:
|
|
571
|
+
row = json.loads(line)
|
|
572
|
+
except json.JSONDecodeError:
|
|
573
|
+
continue
|
|
574
|
+
if not isinstance(row, dict):
|
|
575
|
+
continue
|
|
576
|
+
identity = (str(row.get("document_id") or ""), str(row.get("content_hash") or ""))
|
|
577
|
+
website_metadata_by_identity[identity] = {
|
|
578
|
+
key: row[key]
|
|
579
|
+
for key in ("page_role", "entity_reference", "authority", "representations")
|
|
580
|
+
if row.get(key) is not None
|
|
581
|
+
}
|
|
582
|
+
representations = row.get("representations")
|
|
583
|
+
raw = representations.get("raw") if isinstance(representations, dict) else None
|
|
584
|
+
raw_path = resolve_pack_path(path.resolve(), raw.get("path") if isinstance(raw, dict) else None)
|
|
585
|
+
if raw_path and raw_path.is_file():
|
|
586
|
+
raw_by_identity[identity] = raw_path.read_text(encoding="utf-8")
|
|
587
|
+
pages: list[PageSnapshot] = []
|
|
588
|
+
for record in pack.documents:
|
|
589
|
+
identity = (record.document_id, record.content_hash)
|
|
590
|
+
pages.append(
|
|
591
|
+
PageSnapshot(
|
|
592
|
+
url=public_url(record.url),
|
|
593
|
+
title=record.title,
|
|
594
|
+
html=raw_by_identity.get(identity, ""),
|
|
595
|
+
markdown=record.content,
|
|
596
|
+
metadata={
|
|
597
|
+
**dict(record.metadata),
|
|
598
|
+
**website_metadata_by_identity.get(identity, {}),
|
|
599
|
+
},
|
|
600
|
+
extraction={**record.extraction, "local_pack": str(path.resolve())},
|
|
601
|
+
source_type=record.source_type or "local-pack",
|
|
602
|
+
)
|
|
603
|
+
)
|
|
604
|
+
return pages
|
|
605
|
+
|
|
606
|
+
|
|
534
607
|
def soup_for(page: PageSnapshot) -> BeautifulSoup:
|
|
535
608
|
return BeautifulSoup(page.html or page.markdown, "html.parser")
|
|
536
609
|
|
|
@@ -24,6 +24,7 @@ from .common import (
|
|
|
24
24
|
extract_links,
|
|
25
25
|
fetch_pages_blocking,
|
|
26
26
|
homepage_url_for_domain,
|
|
27
|
+
pages_from_local_pack,
|
|
27
28
|
public_url,
|
|
28
29
|
quote_markdown,
|
|
29
30
|
same_policy_domain,
|
|
@@ -73,7 +74,8 @@ def build_policy_pack(
|
|
|
73
74
|
) -> dict[str, Any]:
|
|
74
75
|
"""Discover policy pages and emit neutral, clause-level evidence records."""
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
local_pages = pages_from_local_pack(domain_or_url)
|
|
78
|
+
domain = domain_from_input(local_pages[0].url) if local_pages else domain_from_input(domain_or_url)
|
|
77
79
|
if not domain:
|
|
78
80
|
raise ContextPackError("Could not resolve a domain from policy-pack input.")
|
|
79
81
|
effective_policy = ensure_policy_for_domain(policy, domain)
|
|
@@ -84,14 +86,21 @@ def build_policy_pack(
|
|
|
84
86
|
input_value=domain_or_url,
|
|
85
87
|
)
|
|
86
88
|
start_url = public_url(domain_or_url if "://" in domain_or_url else homepage_url_for_domain(domain))
|
|
87
|
-
discovery_pages =
|
|
89
|
+
discovery_pages = (
|
|
90
|
+
local_pages[:max_pages]
|
|
91
|
+
if local_pages is not None
|
|
92
|
+
else fetch_pages_blocking([start_url], run=run, max_pages=1)
|
|
93
|
+
)
|
|
88
94
|
if not discovery_pages:
|
|
89
|
-
raise ContextPackError(f"Could not
|
|
95
|
+
raise ContextPackError(f"Could not load policy discovery target: {start_url}")
|
|
90
96
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
if local_pages is not None:
|
|
98
|
+
pages = local_pages[:max_pages]
|
|
99
|
+
else:
|
|
100
|
+
urls = _policy_urls(discovery_pages[0], domain=domain, max_pages=max_pages)
|
|
101
|
+
if _policy_target_hint(discovery_pages[0]) and start_url not in urls:
|
|
102
|
+
urls.insert(0, start_url)
|
|
103
|
+
pages = fetch_pages_blocking(urls, run=run, max_pages=max_pages) if urls else []
|
|
95
104
|
if not pages:
|
|
96
105
|
run.warn(
|
|
97
106
|
"policy_documents_not_found",
|