pictovap 0.2.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.
Files changed (48) hide show
  1. pictovap-0.2.1/LICENSE +9 -0
  2. pictovap-0.2.1/PKG-INFO +209 -0
  3. pictovap-0.2.1/README.md +177 -0
  4. pictovap-0.2.1/pyproject.toml +58 -0
  5. pictovap-0.2.1/setup.cfg +4 -0
  6. pictovap-0.2.1/src/pictova/__init__.py +39 -0
  7. pictovap-0.2.1/src/pictova/app/__init__.py +1 -0
  8. pictovap-0.2.1/src/pictova/app/cli.py +81 -0
  9. pictovap-0.2.1/src/pictova/core/__init__.py +0 -0
  10. pictovap-0.2.1/src/pictova/core/adapters.py +76 -0
  11. pictovap-0.2.1/src/pictova/core/demo_metadata.py +121 -0
  12. pictovap-0.2.1/src/pictova/core/filter.py +454 -0
  13. pictovap-0.2.1/src/pictova/core/language.py +34 -0
  14. pictovap-0.2.1/src/pictova/core/media_publish.py +1035 -0
  15. pictovap-0.2.1/src/pictova/core/media_quality.py +234 -0
  16. pictovap-0.2.1/src/pictova/core/metadata_generator.py +685 -0
  17. pictovap-0.2.1/src/pictova/core/primitives.py +249 -0
  18. pictovap-0.2.1/src/pictova/core/profile.py +100 -0
  19. pictovap-0.2.1/src/pictova/core/sources.py +68 -0
  20. pictovap-0.2.1/src/pictova/data/__init__.py +1 -0
  21. pictovap-0.2.1/src/pictova/data/sample-article.md +15 -0
  22. pictovap-0.2.1/src/pictova/demo.py +681 -0
  23. pictovap-0.2.1/src/pictova/engine/__init__.py +1 -0
  24. pictovap-0.2.1/src/pictova/engine/geo_aliases.py +56 -0
  25. pictovap-0.2.1/src/pictova/engine/publisher.py +25 -0
  26. pictovap-0.2.1/src/pictova/engine/quality.py +75 -0
  27. pictovap-0.2.1/src/pictova/engine/vision_chain.py +302 -0
  28. pictovap-0.2.1/src/pictova/providers/__init__.py +1 -0
  29. pictovap-0.2.1/src/pictova/providers/deposit.py +268 -0
  30. pictovap-0.2.1/src/pictova/providers/local.py +79 -0
  31. pictovap-0.2.1/src/pictova/providers/openverse.py +77 -0
  32. pictovap-0.2.1/src/pictova/providers/pexels.py +82 -0
  33. pictovap-0.2.1/src/pictova/providers/unsplash.py +118 -0
  34. pictovap-0.2.1/src/pictova/publishers/__init__.py +51 -0
  35. pictovap-0.2.1/src/pictova/publishers/ghost.py +256 -0
  36. pictovap-0.2.1/src/pictova/publishers/strapi.py +255 -0
  37. pictovap-0.2.1/src/pictova/services/__init__.py +1 -0
  38. pictovap-0.2.1/src/pictova/services/post_media_guard.py +217 -0
  39. pictovap-0.2.1/src/pictova/services/wordpress.py +918 -0
  40. pictovap-0.2.1/src/pictova/utils/__init__.py +25 -0
  41. pictovap-0.2.1/src/pictova/utils/config.py +58 -0
  42. pictovap-0.2.1/src/pictova/vision_templates.py +238 -0
  43. pictovap-0.2.1/src/pictovap.egg-info/PKG-INFO +209 -0
  44. pictovap-0.2.1/src/pictovap.egg-info/SOURCES.txt +46 -0
  45. pictovap-0.2.1/src/pictovap.egg-info/dependency_links.txt +1 -0
  46. pictovap-0.2.1/src/pictovap.egg-info/entry_points.txt +3 -0
  47. pictovap-0.2.1/src/pictovap.egg-info/requires.txt +11 -0
  48. pictovap-0.2.1/src/pictovap.egg-info/top_level.txt +1 -0
pictovap-0.2.1/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kemal Kaya — yoldaolmak.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -0,0 +1,209 @@
1
+ Metadata-Version: 2.4
2
+ Name: pictovap
3
+ Version: 0.2.1
4
+ Summary: Open-source visual finishing engine for content publishers.
5
+ Author-email: Pictovap Contributors <hello@yoldaolmak.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yoldaolmak/Pictovap
8
+ Project-URL: Documentation, https://github.com/yoldaolmak/Pictovap/blob/main/docs/README.md
9
+ Project-URL: Repository, https://github.com/yoldaolmak/Pictovap.git
10
+ Keywords: wordpress,image automation,llm,vision,seo,cms,unsplash
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Topic :: Multimedia :: Graphics
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: Pillow>=9.0.0
23
+ Requires-Dist: requests>=2.25.0
24
+ Requires-Dist: numpy>=1.20.0
25
+ Provides-Extra: providers
26
+ Requires-Dist: anthropic>=0.3.0; extra == "providers"
27
+ Provides-Extra: test
28
+ Requires-Dist: pytest>=7.4.0; extra == "test"
29
+ Requires-Dist: pytest-cov>=4.1.0; extra == "test"
30
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
31
+ Dynamic: license-file
32
+
33
+ # Pictovap
34
+
35
+ [![CI](https://github.com/yoldaolmak/Pictovap/actions/workflows/ci.yml/badge.svg)](https://github.com/yoldaolmak/Pictovap/actions/workflows/ci.yml)
36
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
37
+
38
+ **Pictovap is an open-source visual finishing engine for content publishers.**
39
+ It turns a finished article into a visually complete, rights-aware,
40
+ publish-ready CMS page — and shows its work at every step.
41
+
42
+ ## The Problem
43
+
44
+ Every publisher runs the same manual routine before an article can go live:
45
+ find images that actually fit the section they're going into, check whether
46
+ the license permits the intended use, resize and convert them to the site's
47
+ format, write alt text and a caption for each one, and place them at the
48
+ right point in the CMS. None of this is hard, individually. It is, however,
49
+ *repetitive*, *easy to get wrong under deadline pressure*, and it *scales
50
+ linearly with how much a publisher writes*. Skipped alt text quietly erodes
51
+ accessibility and SEO. Untracked image provenance is a license or attribution
52
+ problem waiting to surface later, when it's expensive to fix. None of this
53
+ shows up in a style guide — it shows up as an hour of an editor's afternoon,
54
+ per article, forever.
55
+
56
+ Point solutions exist for pieces of this: stock photo plugins, DAM systems,
57
+ generic AI image generators. What's largely missing is the connective layer
58
+ — something that reads what the article actually needs, evaluates candidates
59
+ against that need with a visible, auditable reason for every accept and
60
+ reject, and hands a CMS a placement plan it can execute without a human
61
+ re-deriving the same context from scratch.
62
+
63
+ ## The Solution
64
+
65
+ Pictovap is that connective layer, built as an open, adapter-based pipeline
66
+ rather than a closed SaaS product:
67
+
68
+ ```
69
+ Article Input → Visual Brief → Candidate Images → Fit Score
70
+ → Provenance Pack → CMS Placement → Editor Report
71
+ ```
72
+
73
+ - **Visual Brief** — a structured read of what imagery the article actually
74
+ needs, derived from its heading structure and content, not from a generic
75
+ "insert 3 images" rule.
76
+ - **Fit Score** — every candidate is scored against the brief with a
77
+ transparent, deterministic reason attached (`selected`, `rejected`, or
78
+ `needs_review`, plus why). No black-box relevance number.
79
+ - **Provenance Pack** — a persistent audit trail for every selected image:
80
+ source, license status, attribution, a content hash, and the exact
81
+ processing actions applied. This is what makes "where did this image come
82
+ from and are we allowed to use it" answerable six months later.
83
+ - **CMS Placement** — a CMS-agnostic plan describing where and how each image
84
+ should be placed, independent of whether the destination is WordPress,
85
+ Ghost, Strapi, or something a contributor writes an adapter for tomorrow.
86
+ - **Editor Report** — a human-readable Markdown review surface, so an editor
87
+ signs off on a report, not raw JSON, before anything reaches production.
88
+
89
+ What makes this radical isn't any single stage — it's that the whole pipeline
90
+ is a public, inspectable contract instead of a hosted black box, and that it
91
+ is honest about its own workings by default: the credential-free demo below
92
+ runs the entire pipeline end-to-end, with zero API keys and zero network
93
+ calls, so you can read exactly what it does before you ever hand it a real
94
+ site.
95
+
96
+ Pictovap is not a stock photo search tool, a DAM, a generic AI image
97
+ generator, or a WordPress-only plugin. It has no graphical interface yet — it
98
+ is a CLI-first, adapter-based core, with the editor report as the intended
99
+ human review surface and CMS adapters as the machine-facing execution layer.
100
+
101
+ ## Quickstart
102
+
103
+ ```bash
104
+ git clone https://github.com/yoldaolmak/Pictovap.git
105
+ cd Pictovap
106
+ python3 -m venv .venv
107
+ source .venv/bin/activate
108
+ pip install -r requirements.txt
109
+ pip install -e .
110
+ ```
111
+
112
+ Run the credential-free demo:
113
+
114
+ ```bash
115
+ pictovap demo
116
+ ```
117
+
118
+ ```text
119
+ Brief: 4 slots from 3 sections
120
+ Evaluated: 5 candidates
121
+ Selected: 3 images
122
+ Rejected: 4 candidates
123
+ Placements: 3 instructions
124
+ ```
125
+
126
+ No `.env` file, no API keys, no network calls — every candidate and score
127
+ above comes from deterministic mock data, on purpose. This is the demo's
128
+ guarantee, not just its default state.
129
+
130
+ ## Try Your Own Article
131
+
132
+ ```bash
133
+ pictovap plan \
134
+ --article path/to/your/article.md \
135
+ --profile examples/profiles/sample-publisher.yaml \
136
+ --output my-plan.json \
137
+ --report my-report.md
138
+ ```
139
+
140
+ `my-plan.json` is the canonical, machine-readable artifact for adapters and
141
+ automation. `my-report.md` is the same plan, rendered for a human editor to
142
+ review before anything gets published.
143
+
144
+ ## Adapters
145
+
146
+ Pictovap connects to the outside world only through adapters — the core
147
+ pipeline has no hardcoded dependency on any specific image provider or CMS.
148
+
149
+ **Image sources:** local folder, Unsplash, DepositPhotos, Openverse (no key
150
+ required), and Pexels are implemented. Pixabay and Wikimedia Commons are
151
+ open contribution opportunities — see
152
+ [Good First Issues](docs/contributing/good-first-issues.md). See
153
+ [Image Source Adapters](docs/adapters/image-sources.md).
154
+
155
+ **CMS placement:** WordPress (production-tested), Ghost and Strapi (reference
156
+ implementations, real but with documented limitations). See
157
+ [CMS Adapters](docs/adapters/cms-adapters.md).
158
+
159
+ Every adapter degrades gracefully when unconfigured — a missing API key
160
+ produces an empty result, not a crash, so a partially configured profile
161
+ still runs. Writing a new adapter means implementing one method
162
+ (`search_candidates` or `place`) against a documented `Protocol`; see the
163
+ [Adapter Overview](docs/adapters/overview.md).
164
+
165
+ ## Multi-Language by Design
166
+
167
+ Pictovap's own code, comments, and documentation are English. What it
168
+ *generates* — alt text, captions, titles — is not tied to any one language.
169
+ Article language is detected automatically (or set explicitly via the
170
+ publisher profile), and generated metadata follows it: a Turkish article
171
+ gets Turkish alt text, a French one gets French, and so on. This isn't a
172
+ localization afterthought bolted onto an English-only tool; it's a parameter
173
+ of the pipeline from the start.
174
+
175
+ ## Current Status and Limitations
176
+
177
+ Pictovap is early open-source infrastructure. It has a genuinely
178
+ credential-free local demo, documented core primitives, a real test suite,
179
+ and a working adapter model — it does not yet claim broad ecosystem adoption
180
+ or a large external contributor base.
181
+
182
+ Specifically:
183
+
184
+ - Only the WordPress CMS adapter is production-hardened; Ghost and Strapi are
185
+ real, tested reference implementations with documented gaps (see
186
+ [CMS Adapters](docs/adapters/cms-adapters.md)).
187
+ - The credential-free demo always uses deterministic mock candidates by
188
+ design, regardless of what's configured in `.env` — `pictovap plan` is
189
+ where real, credentialed sources are used.
190
+ - Deterministic structural extraction (the rule-based, non-AI language and
191
+ section detection) is reliable for English and Turkish; other languages
192
+ are untested.
193
+
194
+ ## Compatibility Note
195
+
196
+ Product name: Pictovap. The Python package, import name, and console-script
197
+ entry point may remain `pictova` for backward compatibility — see
198
+ [Brand & Naming](docs/architecture/naming.md).
199
+
200
+ ## Contributing
201
+
202
+ See the [Documentation Portal](docs/README.md) for architecture, concepts,
203
+ and adapter-writing guides, and [DEVELOPER.md](docs/DEVELOPER.md) for the
204
+ contribution workflow. Pull requests that add a new image source or CMS
205
+ adapter, improve test coverage, or fix documentation are all welcome.
206
+
207
+ ## License
208
+
209
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,177 @@
1
+ # Pictovap
2
+
3
+ [![CI](https://github.com/yoldaolmak/Pictovap/actions/workflows/ci.yml/badge.svg)](https://github.com/yoldaolmak/Pictovap/actions/workflows/ci.yml)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+
6
+ **Pictovap is an open-source visual finishing engine for content publishers.**
7
+ It turns a finished article into a visually complete, rights-aware,
8
+ publish-ready CMS page — and shows its work at every step.
9
+
10
+ ## The Problem
11
+
12
+ Every publisher runs the same manual routine before an article can go live:
13
+ find images that actually fit the section they're going into, check whether
14
+ the license permits the intended use, resize and convert them to the site's
15
+ format, write alt text and a caption for each one, and place them at the
16
+ right point in the CMS. None of this is hard, individually. It is, however,
17
+ *repetitive*, *easy to get wrong under deadline pressure*, and it *scales
18
+ linearly with how much a publisher writes*. Skipped alt text quietly erodes
19
+ accessibility and SEO. Untracked image provenance is a license or attribution
20
+ problem waiting to surface later, when it's expensive to fix. None of this
21
+ shows up in a style guide — it shows up as an hour of an editor's afternoon,
22
+ per article, forever.
23
+
24
+ Point solutions exist for pieces of this: stock photo plugins, DAM systems,
25
+ generic AI image generators. What's largely missing is the connective layer
26
+ — something that reads what the article actually needs, evaluates candidates
27
+ against that need with a visible, auditable reason for every accept and
28
+ reject, and hands a CMS a placement plan it can execute without a human
29
+ re-deriving the same context from scratch.
30
+
31
+ ## The Solution
32
+
33
+ Pictovap is that connective layer, built as an open, adapter-based pipeline
34
+ rather than a closed SaaS product:
35
+
36
+ ```
37
+ Article Input → Visual Brief → Candidate Images → Fit Score
38
+ → Provenance Pack → CMS Placement → Editor Report
39
+ ```
40
+
41
+ - **Visual Brief** — a structured read of what imagery the article actually
42
+ needs, derived from its heading structure and content, not from a generic
43
+ "insert 3 images" rule.
44
+ - **Fit Score** — every candidate is scored against the brief with a
45
+ transparent, deterministic reason attached (`selected`, `rejected`, or
46
+ `needs_review`, plus why). No black-box relevance number.
47
+ - **Provenance Pack** — a persistent audit trail for every selected image:
48
+ source, license status, attribution, a content hash, and the exact
49
+ processing actions applied. This is what makes "where did this image come
50
+ from and are we allowed to use it" answerable six months later.
51
+ - **CMS Placement** — a CMS-agnostic plan describing where and how each image
52
+ should be placed, independent of whether the destination is WordPress,
53
+ Ghost, Strapi, or something a contributor writes an adapter for tomorrow.
54
+ - **Editor Report** — a human-readable Markdown review surface, so an editor
55
+ signs off on a report, not raw JSON, before anything reaches production.
56
+
57
+ What makes this radical isn't any single stage — it's that the whole pipeline
58
+ is a public, inspectable contract instead of a hosted black box, and that it
59
+ is honest about its own workings by default: the credential-free demo below
60
+ runs the entire pipeline end-to-end, with zero API keys and zero network
61
+ calls, so you can read exactly what it does before you ever hand it a real
62
+ site.
63
+
64
+ Pictovap is not a stock photo search tool, a DAM, a generic AI image
65
+ generator, or a WordPress-only plugin. It has no graphical interface yet — it
66
+ is a CLI-first, adapter-based core, with the editor report as the intended
67
+ human review surface and CMS adapters as the machine-facing execution layer.
68
+
69
+ ## Quickstart
70
+
71
+ ```bash
72
+ git clone https://github.com/yoldaolmak/Pictovap.git
73
+ cd Pictovap
74
+ python3 -m venv .venv
75
+ source .venv/bin/activate
76
+ pip install -r requirements.txt
77
+ pip install -e .
78
+ ```
79
+
80
+ Run the credential-free demo:
81
+
82
+ ```bash
83
+ pictovap demo
84
+ ```
85
+
86
+ ```text
87
+ Brief: 4 slots from 3 sections
88
+ Evaluated: 5 candidates
89
+ Selected: 3 images
90
+ Rejected: 4 candidates
91
+ Placements: 3 instructions
92
+ ```
93
+
94
+ No `.env` file, no API keys, no network calls — every candidate and score
95
+ above comes from deterministic mock data, on purpose. This is the demo's
96
+ guarantee, not just its default state.
97
+
98
+ ## Try Your Own Article
99
+
100
+ ```bash
101
+ pictovap plan \
102
+ --article path/to/your/article.md \
103
+ --profile examples/profiles/sample-publisher.yaml \
104
+ --output my-plan.json \
105
+ --report my-report.md
106
+ ```
107
+
108
+ `my-plan.json` is the canonical, machine-readable artifact for adapters and
109
+ automation. `my-report.md` is the same plan, rendered for a human editor to
110
+ review before anything gets published.
111
+
112
+ ## Adapters
113
+
114
+ Pictovap connects to the outside world only through adapters — the core
115
+ pipeline has no hardcoded dependency on any specific image provider or CMS.
116
+
117
+ **Image sources:** local folder, Unsplash, DepositPhotos, Openverse (no key
118
+ required), and Pexels are implemented. Pixabay and Wikimedia Commons are
119
+ open contribution opportunities — see
120
+ [Good First Issues](docs/contributing/good-first-issues.md). See
121
+ [Image Source Adapters](docs/adapters/image-sources.md).
122
+
123
+ **CMS placement:** WordPress (production-tested), Ghost and Strapi (reference
124
+ implementations, real but with documented limitations). See
125
+ [CMS Adapters](docs/adapters/cms-adapters.md).
126
+
127
+ Every adapter degrades gracefully when unconfigured — a missing API key
128
+ produces an empty result, not a crash, so a partially configured profile
129
+ still runs. Writing a new adapter means implementing one method
130
+ (`search_candidates` or `place`) against a documented `Protocol`; see the
131
+ [Adapter Overview](docs/adapters/overview.md).
132
+
133
+ ## Multi-Language by Design
134
+
135
+ Pictovap's own code, comments, and documentation are English. What it
136
+ *generates* — alt text, captions, titles — is not tied to any one language.
137
+ Article language is detected automatically (or set explicitly via the
138
+ publisher profile), and generated metadata follows it: a Turkish article
139
+ gets Turkish alt text, a French one gets French, and so on. This isn't a
140
+ localization afterthought bolted onto an English-only tool; it's a parameter
141
+ of the pipeline from the start.
142
+
143
+ ## Current Status and Limitations
144
+
145
+ Pictovap is early open-source infrastructure. It has a genuinely
146
+ credential-free local demo, documented core primitives, a real test suite,
147
+ and a working adapter model — it does not yet claim broad ecosystem adoption
148
+ or a large external contributor base.
149
+
150
+ Specifically:
151
+
152
+ - Only the WordPress CMS adapter is production-hardened; Ghost and Strapi are
153
+ real, tested reference implementations with documented gaps (see
154
+ [CMS Adapters](docs/adapters/cms-adapters.md)).
155
+ - The credential-free demo always uses deterministic mock candidates by
156
+ design, regardless of what's configured in `.env` — `pictovap plan` is
157
+ where real, credentialed sources are used.
158
+ - Deterministic structural extraction (the rule-based, non-AI language and
159
+ section detection) is reliable for English and Turkish; other languages
160
+ are untested.
161
+
162
+ ## Compatibility Note
163
+
164
+ Product name: Pictovap. The Python package, import name, and console-script
165
+ entry point may remain `pictova` for backward compatibility — see
166
+ [Brand & Naming](docs/architecture/naming.md).
167
+
168
+ ## Contributing
169
+
170
+ See the [Documentation Portal](docs/README.md) for architecture, concepts,
171
+ and adapter-writing guides, and [DEVELOPER.md](docs/DEVELOPER.md) for the
172
+ contribution workflow. Pull requests that add a new image source or CMS
173
+ adapter, improve test coverage, or fix documentation are all welcome.
174
+
175
+ ## License
176
+
177
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,58 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pictovap"
7
+ version = "0.2.1"
8
+ description = "Open-source visual finishing engine for content publishers."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Pictovap Contributors", email = "hello@yoldaolmak.com"}
14
+ ]
15
+ keywords = [
16
+ "wordpress", "image automation", "llm", "vision", "seo", "cms", "unsplash"
17
+ ]
18
+ classifiers = [
19
+ "Development Status :: 4 - Beta",
20
+ "Intended Audience :: Developers",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Topic :: Multimedia :: Graphics",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ "Programming Language :: Python :: 3.9",
25
+ "Programming Language :: Python :: 3.10",
26
+ "Programming Language :: Python :: 3.11",
27
+ ]
28
+ dependencies = [
29
+ "Pillow>=9.0.0",
30
+ "requests>=2.25.0",
31
+ "numpy>=1.20.0",
32
+ ]
33
+
34
+ [project.optional-dependencies]
35
+ providers = [
36
+ "anthropic>=0.3.0",
37
+ ]
38
+ test = [
39
+ "pytest>=7.4.0",
40
+ "pytest-cov>=4.1.0",
41
+ "pytest-asyncio>=0.21.0",
42
+ ]
43
+
44
+ [project.urls]
45
+ Homepage = "https://github.com/yoldaolmak/Pictovap"
46
+ Documentation = "https://github.com/yoldaolmak/Pictovap/blob/main/docs/README.md"
47
+ Repository = "https://github.com/yoldaolmak/Pictovap.git"
48
+
49
+ [project.scripts]
50
+ pictova = "pictova.app.cli:main"
51
+ pictovap = "pictova.app.cli:main"
52
+
53
+ [tool.setuptools.packages.find]
54
+ where = ["src"]
55
+ namespaces = false
56
+
57
+ [tool.setuptools.package-data]
58
+ "pictova.data" = ["*.md"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,39 @@
1
+ """
2
+ Pictovap — Open-source visual finishing engine for content publishers.
3
+
4
+ This package provides modules to select, process, generate metadata for, and
5
+ publish images across various CMS platforms.
6
+ """
7
+
8
+ __version__ = "0.2.0"
9
+
10
+ # Public library API — the framework entry point.
11
+ from .demo import create_visual_plan
12
+
13
+ # Adapter contracts
14
+ from .core.adapters import ImageSourceAdapter, CMSAdapter, ReportRenderer
15
+
16
+ # Vision template system
17
+ from .vision_templates import (
18
+ VisionTemplate,
19
+ TRAVEL_BLOG,
20
+ TECHNICAL,
21
+ MINIMAL,
22
+ ECOMMERCE,
23
+ get_template,
24
+ register_template,
25
+ )
26
+
27
+ __all__ = [
28
+ "create_visual_plan",
29
+ "ImageSourceAdapter",
30
+ "CMSAdapter",
31
+ "ReportRenderer",
32
+ "VisionTemplate",
33
+ "TRAVEL_BLOG",
34
+ "TECHNICAL",
35
+ "MINIMAL",
36
+ "ECOMMERCE",
37
+ "get_template",
38
+ "register_template",
39
+ ]
@@ -0,0 +1 @@
1
+ """Application surface for VIL."""
@@ -0,0 +1,81 @@
1
+ """Pictovap CLI entrypoint.
2
+
3
+ Three commands, matching the public library API 1:1:
4
+ demo - run the credential-free example pipeline
5
+ plan - create a visual plan for a real article (pictova.create_visual_plan)
6
+ report - render an existing JSON plan as a Markdown editor report
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import argparse
12
+ import json
13
+ import sys
14
+ from typing import Any, Dict
15
+
16
+ from pictova.demo import create_visual_plan, generate_report_from_file, run_demo
17
+
18
+
19
+ def _print_json(payload: Dict[str, Any]) -> None:
20
+ print(json.dumps(payload, ensure_ascii=False, indent=2))
21
+
22
+
23
+ def build_parser() -> argparse.ArgumentParser:
24
+ parser = argparse.ArgumentParser(prog="pictovap")
25
+ sub = parser.add_subparsers(dest="command", required=True)
26
+
27
+ sub.add_parser("demo", help="Run the built-in credential-free example")
28
+
29
+ plan = sub.add_parser("plan", help="Create a visual plan for a Markdown article")
30
+ plan.add_argument("--article", required=True, help="Path to a Markdown article")
31
+ plan.add_argument("--profile", help="Path to a Publisher Profile YAML")
32
+ plan.add_argument("--output", help="Path to write the JSON output plan")
33
+ plan.add_argument("--report", help="Path to write the Markdown report")
34
+
35
+ report = sub.add_parser("report", help="Generate an editor-readable Markdown report from a plan")
36
+ report.add_argument("--plan", required=True, help="Path to visual-plan.json")
37
+ report.add_argument("--output", required=True, help="Path to write the output report.md")
38
+
39
+ return parser
40
+
41
+
42
+ def main() -> int:
43
+ parser = build_parser()
44
+ args = parser.parse_args()
45
+
46
+ if args.command == "demo":
47
+ run_demo()
48
+ return 0
49
+
50
+ if args.command == "plan":
51
+ try:
52
+ plan_output = create_visual_plan(
53
+ article=args.article,
54
+ profile=args.profile,
55
+ output=args.output,
56
+ report=args.report,
57
+ )
58
+ except FileNotFoundError as e:
59
+ print(f"Error: {e}", file=sys.stderr)
60
+ return 1
61
+ except Exception as e:
62
+ print(f"Error running plan: {e}", file=sys.stderr)
63
+ return 1
64
+ if not args.output:
65
+ _print_json(plan_output)
66
+ return 0
67
+
68
+ if args.command == "report":
69
+ try:
70
+ generate_report_from_file(args.plan, args.output)
71
+ return 0
72
+ except Exception as e:
73
+ print(f"Error generating report: {e}", file=sys.stderr)
74
+ return 1
75
+
76
+ parser.error(f"unknown command: {args.command}")
77
+ return 2
78
+
79
+
80
+ if __name__ == "__main__":
81
+ raise SystemExit(main())
File without changes
@@ -0,0 +1,76 @@
1
+ """
2
+ Formal adapter contracts for Pictovap.
3
+
4
+ Pictovap's core pipeline (Visual Brief -> Fit Score -> Provenance Pack ->
5
+ CMS Placement) has no dependency on any specific image provider or CMS.
6
+ Everything external plugs in through one of the protocols defined here.
7
+
8
+ These are `typing.Protocol` classes: an adapter does not need to inherit
9
+ from them, it only needs to implement the matching methods (structural
10
+ typing / duck typing). They exist so that:
11
+
12
+ - the required shape of an adapter is documented in one importable place
13
+ - `isinstance(obj, ImageSourceAdapter)` works for runtime checks
14
+ - IDEs and type checkers can validate third-party adapters
15
+
16
+ See docs/adapters/overview.md for the conceptual model, and
17
+ docs/contributing/adapters.md for a walkthrough of writing a new one.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from typing import Any, Dict, List, Protocol, runtime_checkable
23
+
24
+ from pictova.core.primitives import CMSPlacement
25
+
26
+
27
+ @runtime_checkable
28
+ class ImageSourceAdapter(Protocol):
29
+ """Supplies candidate images to the Fit Score stage.
30
+
31
+ Implementations may call a local folder, a stock photo API, a DAM, or
32
+ any other source. They must never require credentials to import or
33
+ construct — missing credentials should surface as an empty result or
34
+ a clear error only when a search is actually attempted, so the
35
+ credential-free demo path keeps working.
36
+ """
37
+
38
+ def search_candidates(self, query: str, count: int) -> List[Dict[str, Any]]:
39
+ """Return up to `count` candidate images matching `query`.
40
+
41
+ Each candidate dict must contain at least:
42
+ id, filename, provider, source_type ("local" | "api" | "url"),
43
+ local_path (str | None), source_url (str | None), license,
44
+ attribution (str | None), keywords (list[str]), width, height
45
+ """
46
+ ...
47
+
48
+
49
+ @runtime_checkable
50
+ class CMSAdapter(Protocol):
51
+ """Consumes a CMS Placement plan and executes it against a real CMS.
52
+
53
+ A CMS adapter translates Pictovap's CMS-agnostic placement plan into
54
+ the target platform's native representation (e.g. a WordPress
55
+ Gutenberg block, a Ghost mobiledoc card, a Strapi component).
56
+ """
57
+
58
+ def place(self, placement: CMSPlacement) -> Dict[str, Any]:
59
+ """Execute the placement plan. Returns a dict with at least:
60
+ placed (list), failed (list), warnings (list)
61
+ """
62
+ ...
63
+
64
+
65
+ @runtime_checkable
66
+ class ReportRenderer(Protocol):
67
+ """Renders a visual plan (JSON-shaped dict) into a human- or
68
+ machine-facing output format (Markdown, HTML, a CMS payload, etc.).
69
+ """
70
+
71
+ def render(self, plan: Dict[str, Any]) -> str:
72
+ """Return the rendered report as a string."""
73
+ ...
74
+
75
+
76
+ __all__ = ["ImageSourceAdapter", "CMSAdapter", "ReportRenderer"]