@introspection-ai/operator 0.1.2 → 0.1.4
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.
- package/README.md +13 -5
- package/SYSTEM.md +1 -1
- package/bin/introspection-operator.js +9 -27
- package/extensions/case-runs/index.mjs +6 -1
- package/extensions/shared/recipe-session.mjs +29 -0
- package/extensions/workspace/index.mjs +38 -0
- package/extensions/workspace/workspace.mjs +55 -0
- package/package.json +11 -24
- package/skills/build-draft/references/capabilities.md +1 -1
- package/skills/build-draft/references/documents.md +8 -69
- package/skills/build-draft/references/failures.md +1 -1
- package/bin/local-workspace.mjs +0 -62
- package/python/pyproject.toml +0 -17
- package/python/uv.lock +0 -369
- package/skills/build-draft/references/view_docx.py +0 -138
package/README.md
CHANGED
|
@@ -20,20 +20,28 @@ npx @introspection-ai/operator ~/work/my-agent # start or resume a buil
|
|
|
20
20
|
npx @introspection-ai/operator ~/work/my-agent --model <model> # flags after the folder go to Pi
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
`npx @introspection-ai/operator` runs the package's launcher, `bin/introspection-operator.js`. It starts the build agent (`pi --recipe <the package> --agent build --no-context-files
|
|
23
|
+
`npx @introspection-ai/operator` runs the package's launcher, `bin/introspection-operator.js`. It starts the build agent (`pi --recipe <the package> --agent build --no-context-files`) in a folder of its own, because build treats the folder it starts in as the owner's workspace: it creates the agent's repository there and resumes from what it finds there.
|
|
24
24
|
- **No AGENTS.md or CLAUDE.md:** it turns off Pi's loading of those files from that folder and the folders above it. They're written for coding agents and can describe other agents, which build must not copy.
|
|
25
25
|
- **Folder safety:** it refuses a folder inside the package or nested in another git repository; the agent's own repository is allowed, to resume.
|
|
26
|
-
- **Python:** it
|
|
27
|
-
- **Shared documents:** it creates `files/` and `outputs/` in the build folder, beside the agent's repository
|
|
26
|
+
- **Python:** it checks that `uv` is installed. The Operator has no Python of its own: each documents package brings its own, and Pi builds it when the session starts (Recipes 0.39.0 and later).
|
|
27
|
+
- **Shared documents:** it creates `files/` and `outputs/` in the build folder, beside the agent's repository. The Recipe's workspace extension (`extensions/workspace`) tells the agent where they are, as the cloud does with `/workspace/files` and `/workspace/outputs`. Put the documents you'll share in `files/`: the documents tool opens files only inside the build folder. Given a path elsewhere, the agent copies the file into `files/` first.
|
|
28
28
|
- **Versions:** it checks that Pi's `@introspection-ai/recipes` satisfies the `peerDependencies` range, and says to run `introspection upgrade` when it doesn't.
|
|
29
29
|
|
|
30
30
|
Set `INTROSPECTION_AGENTS_DIR` to put new builds somewhere other than `~/.introspection/agents`.
|
|
31
31
|
|
|
32
32
|
In a checkout of this repository, `pnpm build` runs the same launcher, and installs the dependencies with pnpm once.
|
|
33
33
|
|
|
34
|
+
The launcher is being retired. `introspection local`, in a folder with no Recipe, starts the same session from the copy `pi install npm:@introspection-ai/operator` puts in Pi's package folder, which `introspection setup` installs.
|
|
35
|
+
|
|
36
|
+
### Installed with `pi install`
|
|
37
|
+
|
|
38
|
+
`package.json#pi` is read twice: by Recipes when the package runs as a Recipe, and by Pi when it's installed as a Pi package, which loads its extensions and skills in every session.
|
|
39
|
+
- **Extensions** (`extensions/case-runs`, `extensions/workspace`) act only where Recipes loads them: each asks Recipes for its session (`getRecipeSessionContext`), and an instance Pi loaded as a plain package has none, so it registers nothing. The workspace extension acts only in the Operator's own `build` session.
|
|
40
|
+
- **Skills** are listed in `pi.skills`, because an explicit `pi` block turns off Pi's discovery of `skills/`. Pi then offers them in every session, including an owner's own Recipe runs. Pass `--no-skills` to a Recipe launch to keep them out: Recipes still adds the Recipe's own skills.
|
|
41
|
+
|
|
34
42
|
## Package
|
|
35
43
|
|
|
36
|
-
`@introspection-ai/operator` is the npm package published from this repository's root. It contains the Recipe a person runs (`SYSTEM.md`, `agents/`, `skills
|
|
44
|
+
`@introspection-ai/operator` is the npm package published from this repository's root. It contains the Recipe a person runs (`SYSTEM.md`, `agents/`, `skills/` and `extensions/`) and its launcher (`bin/`), so `npx @introspection-ai/operator` starts a build, and `npx skills sync` finds the skills in it. `docs/`, `scripts/` and the evals are never published.
|
|
37
45
|
|
|
38
46
|
Skills are grouped by the stage of an agent's life (see [`docs/DESIGN.md`](docs/DESIGN.md)), and the group is the prefix of each skill's name, because `npx skills sync` finds skills only at `skills/<name>/SKILL.md` and not in nested folders:
|
|
39
47
|
|
|
@@ -45,7 +53,7 @@ Skills are grouped by the stage of an agent's life (see [`docs/DESIGN.md`](docs/
|
|
|
45
53
|
| `optimize` | `optimize-quality`, `optimize-cost`, `optimize-latency` | Raise quality, then cut cost, then latency, each holding the gains of the one before | Designed; replaces today's `optimize` |
|
|
46
54
|
| `harden` | `harden-scan`, `harden-spar`, `harden-stress` | Last, and optional apart from the scan: check the Recipe against the OWASP Agentic Skills Top 10, spar with it as a red team, and test it under load; failures become permanent cases | Designed; new, with no workflow behind it today |
|
|
47
55
|
|
|
48
|
-
Releases are cut by release-please (`.github/workflows/release.yml`): Conventional Commit titles on `main` update a release pull request, and merging it tags `operator-vX.Y.Z` and publishes to npm through trusted publishing, starting at 0.1.0. CI runs `node scripts/check-skills.mjs` (frontmatter, folder names, and that exactly the Recipe and its launcher are packed: `skills/`, `agents/`, `SYSTEM.md
|
|
56
|
+
Releases are cut by release-please (`.github/workflows/release.yml`): Conventional Commit titles on `main` update a release pull request, and merging it tags `operator-vX.Y.Z` and publishes to npm through trusted publishing, starting at 0.1.0. CI runs `node scripts/check-skills.mjs` (frontmatter, folder names, and that exactly the Recipe and its launcher are packed: `skills/`, `agents/`, `extensions/`, `SYSTEM.md` and `bin/introspection-operator.js`; that `pi.skills` lists `skills`; and that there's no `pi.runtime.python`) and `npm pack --dry-run`; publishing also requires at least one skill.
|
|
49
57
|
|
|
50
58
|
## License
|
|
51
59
|
|
package/SYSTEM.md
CHANGED
|
@@ -6,6 +6,6 @@ Owners are usually business owners, not engineers. Speak plainly, ask only what
|
|
|
6
6
|
|
|
7
7
|
When you need a document from the owner, ask them to share it: as an upload, unless the workspace says how this owner shares files. Documents the owner gives you are of two kinds. The owner's own standing material (their playbook, guidelines, standard terms, templates) is meant to be built into the agent: read it when they give it to you and commit it with the Recipe. Material that arrives with a request (a customer's contract, an inbox) is a case input: read it where it was shared, refer to it by content hash, and never commit it or copy it into the agent's repository.
|
|
8
8
|
|
|
9
|
-
To read or show a Word or PDF document, use the `documents` tool: it reads text, tables and comments, renders scanned pages as images, and for Word makes tracked changes and comments, so you can show the owner a real example markup on their own contract.
|
|
9
|
+
To read or show a Word or PDF document, use the `documents` tool: it reads text, tables and comments, renders scanned pages as images, and for Word makes tracked changes and comments, so you can show the owner a real example markup on their own contract. Don't use Pi's `read` tool, shell PDF tools or Python scripts for Word or PDF files. Never call a document unreadable or image-based without reading it with the tool, and rendering its pages when it has no text; if it truly has no text, say so plainly and ask for another copy.
|
|
10
10
|
|
|
11
11
|
Never enter or ask to see credentials, and never push, deploy or connect real data unless the current step says to.
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
//
|
|
8
8
|
// In a checkout of this repository, `pnpm build` runs this same script.
|
|
9
9
|
//
|
|
10
|
+
// Being retired: `introspection local`, in a folder with no Recipe, starts the Operator the same way, from the
|
|
11
|
+
// package `pi install` put in Pi's package folder. This launcher goes once that CLI release is out.
|
|
12
|
+
//
|
|
10
13
|
// Build treats the folder it starts in as the owner's workspace: it creates the agent's repository
|
|
11
14
|
// there and resumes from what it finds, so it must not start inside this package or another repository.
|
|
12
15
|
import { execFileSync, spawnSync } from "node:child_process";
|
|
13
|
-
import { createHash } from "node:crypto";
|
|
14
16
|
import { existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
|
|
15
17
|
import { homedir } from "node:os";
|
|
16
18
|
import { delimiter, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
@@ -71,30 +73,10 @@ if (min) {
|
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
// The
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// when the pins change and versions sit side by side.
|
|
79
|
-
const python = pkg.pi?.runtime?.python;
|
|
80
|
-
if (python) {
|
|
81
|
-
if (!has("uv")) fail("uv is not installed; the documents tool needs it. Install it: https://docs.astral.sh/uv/getting-started/installation/");
|
|
82
|
-
const project = join(root, python.project);
|
|
83
|
-
const lock = readFileSync(join(root, python.lockfile));
|
|
84
|
-
const key = createHash("sha256").update(lock).digest("hex").slice(0, 12);
|
|
85
|
-
const venv = join(homedir(), ".introspection", "operator-python", `${pkg.version}-${key}`);
|
|
86
|
-
const uvEnv = { ...env, UV_PROJECT_ENVIRONMENT: venv };
|
|
87
|
-
const sync = spawnSync("uv", ["sync", "--frozen", "--no-install-project", "--quiet", "--project", project], { env: uvEnv, stdio: "inherit", shell: process.platform === "win32" });
|
|
88
|
-
if (sync.status !== 0) fail(`couldn't build the Recipe's Python environment from ${join(root, python.lockfile)}`);
|
|
89
|
-
const bin = join(venv, process.platform === "win32" ? "Scripts" : "bin");
|
|
90
|
-
env.VIRTUAL_ENV = venv;
|
|
91
|
-
env.PATH = [bin, env.PATH].join(delimiter);
|
|
92
|
-
delete env.PYTHONHOME;
|
|
93
|
-
const imports = python.imports ?? [];
|
|
94
|
-
if (imports.length > 0) {
|
|
95
|
-
const check = spawnSync(join(bin, "python"), ["-c", imports.map((name) => `import ${name}`).join("; ")], { env, stdio: "inherit" });
|
|
96
|
-
if (check.status !== 0) fail(`the Recipe's Python environment is missing one of: ${imports.join(", ")}`);
|
|
97
|
-
}
|
|
76
|
+
// The documents packages (package.json#pi.documents) bring their own Python: Pi builds it with uv when the
|
|
77
|
+
// session starts (Recipes 0.39.0 and later; the peer check above requires 0.40.0), so only uv has to be here.
|
|
78
|
+
if (pkg.pi?.documents?.length && !has("uv")) {
|
|
79
|
+
fail("uv is not installed; the documents tool needs it. Install it: https://docs.astral.sh/uv/getting-started/installation/");
|
|
98
80
|
}
|
|
99
81
|
|
|
100
82
|
// The folder: the first argument when it isn't a flag, else the next new-<n>. A relative folder resolves
|
|
@@ -135,13 +117,13 @@ mkdirSync(target, { recursive: true });
|
|
|
135
117
|
target = realpathSync(target);
|
|
136
118
|
// The local equivalent of the cloud's workspace: files/ for the documents the owner shares (the documents tool
|
|
137
119
|
// opens files only inside the build folder) and outputs/ for what the agent produces, both beside the agent's
|
|
138
|
-
// repository, not in it.
|
|
120
|
+
// repository, not in it. The Recipe's workspace extension (extensions/workspace) tells the agent where they are.
|
|
139
121
|
for (const dir of ["files", "outputs"]) mkdirSync(join(target, dir), { recursive: true });
|
|
140
122
|
console.error(`introspection-operator: put the documents you'll share in ${join(target, "files")}`);
|
|
141
123
|
console.error(`introspection-operator: starting in ${target}`);
|
|
142
124
|
// Pi would load AGENTS.md and CLAUDE.md from this folder and every folder above it. Those are written for
|
|
143
125
|
// coding agents and can describe other agents, which build must not copy; the Recipe brings its own.
|
|
144
|
-
const result = spawnSync("pi", ["--recipe", root, "--agent", "build", "--no-context-files",
|
|
126
|
+
const result = spawnSync("pi", ["--recipe", root, "--agent", "build", "--no-context-files", ...args], {
|
|
145
127
|
cwd: target,
|
|
146
128
|
env,
|
|
147
129
|
stdio: "inherit",
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
// Tools the build agent runs an agent's cases with: run_case starts one run of the Recipe being built in the
|
|
2
2
|
// background, case_status says what it's doing, stop_case ends it. The runs themselves are in runs.mjs, and
|
|
3
3
|
// what their events mean in events.mjs.
|
|
4
|
+
//
|
|
5
|
+
// They load only where Recipes loads them, as one of the Recipe's extensions. Installed with `pi install`, Pi
|
|
6
|
+
// also loads them in every session, where they register nothing (recipe-session.mjs).
|
|
4
7
|
import { relative } from "node:path";
|
|
5
8
|
import { Type } from "typebox";
|
|
6
9
|
import { minutes } from "./events.mjs";
|
|
7
10
|
import { createCaseRuns, DEFAULT_BUDGET_MINUTES, MAX_WAIT_SECONDS } from "./runs.mjs";
|
|
11
|
+
import { recipeSession } from "../shared/recipe-session.mjs";
|
|
8
12
|
|
|
9
13
|
function text(value) {
|
|
10
14
|
return { content: [{ type: "text", text: value }], details: {} };
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
export default function caseRuns(pi) {
|
|
17
|
+
export default async function caseRuns(pi) {
|
|
18
|
+
if (!(await recipeSession(pi))) return;
|
|
14
19
|
const caseRuns = createCaseRuns();
|
|
15
20
|
|
|
16
21
|
function find(id) {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Which Recipe session, if any, loaded an extension instance.
|
|
2
|
+
//
|
|
3
|
+
// The Operator runs as a Recipe (`introspection init --operator` starts `pi --recipe <operator>`), and only then
|
|
4
|
+
// should its extensions act. Recipes binds a session context to every extension instance it loads
|
|
5
|
+
// (`getRecipeSessionContext`); an instance without one, or from another Recipe, does nothing.
|
|
6
|
+
//
|
|
7
|
+
// The import is static on purpose: Recipes' loader points a static import of `@introspection-ai/recipes` at the
|
|
8
|
+
// host's copy, which a dynamic `import()` from the Operator's own folder can't reach once the Operator is installed
|
|
9
|
+
// without its peers (`~/.introspection/operator`).
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
|
|
12
|
+
import { getRecipeSessionContext } from "@introspection-ai/recipes/extensions";
|
|
13
|
+
|
|
14
|
+
/** The name the package runs under as a Recipe: its package.json name. */
|
|
15
|
+
export const OPERATOR = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8")).name;
|
|
16
|
+
|
|
17
|
+
/** The Recipe session context bound to this instance, or undefined when Recipes didn't load it. */
|
|
18
|
+
export async function recipeSession(pi) {
|
|
19
|
+
try {
|
|
20
|
+
return getRecipeSessionContext(pi);
|
|
21
|
+
} catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** True for the Operator's own build session: this Recipe, its build agent, and the root session. */
|
|
27
|
+
export function isOperatorBuild(session) {
|
|
28
|
+
return session?.recipe?.name === OPERATOR && session?.agent?.name === "build" && session?.session?.role === "root";
|
|
29
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Tells the Operator's build agent where the local workspace's folders are, as the cloud host does for every
|
|
2
|
+
// session, so the Recipe itself says the same thing locally and in the cloud and holds no local paths. It also
|
|
3
|
+
// creates files/ and outputs/ when they're missing, and keeps the build agent's launch out of the commands it runs
|
|
4
|
+
// (workspace.mjs).
|
|
5
|
+
//
|
|
6
|
+
// It acts only in the Operator's own build session (recipe-session.mjs). Installed with `pi install`, Pi loads it
|
|
7
|
+
// in every session, where it does nothing.
|
|
8
|
+
//
|
|
9
|
+
// It adds a message to the conversation rather than changing the system prompt: with a root SYSTEM.md, the
|
|
10
|
+
// Recipes extension replaces Pi's whole prompt, so appended text (`--append-system-prompt`, or a
|
|
11
|
+
// before_agent_start handler that runs first) never reaches the model. The message is added once per session,
|
|
12
|
+
// so continuing a session with `-c` doesn't repeat it.
|
|
13
|
+
import { isOperatorBuild, recipeSession } from "../shared/recipe-session.mjs";
|
|
14
|
+
import { ensureFolders, MESSAGE_TYPE, withoutOperatorEnv, workspaceMessage } from "./workspace.mjs";
|
|
15
|
+
|
|
16
|
+
export default async function workspace(pi) {
|
|
17
|
+
registerWorkspace(pi, await recipeSession(pi));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Register the workspace handlers when the session is the Operator's build session; else do nothing. */
|
|
21
|
+
export function registerWorkspace(pi, session) {
|
|
22
|
+
if (!isOperatorBuild(session)) return false;
|
|
23
|
+
// Recipes loads its extensions as the session starts, in the build folder: create the folders now, so the
|
|
24
|
+
// owner can put documents in files/ before the first message, and again before each turn in case they went.
|
|
25
|
+
ensureFolders(process.cwd());
|
|
26
|
+
pi.on("tool_call", (event) => {
|
|
27
|
+
if (event.toolName === "bash" && typeof event.input?.command === "string") {
|
|
28
|
+
event.input.command = withoutOperatorEnv(event.input.command);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
pi.on("before_agent_start", (_event, ctx) => {
|
|
32
|
+
const root = ctx.cwd ?? process.cwd();
|
|
33
|
+
ensureFolders(root);
|
|
34
|
+
if (ctx.sessionManager.getEntries().some((entry) => entry.type === "custom_message" && entry.customType === MESSAGE_TYPE)) return;
|
|
35
|
+
return { message: { customType: MESSAGE_TYPE, content: workspaceMessage(root), display: false } };
|
|
36
|
+
});
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// The local workspace for a build on the owner's computer: the part of the workspace extension that doesn't need
|
|
2
|
+
// Pi, so it can be tested on its own.
|
|
3
|
+
import { mkdirSync } from "node:fs";
|
|
4
|
+
import { delimiter, join } from "node:path";
|
|
5
|
+
|
|
6
|
+
export const MESSAGE_TYPE = "operator-workspace";
|
|
7
|
+
|
|
8
|
+
// Commands the agent runs must not inherit the build agent's own launch. The Recipes extension exports
|
|
9
|
+
// PI_AGENT_NAME (`build`) for shell tools, and a Recipe launch reads it as its default agent, so
|
|
10
|
+
// `introspection local` in the agent's repository would look for an agent named `build` there and not start.
|
|
11
|
+
//
|
|
12
|
+
// The same goes for an activated Python: a Recipe run with `introspection local` that inherits one uses it, so it
|
|
13
|
+
// passes without an environment of its own and fails for its owner and in the cloud. The Operator declares no
|
|
14
|
+
// Python of its own (each documents package brings its own, which is never activated), but the shell Pi started
|
|
15
|
+
// in may have one.
|
|
16
|
+
const UNSET = ["PI_AGENT_NAME", "VIRTUAL_ENV"];
|
|
17
|
+
|
|
18
|
+
/** The command with the Operator's launch removed from its environment. Windows shells are left as they are. */
|
|
19
|
+
export function withoutOperatorEnv(command, env = process.env, platform = process.platform) {
|
|
20
|
+
if (platform === "win32") return command;
|
|
21
|
+
const unset = `unset ${UNSET.join(" ")}`;
|
|
22
|
+
if (!env.VIRTUAL_ENV) return `${unset}\n${command}`;
|
|
23
|
+
const bin = join(env.VIRTUAL_ENV, "bin");
|
|
24
|
+
const path = (env.PATH ?? "").split(delimiter).filter((dir) => dir !== bin).join(delimiter);
|
|
25
|
+
return `${unset}; export PATH='${path.replaceAll("'", `'\\''`)}'\n${command}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Create files/ and outputs/ beside the agent's repository, if they're missing. */
|
|
29
|
+
export function ensureFolders(root) {
|
|
30
|
+
for (const dir of ["files", "outputs"]) mkdirSync(join(root, dir), { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* What the build agent is told about the workspace, as the cloud host tells every session (introspection-cloud
|
|
35
|
+
* apps/runtime-agent/runtime/resources/context.ts, "Managed workspace").
|
|
36
|
+
*/
|
|
37
|
+
export function workspaceMessage(root) {
|
|
38
|
+
const files = join(root, "files");
|
|
39
|
+
const outputs = join(root, "outputs");
|
|
40
|
+
return [
|
|
41
|
+
"## Managed workspace",
|
|
42
|
+
"",
|
|
43
|
+
"<workspace>",
|
|
44
|
+
` <inputs path="${files}" access="read_write" persistence="local" />`,
|
|
45
|
+
` <outputs path="${outputs}" persistence="local" />`,
|
|
46
|
+
" Create the agent's repository in this folder, beside files/ and outputs/.",
|
|
47
|
+
"</workspace>",
|
|
48
|
+
`This build runs on the owner's computer, and the documents tool opens files only inside ${root}. ` +
|
|
49
|
+
`The owner shares a document by giving you its path, or by putting it in ${files}: ask for it that way ` +
|
|
50
|
+
`("send me the path to it, or put it in ${files}"), not as an upload. ` +
|
|
51
|
+
"When the owner gives you a path to a file outside files/, copy it into files/ first and read the copy; " +
|
|
52
|
+
"don't try the original path, which the tool refuses. Never copy a file straight into the agent's repository. " +
|
|
53
|
+
"What belongs in the Recipe is added from files/.",
|
|
54
|
+
].join("\n");
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@introspection-ai/operator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "The Introspection Operator: a Recipe and skills that build an agent with its owner (brainstorm, draft and review).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -20,16 +20,18 @@
|
|
|
20
20
|
"agents",
|
|
21
21
|
"SYSTEM.md",
|
|
22
22
|
"bin",
|
|
23
|
-
"extensions"
|
|
24
|
-
"python/pyproject.toml",
|
|
25
|
-
"python/uv.lock"
|
|
23
|
+
"extensions"
|
|
26
24
|
],
|
|
27
25
|
"publishConfig": {
|
|
28
26
|
"access": "public"
|
|
29
27
|
},
|
|
30
28
|
"pi": {
|
|
31
29
|
"extensions": [
|
|
32
|
-
"extensions/case-runs"
|
|
30
|
+
"extensions/case-runs",
|
|
31
|
+
"extensions/workspace"
|
|
32
|
+
],
|
|
33
|
+
"skills": [
|
|
34
|
+
"skills"
|
|
33
35
|
],
|
|
34
36
|
"documents": [
|
|
35
37
|
{
|
|
@@ -38,31 +40,16 @@
|
|
|
38
40
|
{
|
|
39
41
|
"format": "pdf"
|
|
40
42
|
}
|
|
41
|
-
]
|
|
42
|
-
"runtime": {
|
|
43
|
-
"python": {
|
|
44
|
-
"project": "python",
|
|
45
|
-
"lockfile": "python/uv.lock",
|
|
46
|
-
"version": ">=3.12,<3.15",
|
|
47
|
-
"imports": [
|
|
48
|
-
"docx",
|
|
49
|
-
"pypdf",
|
|
50
|
-
"pypdfium2",
|
|
51
|
-
"PIL"
|
|
52
|
-
]
|
|
53
|
-
}
|
|
54
|
-
}
|
|
43
|
+
]
|
|
55
44
|
},
|
|
56
45
|
"type": "module",
|
|
57
46
|
"scripts": {
|
|
58
47
|
"build": "node bin/introspection-operator.js"
|
|
59
48
|
},
|
|
60
49
|
"peerDependencies": {
|
|
61
|
-
"@introspection-ai/recipes": ">=0.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"@introspection-ai/recipe-documents-docx": ">=0.1.0",
|
|
65
|
-
"@introspection-ai/recipe-documents-pdf": ">=0.1.0"
|
|
50
|
+
"@introspection-ai/recipes": ">=0.40.0",
|
|
51
|
+
"@introspection-ai/recipe-documents-docx": ">=0.3.0",
|
|
52
|
+
"@introspection-ai/recipe-documents-pdf": ">=0.2.0"
|
|
66
53
|
},
|
|
67
54
|
"packageManager": "pnpm@12.9.1",
|
|
68
55
|
"bin": {
|
|
@@ -4,7 +4,7 @@ Check this list before writing code. Each entry says when a case needs it.
|
|
|
4
4
|
|
|
5
5
|
| Capability | Use when a case needs to | How a Recipe gets it |
|
|
6
6
|
| --- | --- | --- |
|
|
7
|
-
| `documents` | read, edit with tracked changes, comment on or compare Word or PDF files | `pi.documents` with a `format` (`docx`, `pdf`) per entry,
|
|
7
|
+
| `documents` | read, edit with tracked changes, comment on or compare Word or PDF files | `pi.documents` with a `format` (`docx`, `pdf`) per entry, and the format's package `@introspection-ai/recipe-documents-<format>` as a peer (Recipes 0.40.0 or later installs it alongside itself); for contract redlines add `"profile": "legal-redlining-en-US"` to the docx entry. If the CLI or Recipes is too old, run `introspection upgrade`; see [documents](documents.md). For PDFs with tables, add the pdf package's `tables` extra |
|
|
8
8
|
| Channels | receive or answer messages in Slack or another chat surface | a channel adapter package (e.g. `@introspection-ai/recipe-channel-slack`) as a dependency, and the channel's declaration in `package.json#pi` |
|
|
9
9
|
| MCP connectors | read or write in a service (email, Drive, a CRM, an internal API) | an MCP declaration in the Recipe; locally a fake, on the platform a connection the owner makes in deploy |
|
|
10
10
|
| Scheduling | run on a timetable or once at a set time | a platform automation created at deploy, not code in the Recipe |
|
|
@@ -2,84 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
Plain text loses what a reviewer needs: a normal paragraph read drops tracked insertions and deletions without saying so. Change a document with tracked changes, never a clean retype, and never overwrite the original.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## The `documents` tool
|
|
6
6
|
|
|
7
|
-
Declare each format and
|
|
7
|
+
Declare each format, and its package as a peer: Recipes installs the docx and pdf packages alongside itself, so the platform provides them (`@introspection-ai/recipes` 0.40.0 or later):
|
|
8
8
|
|
|
9
9
|
```json
|
|
10
|
-
"
|
|
11
|
-
"@introspection-ai/recipe-documents-docx": ">=0.
|
|
12
|
-
"@introspection-ai/recipe-documents-pdf": ">=0.
|
|
10
|
+
"peerDependencies": {
|
|
11
|
+
"@introspection-ai/recipe-documents-docx": ">=0.4.0",
|
|
12
|
+
"@introspection-ai/recipe-documents-pdf": ">=0.3.0"
|
|
13
13
|
},
|
|
14
14
|
"pi": { "documents": [{ "format": "docx" }, { "format": "pdf" }] }
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
and list `documents` in the agent's `tools`.
|
|
17
|
+
and list `documents` in the agent's `tools`. Pin a package (in `dependencies`, with an exact version) only when the agent must stay on the version it was tested with. The packages bring their own Python, so the Recipe needs no `pi.runtime.python` for documents.
|
|
18
18
|
|
|
19
|
-
For a kind of work a format ships a profile for, add it to that format's entry: `{ "format": "docx", "profile": "legal-redlining-en-US" }` for contract redlines and responses
|
|
19
|
+
For a kind of work a format ships a profile for, add it to that format's entry: `{ "format": "docx", "profile": "legal-redlining-en-US" }` for contract redlines and responses. The tool then offers the profile's skill beside its core one; don't list either in the agent's `skills` or name them in the instructions. Put the owner's own positions and voice in the Recipe's skills, not in a copy of the profile. For other kinds of work, leave `profile` out. A `commands` list on a format narrows what it may do, for example `["read", "comment"]` for an agent that only reviews. Then run `introspection check` and `introspection local -p "hello"`. If both pass, use the tool's commands for reading, redlining, commenting and comparing, and write no scripts for them.
|
|
20
20
|
|
|
21
|
-
If
|
|
22
|
-
|
|
23
|
-
## Fallback: paper-docx in the Recipe's Python
|
|
24
|
-
|
|
25
|
-
`paper-docx` is a fork of python-docx that owns the `docx` import. Never install upstream `python-docx` beside it. Ask the library for its API: `help(docx.search.Span.replace)`.
|
|
26
|
-
|
|
27
|
-
1. Declare the project and lock it (installed when the runtime is baked, never at run time):
|
|
28
|
-
|
|
29
|
-
```toml
|
|
30
|
-
# python/pyproject.toml
|
|
31
|
-
[project]
|
|
32
|
-
name = "recipe-documents"
|
|
33
|
-
version = "0.1.0"
|
|
34
|
-
requires-python = ">=3.12,<3.15"
|
|
35
|
-
dependencies = ["paper-docx==0.2.0"]
|
|
36
|
-
|
|
37
|
-
[tool.uv]
|
|
38
|
-
constraint-dependencies = ["python-docx<0"]
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
```sh
|
|
42
|
-
uv lock --project python # commit python/pyproject.toml and python/uv.lock
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
```json
|
|
46
|
-
"runtime": { "python": { "project": "python", "lockfile": "python/uv.lock", "version": ">=3.12,<3.15", "imports": ["docx"] } }
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
(in `package.json#pi`). For PDFs add `pypdf[crypto]==6.21.4` and `pypdfium2==5.14.0`, with their imports `pypdf` and `pypdfium2`.
|
|
50
|
-
|
|
51
|
-
2. **Reading:** copy [view_docx.py](view_docx.py) into the Recipe as `lib/view_docx.py`. It prints the text with tracked changes as `[+new+]` / `[-old-]` and comments inline, each with author and date, and starts with a count of changes and comments to check against.
|
|
52
|
-
|
|
53
|
-
3. **Editing:** give the agent a `documents` skill with this pattern, and `bash` in its tools:
|
|
54
|
-
|
|
55
|
-
```python
|
|
56
|
-
# python edit_docx.py <original> <new file> <author>
|
|
57
|
-
import sys
|
|
58
|
-
import docx
|
|
59
|
-
from docx.package import pending_changes, text_diff
|
|
60
|
-
from docx.search import find_text
|
|
61
|
-
|
|
62
|
-
original, marked, author = sys.argv[1:4]
|
|
63
|
-
document = docx.Document(original)
|
|
64
|
-
spans = find_text(document, "thirty days")
|
|
65
|
-
if len(spans) != 1: # pass nth= or near= when the text appears more than once
|
|
66
|
-
sys.exit(f"Expected one match, found {len(spans)}")
|
|
67
|
-
spans[0].replace("sixty days", tracked=True, author=author)
|
|
68
|
-
document.save(marked)
|
|
69
|
-
print(pending_changes(marked)) # what the changes do if accepted
|
|
70
|
-
print(text_diff(original, marked))
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
Skill rules: save results as new files in an `outputs/` folder of the workspace (`/workspace/outputs/` on the platform); read every result back with `view_docx.py` before saying it's done; sign changes with the name the owner gave for the markup (ask if none); comments are `document.add_comment(runs, text=..., author=..., initials=...)`; a refusal from the library means unsupported, so say so and never edit raw XML; never accept or reject someone else's changes unless asked; run scripts with `python`, not a login shell (`bash -lc` loses the environment).
|
|
74
|
-
|
|
75
|
-
4. **Running locally:** `introspection local` validates the Python declaration but doesn't build it. Build it and start with it active:
|
|
76
|
-
|
|
77
|
-
```sh
|
|
78
|
-
uv sync --project python
|
|
79
|
-
VIRTUAL_ENV="$PWD/python/.venv" PATH="$PWD/python/.venv/bin:$PATH" introspection local
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Add `python/.venv/` and `__pycache__/` to `.gitignore`.
|
|
21
|
+
If either fails, find the cause before changing the Recipe: an unknown `pi.documents` key or an unknown profile means the installed CLI or Recipes is older than this needs, so run `introspection upgrade`. Never remove a profile, or replace the tool with scripts, to make the agent start; record the failure in Part B and ask the owner to upgrade if you can't.
|
|
83
22
|
|
|
84
23
|
## Inputs
|
|
85
24
|
|
|
@@ -6,7 +6,7 @@ What actually goes wrong when building and proving an agent, and what to do.
|
|
|
6
6
|
|
|
7
7
|
- **A clean `introspection check` doesn't mean it runs.** It checks the package against itself: an MCP server with no endpoint anywhere, or a capability that can't exist, still passes. Only a run proves it.
|
|
8
8
|
- **The check's errors are precise; act on them.** A missing field, an undeclared skill or bad YAML comes with the name and, for YAML, the line and column; an unknown field lists the valid ones. Fix from the message, not by copying another Recipe.
|
|
9
|
-
- **`unknown key` under `package.json#pi`** means the installed CLI doesn't know that capability yet (for example `documents` in CLI 0.63).
|
|
9
|
+
- **`unknown key` under `package.json#pi`** means the installed CLI doesn't know that capability yet (for example `documents` in CLI 0.63). Run `introspection upgrade`; don't work around it. See [documents.md](documents.md).
|
|
10
10
|
- **Model names don't transliterate.** A Recipe names a model as `provider/model`, not a provider's raw API id. Pick it from the documented list, and treat the template's model as a placeholder to decide.
|
|
11
11
|
- **Extension code isn't checked when you write it.** A guessed registration API passes every check and fails at run time. Read the extension contract before writing one, and run it.
|
|
12
12
|
- **"Pi is not installed" can mean Node is too old.** Run `introspection setup` and read what it reports before reinstalling Pi.
|
package/bin/local-workspace.mjs
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// A Pi extension the launcher loads (`pi -e`) for a local build. It tells the build agent where the
|
|
2
|
-
// workspace's folders are, as the cloud host does for every session (introspection-cloud
|
|
3
|
-
// apps/runtime-agent/runtime/resources/context.ts, "Managed workspace"), so the Recipe itself says the same
|
|
4
|
-
// thing locally and in the cloud and holds no local paths.
|
|
5
|
-
//
|
|
6
|
-
// It adds a message to the conversation rather than changing the system prompt: with a root SYSTEM.md, the
|
|
7
|
-
// Recipes extension replaces Pi's whole prompt, so appended text (`--append-system-prompt`, or a
|
|
8
|
-
// before_agent_start handler that runs first) never reaches the model. The message is added once per session,
|
|
9
|
-
// so continuing a session with `-c` doesn't repeat it.
|
|
10
|
-
import { delimiter, join } from "node:path";
|
|
11
|
-
|
|
12
|
-
const TYPE = "operator-workspace";
|
|
13
|
-
|
|
14
|
-
// Commands the agent runs must not inherit the build agent's own launch. The Recipes extension exports
|
|
15
|
-
// PI_AGENT_NAME (`build`) for shell tools, and a Recipe launch reads it as its default agent, so
|
|
16
|
-
// `introspection local` in the agent's repository looks for an agent named `build` there and doesn't start.
|
|
17
|
-
// So every bash command starts by unsetting it. Windows shells are left as they are.
|
|
18
|
-
//
|
|
19
|
-
// The same goes for the Operator's own Python: the launcher starts Pi with it (VIRTUAL_ENV, its bin first on
|
|
20
|
-
// PATH) for the Operator's documents tool. A Recipe run with `introspection local` that inherits it uses the
|
|
21
|
-
// Operator's environment, so it passes without one of its own and fails for its owner and in the cloud.
|
|
22
|
-
const operatorPython = process.env.VIRTUAL_ENV;
|
|
23
|
-
const UNSET = ["PI_AGENT_NAME", "VIRTUAL_ENV"];
|
|
24
|
-
|
|
25
|
-
function withoutOperatorEnv(command) {
|
|
26
|
-
if (process.platform === "win32") return command;
|
|
27
|
-
const unset = `unset ${UNSET.join(" ")}`;
|
|
28
|
-
if (!operatorPython) return `${unset}\n${command}`;
|
|
29
|
-
const bin = join(operatorPython, "bin");
|
|
30
|
-
const path = (process.env.PATH ?? "").split(delimiter).filter((dir) => dir !== bin).join(delimiter);
|
|
31
|
-
return `${unset}; export PATH='${path.replaceAll("'", `'\\''`)}'\n${command}`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export default function localWorkspace(pi) {
|
|
35
|
-
pi.on("tool_call", (event) => {
|
|
36
|
-
if (event.toolName === "bash" && typeof event.input?.command === "string") {
|
|
37
|
-
event.input.command = withoutOperatorEnv(event.input.command);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
pi.on("before_agent_start", (_event, ctx) => {
|
|
41
|
-
if (ctx.sessionManager.getEntries().some((entry) => entry.type === "custom_message" && entry.customType === TYPE)) return;
|
|
42
|
-
const root = ctx.cwd ?? process.cwd();
|
|
43
|
-
const files = join(root, "files");
|
|
44
|
-
const outputs = join(root, "outputs");
|
|
45
|
-
const content = [
|
|
46
|
-
"## Managed workspace",
|
|
47
|
-
"",
|
|
48
|
-
"<workspace>",
|
|
49
|
-
` <inputs path="${files}" access="read_write" persistence="local" />`,
|
|
50
|
-
` <outputs path="${outputs}" persistence="local" />`,
|
|
51
|
-
" Create the agent's repository in this folder, beside files/ and outputs/.",
|
|
52
|
-
"</workspace>",
|
|
53
|
-
`This build runs on the owner's computer, and the documents tool opens files only inside ${root}. ` +
|
|
54
|
-
`The owner shares a document by giving you its path, or by putting it in ${files}: ask for it that way ` +
|
|
55
|
-
`("send me the path to it, or put it in ${files}"), not as an upload. ` +
|
|
56
|
-
"When the owner gives you a path to a file outside files/, copy it into files/ first and read the copy; " +
|
|
57
|
-
"don't try the original path, which the tool refuses. Never copy a file straight into the agent's repository. " +
|
|
58
|
-
"What belongs in the Recipe is added from files/.",
|
|
59
|
-
].join("\n");
|
|
60
|
-
return { message: { customType: TYPE, content, display: false } };
|
|
61
|
-
});
|
|
62
|
-
}
|
package/python/pyproject.toml
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# The Python the Recipe's `documents` tool runs on: paper-docx for Word, and pypdf, pypdfium2 and pillow for
|
|
2
|
-
# PDF. Declared in package.json#pi.runtime.python; the launcher builds it with `uv sync --frozen`.
|
|
3
|
-
[project]
|
|
4
|
-
name = "introspection-operator-runtime"
|
|
5
|
-
version = "0.0.0"
|
|
6
|
-
requires-python = ">=3.12,<3.15"
|
|
7
|
-
dependencies = [
|
|
8
|
-
"paper-docx==0.2.0",
|
|
9
|
-
"pypdf[crypto]==6.21.4",
|
|
10
|
-
"pypdfium2==5.14.0",
|
|
11
|
-
"pillow==13.0.0",
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
[tool.uv]
|
|
15
|
-
package = false
|
|
16
|
-
# paper-docx provides the `docx` module; python-docx would shadow it.
|
|
17
|
-
constraint-dependencies = ["python-docx<0"]
|
package/python/uv.lock
DELETED
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
version = 1
|
|
2
|
-
revision = 5
|
|
3
|
-
requires-python = ">=3.12, <3.15"
|
|
4
|
-
|
|
5
|
-
[options]
|
|
6
|
-
exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values.
|
|
7
|
-
exclude-newer-span = "P3D"
|
|
8
|
-
|
|
9
|
-
[options.exclude-newer-package]
|
|
10
|
-
introspection-harbor = false
|
|
11
|
-
introspection-recipe-check = false
|
|
12
|
-
introspection-remote-proto = false
|
|
13
|
-
introspection-sdk = false
|
|
14
|
-
|
|
15
|
-
[manifest]
|
|
16
|
-
constraints = [{ name = "python-docx", specifier = "<0" }]
|
|
17
|
-
|
|
18
|
-
[[package]]
|
|
19
|
-
name = "cffi"
|
|
20
|
-
version = "2.1.1"
|
|
21
|
-
source = { registry = "https://pypi.org/simple" }
|
|
22
|
-
dependencies = [
|
|
23
|
-
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
|
|
24
|
-
]
|
|
25
|
-
sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" }
|
|
26
|
-
wheels = [
|
|
27
|
-
{ url = "https://files.pythonhosted.org/packages/10/69/43965eccfdead3b9220015fd1320e117be8c6ed01a62ffab76eeb752f5d5/cffi-2.1.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0", size = 184821, upload-time = "2026-08-03T21:19:44.887Z" },
|
|
28
|
-
{ url = "https://files.pythonhosted.org/packages/54/7d/16e5a096677b5e313ca80cd5e5170efa3ea44624a82bb111925522da64b1/cffi-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf", size = 184719, upload-time = "2026-08-03T21:19:46.129Z" },
|
|
29
|
-
{ url = "https://files.pythonhosted.org/packages/56/e6/8941622732edec876dd17d0453dce07317ae96db34f2ec1436c9d3785986/cffi-2.1.1-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a", size = 214799, upload-time = "2026-08-03T21:19:47.218Z" },
|
|
30
|
-
{ url = "https://files.pythonhosted.org/packages/44/de/f98430906df1545ffde0d543dd124a7a439bc2cd32b36b9c53f805df7333/cffi-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890", size = 222389, upload-time = "2026-08-03T21:19:48.331Z" },
|
|
31
|
-
{ url = "https://files.pythonhosted.org/packages/6a/5b/717f1526b9957b34456313c31645c5b82b8fb5c3fe9e4752999be7128bfc/cffi-2.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50", size = 210249, upload-time = "2026-08-03T21:19:49.543Z" },
|
|
32
|
-
{ url = "https://files.pythonhosted.org/packages/64/b3/f8aa4f3e34986c7e4ec45072d1b1b9dd295b6b18007b45518d79726dd725/cffi-2.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e", size = 208775, upload-time = "2026-08-03T21:19:50.918Z" },
|
|
33
|
-
{ url = "https://files.pythonhosted.org/packages/b1/db/dceb9dd5b231e1da801793f8acc9f3c52a7e1afe40bb1aae37e02b0faad5/cffi-2.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf", size = 221822, upload-time = "2026-08-03T21:19:52.054Z" },
|
|
34
|
-
{ url = "https://files.pythonhosted.org/packages/a0/d2/6cd24ae3be000a634109c247d1475d62e5616d0dc78c82770942ec384248/cffi-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517", size = 225232, upload-time = "2026-08-03T21:19:53.109Z" },
|
|
35
|
-
{ url = "https://files.pythonhosted.org/packages/cb/52/3fa190537004dd7f0ab860a6dc7c0175b8667f68d1e618a46f5498d30250/cffi-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735", size = 223597, upload-time = "2026-08-03T21:19:54.515Z" },
|
|
36
|
-
{ url = "https://files.pythonhosted.org/packages/80/fb/0bb75b7039588c074b37ae99f40d9bfddf990ecb2fbc346ebccd2e56b9be/cffi-2.1.1-cp312-cp312-win32.whl", hash = "sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e", size = 175292, upload-time = "2026-08-03T21:19:55.566Z" },
|
|
37
|
-
{ url = "https://files.pythonhosted.org/packages/d9/79/615cc094e2fb508cade7de88d3b4f6c4ec2bab695c97bce9153dc65aadf5/cffi-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a", size = 185919, upload-time = "2026-08-03T21:19:56.89Z" },
|
|
38
|
-
{ url = "https://files.pythonhosted.org/packages/70/c6/d0ea84713fe46b243a436a18fcd47d639732747e21635c8a27191b06dc30/cffi-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80", size = 180093, upload-time = "2026-08-03T21:19:58.155Z" },
|
|
39
|
-
{ url = "https://files.pythonhosted.org/packages/9d/f4/035513d4117049066b4779dc3b7c0c0fdad175fa13731c9f4003f1cd1478/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e", size = 194248, upload-time = "2026-08-03T21:19:59.399Z" },
|
|
40
|
-
{ url = "https://files.pythonhosted.org/packages/76/af/2aeb4dbb5fc41a04161ae9ff1518de7cec08e164f44a8ce6a4cf7fd2cd1d/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c", size = 196908, upload-time = "2026-08-03T21:20:00.746Z" },
|
|
41
|
-
{ url = "https://files.pythonhosted.org/packages/a7/46/2e5fdde8555706dd98139a910ca11be02809f3f605ce956f655d0214e100/cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6", size = 184805, upload-time = "2026-08-03T21:20:02.02Z" },
|
|
42
|
-
{ url = "https://files.pythonhosted.org/packages/55/41/4c7042f317b9217502988f0873af87e16ad606dc20f84e546e3e6ce9764c/cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971", size = 184764, upload-time = "2026-08-03T21:20:03.141Z" },
|
|
43
|
-
{ url = "https://files.pythonhosted.org/packages/43/1f/1c3d90d91811c8f86ced9ed637956c54bfe5b79ca98fe976d7f8c8979f6b/cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c", size = 214722, upload-time = "2026-08-03T21:20:04.377Z" },
|
|
44
|
-
{ url = "https://files.pythonhosted.org/packages/37/6f/3b5ce4c3b2192d250f04908f2bfd91ef34552ec8f7716a5d4abdb8d67bb2/cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125", size = 222369, upload-time = "2026-08-03T21:20:05.544Z" },
|
|
45
|
-
{ url = "https://files.pythonhosted.org/packages/02/10/4b3c75dde3d9663c9e02ba05c2668b954f671d4bbe346413ca8c696b295a/cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264", size = 210175, upload-time = "2026-08-03T21:20:06.75Z" },
|
|
46
|
-
{ url = "https://files.pythonhosted.org/packages/df/62/14f74b9543e605d17701dc797b815958b8bb70b7624ce1b832ddad48ed6c/cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3", size = 208670, upload-time = "2026-08-03T21:20:08.04Z" },
|
|
47
|
-
{ url = "https://files.pythonhosted.org/packages/95/95/86342356ff5953b3fb06f7ef7c5bee212d45e770abc7218d451b9148313c/cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2", size = 221824, upload-time = "2026-08-03T21:20:09.274Z" },
|
|
48
|
-
{ url = "https://files.pythonhosted.org/packages/eb/ff/7b3429ff53aafe931ed8a5fc69f481bbef7ba6de87ddcbb63d08f483f613/cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b", size = 225148, upload-time = "2026-08-03T21:20:10.7Z" },
|
|
49
|
-
{ url = "https://files.pythonhosted.org/packages/34/34/a95870b9221e09cf4f2ce3178b1a210abdfe63a1bd357da940418d7b8d15/cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7", size = 223564, upload-time = "2026-08-03T21:20:12.165Z" },
|
|
50
|
-
{ url = "https://files.pythonhosted.org/packages/70/ea/839b50531021a647fb5e929f72cf97bc1ff702b5472166164b5b6e76b851/cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac", size = 175263, upload-time = "2026-08-03T21:20:13.559Z" },
|
|
51
|
-
{ url = "https://files.pythonhosted.org/packages/60/a6/8b149b2c3f2e11aaa1618ef64500b45f50f22c57a977a4dff1aff1f91042/cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d", size = 185688, upload-time = "2026-08-03T21:20:14.69Z" },
|
|
52
|
-
{ url = "https://files.pythonhosted.org/packages/01/9a/11f687cb39d6a3504060d5242f04f48c735afb4d3d533958a20594890cb2/cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973", size = 180078, upload-time = "2026-08-03T21:20:15.917Z" },
|
|
53
|
-
{ url = "https://files.pythonhosted.org/packages/d3/7b/d6bbf82b8b96e7391438898c42f5bd96dd02030fd5b64937d248220003e2/cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c", size = 194064, upload-time = "2026-08-03T21:20:17.148Z" },
|
|
54
|
-
{ url = "https://files.pythonhosted.org/packages/94/e6/bcc91b283be94735e268487a054004f0aa19947b6348fa367db53230abc8/cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb", size = 196720, upload-time = "2026-08-03T21:20:18.268Z" },
|
|
55
|
-
{ url = "https://files.pythonhosted.org/packages/d9/99/c4b0c17cacdc9c3b8f280026286a9826d6a208c0f047591a3c3ce99b91fd/cffi-2.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54", size = 184964, upload-time = "2026-08-03T21:20:19.708Z" },
|
|
56
|
-
{ url = "https://files.pythonhosted.org/packages/b3/a9/9db617d05d7367c1ad0ab00b3aa6e6f9281edd689b4ee9ea0e5a84e89c97/cffi-2.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72", size = 184962, upload-time = "2026-08-03T21:20:20.833Z" },
|
|
57
|
-
{ url = "https://files.pythonhosted.org/packages/67/b8/b42132ca113dc567d37684437b46ca1dafc885902b02a110a02d5b511857/cffi-2.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1", size = 222328, upload-time = "2026-08-03T21:20:22.118Z" },
|
|
58
|
-
{ url = "https://files.pythonhosted.org/packages/80/10/c5c0cbf0a657aecf59ef511409734230bf556f05a0d6c9eed7aa5c0a0166/cffi-2.1.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062", size = 209985, upload-time = "2026-08-03T21:20:23.401Z" },
|
|
59
|
-
{ url = "https://files.pythonhosted.org/packages/d5/6c/bfa0b87b03b9238148beca990292843c9396ba069b54496596594173de7b/cffi-2.1.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03", size = 208530, upload-time = "2026-08-03T21:20:24.628Z" },
|
|
60
|
-
{ url = "https://files.pythonhosted.org/packages/e9/02/4e7d553a7ac4b4238b38b3c1b80d486e9d4436f8d2acbf87a0997fe3f402/cffi-2.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96", size = 221525, upload-time = "2026-08-03T21:20:25.758Z" },
|
|
61
|
-
{ url = "https://files.pythonhosted.org/packages/82/1d/a4aaf9babd75acb4d5f223bff71533bee748dd770a382619a798960ee9ba/cffi-2.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527", size = 225053, upload-time = "2026-08-03T21:20:26.985Z" },
|
|
62
|
-
{ url = "https://files.pythonhosted.org/packages/81/10/5dc0e7bdd18e22107054288283380fc97a06ae3f1656a106908d666a3c88/cffi-2.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13", size = 223213, upload-time = "2026-08-03T21:20:28.277Z" },
|
|
63
|
-
{ url = "https://files.pythonhosted.org/packages/0b/e9/d0061c364cde06ee43168a0d076ac1da512cbc380d44767b844ba34fe2b6/cffi-2.1.1-cp314-cp314-win32.whl", hash = "sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c", size = 177682, upload-time = "2026-08-03T21:20:44.288Z" },
|
|
64
|
-
{ url = "https://files.pythonhosted.org/packages/a7/06/1c3e01e3ba14c39f6d10bfbac52753b7e22259e38088e5cfe1d704918690/cffi-2.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48", size = 187949, upload-time = "2026-08-03T21:20:45.623Z" },
|
|
65
|
-
{ url = "https://files.pythonhosted.org/packages/87/5b/da4e39efe18eeb89cf580ea9cfc66b6a7c3eadb808fc0cc1d3a295cb5a5d/cffi-2.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836", size = 182947, upload-time = "2026-08-03T21:20:46.955Z" },
|
|
66
|
-
{ url = "https://files.pythonhosted.org/packages/23/59/40338bf421c5accea1d45158170c87006ef1cd371b05c077e76476949728/cffi-2.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3", size = 188504, upload-time = "2026-08-03T21:20:29.495Z" },
|
|
67
|
-
{ url = "https://files.pythonhosted.org/packages/7d/47/5ecf1023850036e674c77ec4de86182d309ae344e39e7cba984b7df5d647/cffi-2.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2", size = 188259, upload-time = "2026-08-03T21:20:31.291Z" },
|
|
68
|
-
{ url = "https://files.pythonhosted.org/packages/2a/9c/92934c3bea9f785b23eba304538c0b4d37a2a96d2431eb3a1bc87a11aa19/cffi-2.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94", size = 223864, upload-time = "2026-08-03T21:20:32.571Z" },
|
|
69
|
-
{ url = "https://files.pythonhosted.org/packages/4d/45/ba4c93527bc38616a8bd36488acb69a2212d60486794f0c1f318949bbb76/cffi-2.1.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc", size = 211538, upload-time = "2026-08-03T21:20:33.808Z" },
|
|
70
|
-
{ url = "https://files.pythonhosted.org/packages/80/e9/b6ef565e452acb932fb0cb5443f44a78efbd1233e566f02b5a83855e9115/cffi-2.1.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29", size = 210688, upload-time = "2026-08-03T21:20:34.974Z" },
|
|
71
|
-
{ url = "https://files.pythonhosted.org/packages/9a/95/eff5f0cee78d2eabc7eebffec40d3fc1876b5f3c95582e018bb4b99601f2/cffi-2.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676", size = 223803, upload-time = "2026-08-03T21:20:36.564Z" },
|
|
72
|
-
{ url = "https://files.pythonhosted.org/packages/fa/01/579d39fb8bef00a335a23d83757b44feb24cd6345a2c451b64cb67b9c362/cffi-2.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e", size = 226763, upload-time = "2026-08-03T21:20:37.816Z" },
|
|
73
|
-
{ url = "https://files.pythonhosted.org/packages/8d/b0/0b44f47c60b01b57b6e2bbd92343f13a85a1d93bc46ccf6e47e244acd99c/cffi-2.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f", size = 225688, upload-time = "2026-08-03T21:20:38.959Z" },
|
|
74
|
-
{ url = "https://files.pythonhosted.org/packages/eb/d2/3b7176cb570a1d3e27faf67b72f591af508036e0d8b2be2ef9af9e8c84bb/cffi-2.1.1-cp314-cp314t-win32.whl", hash = "sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4", size = 182868, upload-time = "2026-08-03T21:20:40.388Z" },
|
|
75
|
-
{ url = "https://files.pythonhosted.org/packages/56/78/31f00c1bcd97c9bbf55f1bfdf5bc809a5de8887473e90bb9960dca825e80/cffi-2.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e", size = 194104, upload-time = "2026-08-03T21:20:41.725Z" },
|
|
76
|
-
{ url = "https://files.pythonhosted.org/packages/7b/1b/58496f2ed0a35de575250c02a43ab3cc2c04d494a88fed31c1cabc0fd176/cffi-2.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5", size = 186402, upload-time = "2026-08-03T21:20:43.042Z" },
|
|
77
|
-
]
|
|
78
|
-
|
|
79
|
-
[[package]]
|
|
80
|
-
name = "cryptography"
|
|
81
|
-
version = "50.0.2"
|
|
82
|
-
source = { registry = "https://pypi.org/simple" }
|
|
83
|
-
dependencies = [
|
|
84
|
-
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
|
85
|
-
]
|
|
86
|
-
sdist = { url = "https://files.pythonhosted.org/packages/9d/af/182eb91b0df3fe75c4d9f26fe70684569566745f6ba7e5c9c73a862c5252/cryptography-50.0.2.tar.gz", hash = "sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5", size = 880623, upload-time = "2026-09-30T15:30:04.884Z" }
|
|
87
|
-
wheels = [
|
|
88
|
-
{ url = "https://files.pythonhosted.org/packages/e5/56/d194340cc4a57535e82e1bee9e89667ac4b7c13b5d3f59686deae3094dd5/cryptography-50.0.2-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb", size = 3914904, upload-time = "2026-09-30T14:43:44.339Z" },
|
|
89
|
-
{ url = "https://files.pythonhosted.org/packages/d9/69/c9bd862c3bf43d6399c433caf002df16e2dffd4be49bdf515cda38038711/cryptography-50.0.2-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0", size = 4731146, upload-time = "2026-09-30T14:43:47.113Z" },
|
|
90
|
-
{ url = "https://files.pythonhosted.org/packages/21/69/64cef1f702bf6657e0cc186ed1a2891d50d29fb41586b254e1c07adea261/cryptography-50.0.2-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:630ebfea3bf689d075f82316324ff7433dc447fe6bc1bfc76524b74b4a9567d2", size = 4719841, upload-time = "2026-09-30T14:43:49.01Z" },
|
|
91
|
-
{ url = "https://files.pythonhosted.org/packages/38/6b/61a3f8d8c5e1e49a6cddccafc4015cc1c0021360ab0acb4080e7a423644a/cryptography-50.0.2-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f9f6143a8c75945eb960d9eb98905a441394abfa24afaae239d514ffb2586480", size = 4738340, upload-time = "2026-09-30T14:43:50.932Z" },
|
|
92
|
-
{ url = "https://files.pythonhosted.org/packages/7b/2e/7212ca32fd43dc91f2f41db20160b268098874b4c9a0e7be94d6835f5b2e/cryptography-50.0.2-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:a582ab2ae1d34f67112cadc86702774c9ea4374df6bca6afe672817203c99134", size = 5367029, upload-time = "2026-09-30T14:43:52.911Z" },
|
|
93
|
-
{ url = "https://files.pythonhosted.org/packages/1a/f1/b474e930c4d910328780e3940da76f5aa5cbc48ce1fc14e44d239d9ea9db/cryptography-50.0.2-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4061c0079120205fb760c58acab6443e217307dcf05e3702cf970e0689972856", size = 4753050, upload-time = "2026-09-30T14:43:55.272Z" },
|
|
94
|
-
{ url = "https://files.pythonhosted.org/packages/7c/52/9af10e80ac16b0fcc2123f9cbd5e7afbd0fd5075bb7a607c592258a39cda/cryptography-50.0.2-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:ac9ed99d81760c62fe89d5f0815cdfa1ba9a35141cf30f1c2d044f04b4803d2e", size = 4376724, upload-time = "2026-09-30T14:43:57.24Z" },
|
|
95
|
-
{ url = "https://files.pythonhosted.org/packages/71/37/6202e488cc1eb625ea110c292c6bda92823176e023f427d8d5660ce8d632/cryptography-50.0.2-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:87e9ce85beb6b328ba370cc6e6aea483c92617b4c95b1d33a49297eb662bfb04", size = 4737859, upload-time = "2026-09-30T14:43:59.541Z" },
|
|
96
|
-
{ url = "https://files.pythonhosted.org/packages/8f/30/e86d7d518489b0ae2497091a35287abcb1a2ce4037837a34afbe9b1d6964/cryptography-50.0.2-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f265528741e048bce55c3463ed721fb0aa45a5888d8add8cfeccb3035451bbdc", size = 5324103, upload-time = "2026-09-30T14:44:01.901Z" },
|
|
97
|
-
{ url = "https://files.pythonhosted.org/packages/d3/69/2c833a049475e0a3444e94c7d0aca0aa51d166374a449b09e92ac98138de/cryptography-50.0.2-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9dab55f57c74c3cad24c323bacbbd04be4705ba6eb0d92e920b1fc4837ed5079", size = 4752576, upload-time = "2026-09-30T14:44:04.545Z" },
|
|
98
|
-
{ url = "https://files.pythonhosted.org/packages/6c/5d/906970b83bbfc1f5bbfb677a143c181f2801f23b6a7204a3b47c42c97e65/cryptography-50.0.2-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25784ce8b9621c90c643efb9e1e2162ab3b0224cae446ad5e70e7fcb1ce18b51", size = 4870819, upload-time = "2026-09-30T14:44:06.884Z" },
|
|
99
|
-
{ url = "https://files.pythonhosted.org/packages/68/e3/f2298d3bb55e0c4a91841ec4d01b3f020ba8c5fbf15ccdcc6dcf03f97025/cryptography-50.0.2-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:85d0d9a31b9098e98534226d5686b47264b95e62ce459dc2e62fdfc809f9fe93", size = 5030152, upload-time = "2026-09-30T14:44:09.443Z" },
|
|
100
|
-
{ url = "https://files.pythonhosted.org/packages/9a/4f/adfc442765721292fff86d314ce385d3249d22db42295c0dd057727b60f3/cryptography-50.0.2-cp311-abi3-win_amd64.whl", hash = "sha256:7afa5a6602a9f29af1f3a2965f831bae7c9d5d597b7cbb716d41ab3b7d89879c", size = 3824692, upload-time = "2026-09-30T14:44:11.671Z" },
|
|
101
|
-
{ url = "https://files.pythonhosted.org/packages/ce/cb/52eb3770c0d0be2702a98c6e96065ddc0a2877cf0845aa9c23397c142cd4/cryptography-50.0.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f785f6161f202ab04d8ca194158968798e480ca058943907972da5f12e2881e8", size = 3892731, upload-time = "2026-09-30T14:44:13.485Z" },
|
|
102
|
-
{ url = "https://files.pythonhosted.org/packages/19/8e/aa1fc533d4546b127b45de8aa024eb5933d23eff9debfe25931e56861095/cryptography-50.0.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0ecbc5652bdb6fc9eaf89a7d196e20941adfe812f43bc4ca05d9150496821047", size = 4710431, upload-time = "2026-09-30T14:44:15.427Z" },
|
|
103
|
-
{ url = "https://files.pythonhosted.org/packages/6a/64/72bc3f75176e7e406b748a3e3830432b8c51297b38368713df04dc04898a/cryptography-50.0.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ab50ee449bf968271e820086f10a33d101dd060370abc10bcd22279be2656539", size = 4694824, upload-time = "2026-09-30T14:44:17.69Z" },
|
|
104
|
-
{ url = "https://files.pythonhosted.org/packages/4e/c6/62c77550edfa5ca3f14bf44a1e6739b9fa09d6e998a11d97ed8213bccc98/cryptography-50.0.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a9f7355e6fab51f6c369b86fb7571cffa05edee2c2121e0380a37fb9ac1cd5c1", size = 4716967, upload-time = "2026-09-30T14:44:19.661Z" },
|
|
105
|
-
{ url = "https://files.pythonhosted.org/packages/f4/37/cce70f150c432914460157a6ecc161752e053aa5ec0ef3b3f7dc6e31039a/cryptography-50.0.2-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:94e5e9f108ee10471288214d3d233fbfbb492840a8457eb85178d643ddeb32c7", size = 5328676, upload-time = "2026-09-30T14:44:21.744Z" },
|
|
106
|
-
{ url = "https://files.pythonhosted.org/packages/aa/9a/6f2f0304d634ceafdeaf23e84537336664ac419b5d07611675c2ad3f6b7a/cryptography-50.0.2-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:241449bf940a5d27309bd317e6f9a2af6932113818bb2b8f5c59ddc7ef16da18", size = 4727698, upload-time = "2026-09-30T14:44:24.178Z" },
|
|
107
|
-
{ url = "https://files.pythonhosted.org/packages/1d/de/66bcf9244d118663b2e1aaded8990f4640e3d7b7411870a5765f252074d2/cryptography-50.0.2-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d8947001be83df1394050758ce0e745dd74fb134eef0a4b5124208dfc3a68c37", size = 4354821, upload-time = "2026-09-30T14:44:26.263Z" },
|
|
108
|
-
{ url = "https://files.pythonhosted.org/packages/bd/e6/db28a28c7b6c676addce89136de3d8db49ea825a8c863472e36e42ead4ad/cryptography-50.0.2-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4a20ce1e5cb4284a86692fdcba7cb8754185c6b2e5c56fcef3751cf451d3cdc2", size = 4716748, upload-time = "2026-09-30T14:44:28.447Z" },
|
|
109
|
-
{ url = "https://files.pythonhosted.org/packages/30/96/01546c7f69ea0e2ab790a2e4f0934a4052fb9b388147fbf83c2fd72f1e57/cryptography-50.0.2-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:84f964e537f916e2cc85199e5a88742e964939b575ac8598b3f9d6cc416cdaf1", size = 5285085, upload-time = "2026-09-30T14:44:30.704Z" },
|
|
110
|
-
{ url = "https://files.pythonhosted.org/packages/6c/01/03263395f74d50b071e9e66daace3f8bef80493e5d410726f2ba8554736b/cryptography-50.0.2-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:828d49b0ff5a0e3975865571c5d91dbbdd0d38d8289b249a163e9425413a5e05", size = 4727268, upload-time = "2026-09-30T14:44:32.92Z" },
|
|
111
|
-
{ url = "https://files.pythonhosted.org/packages/eb/94/2bfe8f29ec0cc9c0d99359c4161adf32858e4934b72c6d100d2ac0bbe962/cryptography-50.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:deb9fde5c60e437ee4821bc9bc39ff31b42135c27e1dc61ef0a629389c1de62e", size = 4849503, upload-time = "2026-09-30T14:44:34.969Z" },
|
|
112
|
-
{ url = "https://files.pythonhosted.org/packages/54/44/e80651ecbf0e42b62e2bb5f5768916e07eea72e1297338956a61df361f88/cryptography-50.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8c71ba2cd31fc93748c38e1b613200ff1c2665cbfd5341fe3a61cfde35a1430e", size = 5004057, upload-time = "2026-09-30T14:44:37.064Z" },
|
|
113
|
-
{ url = "https://files.pythonhosted.org/packages/f8/cc/1d33befb3cd7ea7e77d2d73f43f2066471da1b21f24a6156efcaabf6d2e8/cryptography-50.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:78198641e5be9521beea5aa782bb551a58068d10e6eb04c9c680c1b69f2e7d45", size = 3795868, upload-time = "2026-09-30T14:44:39.71Z" },
|
|
114
|
-
{ url = "https://files.pythonhosted.org/packages/2d/49/93f6a6e7a87c9aa68d44d3e1cdb5fe8f60c90d5d2f46acae9a56892816b8/cryptography-50.0.2-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:edc3342adf8f697fc5f59c887a304356f147b397809440ed64e2fa6af2f50f37", size = 4133708, upload-time = "2026-09-30T14:44:41.807Z" },
|
|
115
|
-
{ url = "https://files.pythonhosted.org/packages/8c/75/32ac2a56243d778805c16ca6a32b8f74fb757df7e28d7ecb560afafb59cf/cryptography-50.0.2-cp315-abi3.abi3t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d370b8d1dfcdf7130178137f6fbee6140774a1acc6cacefc4b42643ec11d0a3a", size = 4956267, upload-time = "2026-09-30T14:44:43.693Z" },
|
|
116
|
-
{ url = "https://files.pythonhosted.org/packages/aa/a4/2c8d734e43d97f0842ee9f1b7b4bfb3d0cf5e19edebf43c2afe6675c2320/cryptography-50.0.2-cp315-abi3.abi3t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f2f9bd7f90c64fe89253f0a2c05e3c4856072660429ce8831b4235bf29403a67", size = 4966465, upload-time = "2026-09-30T14:44:45.769Z" },
|
|
117
|
-
{ url = "https://files.pythonhosted.org/packages/c2/58/ee288c829a6f41f6235ae9dd33d82fd19b45442b65b4c8a3da36963d9f7a/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_28_aarch64.whl", hash = "sha256:e275096ea1e60cc595cda2836fd4a6c725d1125108b868be17f53684d164e2cc", size = 4959356, upload-time = "2026-09-30T14:44:48.211Z" },
|
|
118
|
-
{ url = "https://files.pythonhosted.org/packages/92/20/9ded6d51ddd9897f6b6e81fb9ebea7951d7cc5d6c890b0ed8abf77a51a80/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_28_ppc64le.whl", hash = "sha256:b13478603dcd0a2479ff8e87e2c19a7d525734686fe3c49542472293a204212d", size = 5548822, upload-time = "2026-09-30T14:44:50.86Z" },
|
|
119
|
-
{ url = "https://files.pythonhosted.org/packages/02/a8/8df951850d6b31d2a00218f19e2b3f999523437ed7a819df7fa427942fca/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_28_x86_64.whl", hash = "sha256:58a0c478eeca76fe5e07993c5a0703def34a6dc6a0cda4f5564639b33112ffe7", size = 5001199, upload-time = "2026-09-30T14:44:53.379Z" },
|
|
120
|
-
{ url = "https://files.pythonhosted.org/packages/8b/f9/36b3022218ce75b7cdf068fb95f809f9bd0d820e4955ef43b90c255cc7ac/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_31_armv7l.whl", hash = "sha256:d38cdff612d06fa6a32840d5e1b1f7a27cee4a349aa9085d94a67789d6bfd408", size = 4629333, upload-time = "2026-09-30T14:44:55.635Z" },
|
|
121
|
-
{ url = "https://files.pythonhosted.org/packages/8c/72/20f99a219f6af47cdd1cbd978c243b92d71496e168a746138af44ded4f29/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_34_aarch64.whl", hash = "sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b", size = 4958822, upload-time = "2026-09-30T14:44:59.639Z" },
|
|
122
|
-
{ url = "https://files.pythonhosted.org/packages/f2/20/196f112617fb08eb4d608a2a6c422373d46f9cc2857f38fc0667033c0899/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_34_ppc64le.whl", hash = "sha256:cbc8738fd8526d80f35cb3a40d41f41a2e7030bb3b18b09a6778ef63d291c2fd", size = 5506351, upload-time = "2026-09-30T14:45:02.267Z" },
|
|
123
|
-
{ url = "https://files.pythonhosted.org/packages/24/95/83378121ef3eaaaf71d4b781577ff794acb39b9e1b87a3f156898c8497ed/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_34_x86_64.whl", hash = "sha256:e105ab60406787da31fccc883fc0f733af1efd78f0136a4599692c4083a73d0c", size = 5000859, upload-time = "2026-09-30T14:45:05.009Z" },
|
|
124
|
-
{ url = "https://files.pythonhosted.org/packages/22/f7/70fd7ae4d1dbfa7ba29b02e1b9068771519a86027756510b700ce81086a8/cryptography-50.0.2-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:6f8700550aa1474a91e5dc07049c46f98b423b5b1ddd0483e0b51362eeeaf5be", size = 5092151, upload-time = "2026-09-30T15:29:15.932Z" },
|
|
125
|
-
{ url = "https://files.pythonhosted.org/packages/d4/be/688367b74de86984bd58d8efacfc7c9e68b89a6a22ced0fb4f38db50254a/cryptography-50.0.2-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:c71be1cbfa5cd9a41ee452acf1eccd82b2c05950358b106ec8ceb83411d1a020", size = 5286120, upload-time = "2026-09-30T15:29:18.309Z" },
|
|
126
|
-
{ url = "https://files.pythonhosted.org/packages/39/d1/55f8a3f2ef5d1529e16835ef10cf0fe3d559ce237b46dddc440c0bba3649/cryptography-50.0.2-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:c423ab384a46c4dff7217b2ea5ba2e11cffdeab6441acd04cf65a369caf0366c", size = 4111557, upload-time = "2026-09-30T15:29:20.155Z" },
|
|
127
|
-
{ url = "https://files.pythonhosted.org/packages/23/ad/ac987755d00e1e64273760228d2635ae38dae2be83e3c6e0d3289d91dec3/cryptography-50.0.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:0ec5f09541743261e66e291b4a0cbf0fb2997aeaab6d9e9c740b9dba1b58d1c2", size = 3943588, upload-time = "2026-09-30T15:29:22.265Z" },
|
|
128
|
-
{ url = "https://files.pythonhosted.org/packages/d5/8d/6d585339bedf85d45044c85d8412dac53f2bb6f918e8b7777efba1787844/cryptography-50.0.2-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c5e67125c7dca78d199ec4e116aa93dbb83494808ecbb8211a2cb09b1bf41dbd", size = 4756166, upload-time = "2026-09-30T15:29:24.58Z" },
|
|
129
|
-
{ url = "https://files.pythonhosted.org/packages/bf/f1/1c1f6874e8550cfddd4b688ceb38cefb6ed15ceed224d56f133f3d88c214/cryptography-50.0.2-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee247f5c245c9a2fe7c8e2214e295918838e44e00a45a6718451e4004219e767", size = 4749145, upload-time = "2026-09-30T15:29:26.807Z" },
|
|
130
|
-
{ url = "https://files.pythonhosted.org/packages/c1/63/61b15dc1a8de03fe0adbe3fd7608b3ad5c73bf50993bbcb1faaa930afe33/cryptography-50.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dfe9763530994147d9af1def057a5b9658b00e8f8fe8743d144d1e0911c2e454", size = 4763638, upload-time = "2026-09-30T15:29:28.588Z" },
|
|
131
|
-
{ url = "https://files.pythonhosted.org/packages/fc/35/b345bdfa40c9126df1a9d33236aa98418367931b8725f84fc3ae2b98dc59/cryptography-50.0.2-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:58ddb5a8e3179d12f19e4ea34d2d32e9d63a4baa142c875c1eb59f41b7243acd", size = 5382217, upload-time = "2026-09-30T15:29:30.589Z" },
|
|
132
|
-
{ url = "https://files.pythonhosted.org/packages/4f/87/ef344a9e616871f2519c22d6afcda79ddd5d35e9592d95eb6e677608d055/cryptography-50.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f21e8a22c8605750c7af886bab299a363721264061b4ac0a30efb73cfd58efc5", size = 4781387, upload-time = "2026-09-30T15:29:32.605Z" },
|
|
133
|
-
{ url = "https://files.pythonhosted.org/packages/90/5b/f2fdb13cd0b96f6f932c8627bb292a45f11c64d21620a8e120aee9a3b848/cryptography-50.0.2-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:9c8402a82ea0dc4ceeab793db05f0fafa8ca139ca34fcde5df0f596103c74107", size = 4403790, upload-time = "2026-09-30T15:29:34.374Z" },
|
|
134
|
-
{ url = "https://files.pythonhosted.org/packages/bc/ce/7e4f662b1e3c393513569e402cfc85ac7da0bd3d5435e122a3140219eb2d/cryptography-50.0.2-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:0ddc924c04591c2811ca024d62ecad4f7f6f08af8939c211438f48a16bd23602", size = 4764319, upload-time = "2026-09-30T15:29:36.149Z" },
|
|
135
|
-
{ url = "https://files.pythonhosted.org/packages/3c/3f/86ff33ce34cc0de6847fb96e035a1a760d81652e38643f617c02ad32ef7a/cryptography-50.0.2-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:a6557e5f38e065ca9fbdaf7cfc7435ecb1d113aa81a022d1b51921ee7432e227", size = 5338560, upload-time = "2026-09-30T15:29:39.053Z" },
|
|
136
|
-
{ url = "https://files.pythonhosted.org/packages/40/cf/6b5c8e2fd9202d98988ab7cb5cc5c991704c4ad55f492ff408e4969f83f1/cryptography-50.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c", size = 4780973, upload-time = "2026-09-30T15:29:41.251Z" },
|
|
137
|
-
{ url = "https://files.pythonhosted.org/packages/10/bf/8d6ebc7dded797bd0f0160d52188021211f011a2b164ef0ae1dac4587465/cryptography-50.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e", size = 4897738, upload-time = "2026-09-30T15:29:43.106Z" },
|
|
138
|
-
{ url = "https://files.pythonhosted.org/packages/d4/aa/f3f6e0de7e6253b8baa8b2d8fb9d50924fa75cee3d4624bd4bc1208ee923/cryptography-50.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94", size = 5058280, upload-time = "2026-09-30T15:29:44.827Z" },
|
|
139
|
-
{ url = "https://files.pythonhosted.org/packages/f6/b6/a1faf3a27ae9405fb34b1713cc73b2d8a26b04d5c561578fa2e6ef3e5bb9/cryptography-50.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de", size = 3854095, upload-time = "2026-09-30T15:29:46.782Z" },
|
|
140
|
-
]
|
|
141
|
-
|
|
142
|
-
[[package]]
|
|
143
|
-
name = "introspection-operator-runtime"
|
|
144
|
-
version = "0.0.0"
|
|
145
|
-
source = { virtual = "." }
|
|
146
|
-
dependencies = [
|
|
147
|
-
{ name = "paper-docx" },
|
|
148
|
-
{ name = "pillow" },
|
|
149
|
-
{ name = "pypdf", extra = ["crypto"] },
|
|
150
|
-
{ name = "pypdfium2" },
|
|
151
|
-
]
|
|
152
|
-
|
|
153
|
-
[package.metadata]
|
|
154
|
-
requires-dist = [
|
|
155
|
-
{ name = "paper-docx", specifier = "==0.2.0" },
|
|
156
|
-
{ name = "pillow", specifier = "==13.0.0" },
|
|
157
|
-
{ name = "pypdf", extras = ["crypto"], specifier = "==6.21.4" },
|
|
158
|
-
{ name = "pypdfium2", specifier = "==5.14.0" },
|
|
159
|
-
]
|
|
160
|
-
|
|
161
|
-
[[package]]
|
|
162
|
-
name = "lxml"
|
|
163
|
-
version = "6.1.3"
|
|
164
|
-
source = { registry = "https://pypi.org/simple" }
|
|
165
|
-
sdist = { url = "https://files.pythonhosted.org/packages/23/ad/28ecd7cb894d172f3c9c80a075eeeb2017ac62e3632cee05a5f9493547eb/lxml-6.1.3.tar.gz", hash = "sha256:45222d94ddd511536f3b2f7d9deae3b2339b4ce0f075f1ca25703b07cad9dd21", size = 4211198, upload-time = "2026-09-02T14:48:02.287Z" }
|
|
166
|
-
wheels = [
|
|
167
|
-
{ url = "https://files.pythonhosted.org/packages/dd/1f/a180b57d9eeabaab77f9d5aa30356898ea749c4795596a8f66d1eb6bef2e/lxml-6.1.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c0710ac085a157b593c38fbcacd950f15c4afa8e2057527185875ab302752bc", size = 8602094, upload-time = "2026-09-02T14:47:26.054Z" },
|
|
168
|
-
{ url = "https://files.pythonhosted.org/packages/a8/25/070c92013a1c029a602b03560d68772313d918268667fa993da7961759c9/lxml-6.1.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:623c8799c17128753c65699f1c3aa32402657393a9ad6db09ed8b98ddf76611d", size = 4638308, upload-time = "2026-09-02T14:47:29.587Z" },
|
|
169
|
-
{ url = "https://files.pythonhosted.org/packages/1e/1c/722e88883173097a1a375153e3c2447eba3060d0231522cf6596e99f4195/lxml-6.1.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f683dc6300317700025e41d89a43e0276692ded16113a3c43eab704d605c58e5", size = 4939696, upload-time = "2026-09-02T14:47:32.997Z" },
|
|
170
|
-
{ url = "https://files.pythonhosted.org/packages/db/36/aa413bc214dc4f785ad2b2ddd8cc99aae7062d49ab155e91e6011af00daf/lxml-6.1.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:379f8a75cf6eb7eef0af074b55f49ab73b868388a98de14646abcdfa4564bb11", size = 5105247, upload-time = "2026-09-02T14:47:36.734Z" },
|
|
171
|
-
{ url = "https://files.pythonhosted.org/packages/a3/a0/a1f7f1313795bfec67b77f01ef3b1128d49f2d7f66a8413fa55d47f4e25f/lxml-6.1.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b37772102d44bb6628186accca3a121b1fa3a6b3d97518a8c29a5229ca4c0d0a", size = 5011915, upload-time = "2026-09-02T14:47:39.846Z" },
|
|
172
|
-
{ url = "https://files.pythonhosted.org/packages/b9/78/840e7e3f1d0cc7a5cfac5d8505b97e25b6427fd774ac4bae672aaebfb4b5/lxml-6.1.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ddcf547bea2aee967d6a77779376a45e77e610e8465147a1f3d7e20d539d6e32", size = 5638175, upload-time = "2026-09-02T14:47:43.644Z" },
|
|
173
|
-
{ url = "https://files.pythonhosted.org/packages/0a/20/e022dbc6b4753a9bc9fc5fb28a27163430c1731b9913997f6544c1b2518c/lxml-6.1.3-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:909f4e927bb051f7740d6367285fc60cdcfdaf0258c2dba4ff5ba7eadadc250c", size = 5244675, upload-time = "2026-09-02T14:47:47.635Z" },
|
|
174
|
-
{ url = "https://files.pythonhosted.org/packages/99/83/82cde81d2b5eb38d1539fdfdf318abdd014a7e604f4df01c9cd3deb18f2a/lxml-6.1.3-cp312-cp312-manylinux_2_28_i686.whl", hash = "sha256:a5c18810318303ce9afb3f95e2ddb54834f96fa699a8600433fd5a93dcf44c56", size = 5358205, upload-time = "2026-09-02T14:47:50.306Z" },
|
|
175
|
-
{ url = "https://files.pythonhosted.org/packages/d2/a1/f3b057371c8cb29f2a9c9c44ea320592446e40b74a4b0af68c3d8e65bc73/lxml-6.1.3-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:3e42265103fb385d8642a78672edf376c6f7e1d3598a7a4f9cb1278f2f6b5f6f", size = 4704495, upload-time = "2026-09-02T14:47:53.251Z" },
|
|
176
|
-
{ url = "https://files.pythonhosted.org/packages/1a/a4/230eb28be5d412152ffc3c679b51fe1aeede5a53f3a8eb6e9748f2f4754f/lxml-6.1.3-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:21402998e4b78e7cce237d2788841aaa21ac9a4d1574d04dc2d12ee41ae807b5", size = 5255117, upload-time = "2026-09-02T14:47:55.963Z" },
|
|
177
|
-
{ url = "https://files.pythonhosted.org/packages/a3/18/1969f56763af24ce42ea156007b0b2d73fddea552e283b2010416394f0f4/lxml-6.1.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:38fc4e4e4e084e0bd491949482527d406788045c546d4f8789e93fc527b91385", size = 5054424, upload-time = "2026-09-02T14:47:58.131Z" },
|
|
178
|
-
{ url = "https://files.pythonhosted.org/packages/f4/d4/2a90acc1f6fabaa3a8db9340437822bd8d041b205d626a4b3e8621aaa390/lxml-6.1.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5609efdb0d3c95499c00046bc53648b3482ec2175b5503d6e611b3f0555dc71d", size = 4785572, upload-time = "2026-09-02T14:48:01.029Z" },
|
|
179
|
-
{ url = "https://files.pythonhosted.org/packages/a5/1e/b90e845b1dcd0f2f3f26b98283d857f25909223aacd265eee032c34ab8b1/lxml-6.1.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:97ce49699d87ebf8aad631b55d65b33219a4f1bfefbbf5bff19dc9af160aeaf9", size = 5656516, upload-time = "2026-09-02T14:48:03.419Z" },
|
|
180
|
-
{ url = "https://files.pythonhosted.org/packages/eb/ab/0a1b802c57f3fba5c4efd77d5c6b78adaa8f7b681f0c90456b140fe8bf6c/lxml-6.1.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:48542c9acba9ff9450bd18d871d2c2c8787fdb283572b623d206f1b927cd7d9e", size = 5245982, upload-time = "2026-09-02T14:48:06.109Z" },
|
|
181
|
-
{ url = "https://files.pythonhosted.org/packages/da/ee/2c016fbceb3778137459292538d9dfa7e3ad9070fe409c15254ddd90d2cc/lxml-6.1.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c55e71a9b1db1f107efb60da49c093689b74c5c31a708e5379e2fd9439d4fbb5", size = 5267340, upload-time = "2026-09-02T14:48:08.374Z" },
|
|
182
|
-
{ url = "https://files.pythonhosted.org/packages/9c/b1/736d18fd6f0835761923b7bac1f0c27d60c1200384e9093f05d8c5100525/lxml-6.1.3-cp312-cp312-win32.whl", hash = "sha256:b3ff39654f0ce6ebd4db154211136dbe7e8157bcc3bed2344c87f32c7c6ecb6c", size = 3602606, upload-time = "2026-09-02T14:48:10.384Z" },
|
|
183
|
-
{ url = "https://files.pythonhosted.org/packages/3a/5b/6ed903e4e6278a020c8a6f0dbbe78030d041840a6b4a64ea441a1e414077/lxml-6.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:3e9a00d1c2c30936f7add097c41afc5da6556c580909104aafd382cac92a855c", size = 4005999, upload-time = "2026-09-02T14:48:12.51Z" },
|
|
184
|
-
{ url = "https://files.pythonhosted.org/packages/e4/1b/7bcebb7b6332cb3ae85e9c13b139adb6f23f75c71d84041c56a5005d9a29/lxml-6.1.3-cp312-cp312-win_arm64.whl", hash = "sha256:1aeca87830c4fe649dcf93fe2b059525b71c72587f21be4ae4af7103082a79fa", size = 3666631, upload-time = "2026-09-02T14:48:14.567Z" },
|
|
185
|
-
{ url = "https://files.pythonhosted.org/packages/52/05/3ef45db776baea068044c799bbba68f3ca00a440c0e930a17c572f3d9639/lxml-6.1.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3a48093cdb058a93af842ede9703520e810b05dcd0fc6d7190a06376c3bfb6bd", size = 8590357, upload-time = "2026-09-02T14:48:17.413Z" },
|
|
186
|
-
{ url = "https://files.pythonhosted.org/packages/8c/a5/eee2fc77eee5ea68e4a4334b1def1781a3beaeefd3d98e81b4a38dc447b7/lxml-6.1.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:887c021d9a977cff89cb273047c1352997b772a8908a25c21836861f69b92be1", size = 4632616, upload-time = "2026-09-02T14:48:20.745Z" },
|
|
187
|
-
{ url = "https://files.pythonhosted.org/packages/35/42/df27b56848acd29d8a720acc28977911aab36f2a09df4208d5502e887415/lxml-6.1.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:611a51e61c92f62345a50b0035df6fc0d678f9299f33728826d831598862f59d", size = 4936186, upload-time = "2026-09-02T14:48:22.94Z" },
|
|
188
|
-
{ url = "https://files.pythonhosted.org/packages/ab/8d/8a7b91df0b54d09d25f5f44885d6b3e0a6d6643a8c070191580318d20c42/lxml-6.1.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b477912f42c5c33405a10c759d22f80cf5af043ae02d95b9d8e5e5bc555739ed", size = 5093324, upload-time = "2026-09-02T14:48:25.132Z" },
|
|
189
|
-
{ url = "https://files.pythonhosted.org/packages/c6/7e/8f340ddcd43790332fb0de8a26628d571a492da3300cd191821698407c96/lxml-6.1.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cffe18571ccc51d742cd08cbb3f8b756de9311d18c7ea98f5d92f37b8fb60c2", size = 4998850, upload-time = "2026-09-02T14:48:27.394Z" },
|
|
190
|
-
{ url = "https://files.pythonhosted.org/packages/c5/c1/9c5bb572f1f09ec9e4322bd4a4e9f4ad48347fc56ef94cf4df58a5279dc8/lxml-6.1.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:75cc6569e86be5785b6188ef1642670c6adbc984e81ec35e224842ecd9eefcc8", size = 5626813, upload-time = "2026-09-02T14:48:29.61Z" },
|
|
191
|
-
{ url = "https://files.pythonhosted.org/packages/ac/7d/8bf1fd8bae8247743968bb76d027a1ac5bd2c4b44495fba6a71b30d10706/lxml-6.1.3-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d85dfab42dd672f87a7f76e9de7172962aee69fa12044f0d6e1a23cbd53fb80e", size = 5232385, upload-time = "2026-09-02T14:48:31.969Z" },
|
|
192
|
-
{ url = "https://files.pythonhosted.org/packages/7b/2e/6cef69ed81cb7df0d03b0dd09d08e6e2cf5061a743ff6f42f0b741548e9b/lxml-6.1.3-cp313-cp313-manylinux_2_28_i686.whl", hash = "sha256:42632b4024ab24a6b488f559ac851312509888b6b80ae2aa11cf29a646a0d245", size = 5347088, upload-time = "2026-09-02T14:48:34.13Z" },
|
|
193
|
-
{ url = "https://files.pythonhosted.org/packages/5f/e1/8e5fd8ddc8c7d685badb0f2db149e3c9da84eefc2827c01c658df2c4e3cb/lxml-6.1.3-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:febd35ef45f603c2d74b74655efdbf45e14f55fc0aef4ac82b663ca829b283e0", size = 4707227, upload-time = "2026-09-02T14:48:36.62Z" },
|
|
194
|
-
{ url = "https://files.pythonhosted.org/packages/7a/7e/00041382a11be40a88bf405ebff11c8efabd3de79f2691e1638b1c47a8a0/lxml-6.1.3-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a43b3bdf11e477dc7770609d3477316f974354dfc8425d596f64f471cc8daf6e", size = 5240208, upload-time = "2026-09-02T14:48:38.893Z" },
|
|
195
|
-
{ url = "https://files.pythonhosted.org/packages/fd/fe/316538b5cff0936fa63d45d421c655730fcbb5a28dcac728c175083002bc/lxml-6.1.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d582042c69857c364e8153de6e18e0da9b7b515a6a8113caf69a6ec8e0520f2", size = 5050271, upload-time = "2026-09-02T14:48:41.213Z" },
|
|
196
|
-
{ url = "https://files.pythonhosted.org/packages/c9/91/455bcccb3ac725373007344d351151810cd19762d1673b64b811f4359a42/lxml-6.1.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8e49a646acfab83c68974f4aa1d0a2acca9e88d7d627ae0fc13201b14b76d310", size = 4780433, upload-time = "2026-09-02T14:48:43.779Z" },
|
|
197
|
-
{ url = "https://files.pythonhosted.org/packages/cb/f6/580440e2f52cf00bba5c5e1080bfa88cdfcde73be71a11d95170ddbb663f/lxml-6.1.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0dee106e9aa97fb00541b1ed7827070564d0549c3d3fba8920e6b20fd980f748", size = 5645928, upload-time = "2026-09-02T14:48:46.187Z" },
|
|
198
|
-
{ url = "https://files.pythonhosted.org/packages/f6/dc/d123c1f244306543d545f62443f794959e4f1ea709fe100f8740d514e74a/lxml-6.1.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:dd5e90f34cffcfed97f36cf066325773d2b6021c60c29942e53a18b028501b1d", size = 5231184, upload-time = "2026-09-02T14:48:48.691Z" },
|
|
199
|
-
{ url = "https://files.pythonhosted.org/packages/c3/3c/fe55b2bd5c6113c906511cd88f6a470195c5fbff1124f19970ab706c3477/lxml-6.1.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d9b3e7d71bf6acff341233417abbdface29c647e3113892d9aaedc02eb4aa2bc", size = 5255814, upload-time = "2026-09-02T14:48:50.948Z" },
|
|
200
|
-
{ url = "https://files.pythonhosted.org/packages/e7/a7/485df55acf55dc35e4ca89d2f48f03889e5a3241826b18b85102b32ce9d8/lxml-6.1.3-cp313-cp313-win32.whl", hash = "sha256:160fcf381f76c3aeac28a756bec44f48942a8f7245a87aa28e3a523b4d90cd87", size = 3602214, upload-time = "2026-09-02T14:48:53.236Z" },
|
|
201
|
-
{ url = "https://files.pythonhosted.org/packages/c0/28/e46a7702bd95e9043291f7c3539b6184cba66f96cea9936f20939b284eeb/lxml-6.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:e477aca0bc0d19f3b4ae9e4f2a1cfd687c31bf772d78734910658186b40b2477", size = 4004091, upload-time = "2026-09-02T14:48:55.699Z" },
|
|
202
|
-
{ url = "https://files.pythonhosted.org/packages/8a/1d/154c78e20479a43916e63f19cb720d83f44f024b03228be44c92d9a97b24/lxml-6.1.3-cp313-cp313-win_arm64.whl", hash = "sha256:b1cc980905221a5d8b3c476330730b3adb40ff80add71ffbdb6215ba055656f1", size = 3665468, upload-time = "2026-09-02T14:48:57.703Z" },
|
|
203
|
-
{ url = "https://files.pythonhosted.org/packages/0c/15/fc75a70b0af6021d0ea16811f1fc71cc42cd06ce90fe10f007a69b2eed84/lxml-6.1.3-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:2bec13085dc8ef48a3fe62f7dfcacfeda2c785cdf19cc8eeda2bb9ed081da165", size = 8609725, upload-time = "2026-09-02T14:49:00.156Z" },
|
|
204
|
-
{ url = "https://files.pythonhosted.org/packages/84/ef/398fcf9018f881ec9aeaafae1ddd6586dfb13314a35d35e899de373dcae0/lxml-6.1.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4f4db7c7e954d289d71878938348b3d91b904a3e8210a11939359fb758a58e7d", size = 4639629, upload-time = "2026-09-02T14:49:02.81Z" },
|
|
205
|
-
{ url = "https://files.pythonhosted.org/packages/a7/2d/49b6a6ad7ce8f64b07b9fe852ff0c6d3fcbb26db61bee4f63d4120180a1c/lxml-6.1.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2cae5d5c90a62d9139c512a0cb1aad1d182b022b5740daea2617eb5bf7fc658e", size = 4965074, upload-time = "2026-09-02T14:49:05.133Z" },
|
|
206
|
-
{ url = "https://files.pythonhosted.org/packages/66/bc/6230cf80e4331c33383b0b6b73dc31a393dd76edd4cb73d761de5123034d/lxml-6.1.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c6c0c13128a32eb04a51357e56a094e13aa8e6d3d1884de2e9ae923f6915e1a8", size = 5099355, upload-time = "2026-09-02T14:49:07.343Z" },
|
|
207
|
-
{ url = "https://files.pythonhosted.org/packages/ac/cf/d1143d9b7717e07a82f158a1fc9ce6e581fdad1226734950af869e3ffde4/lxml-6.1.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2221e88679d1351e9a40aaee54bc65679b9795bbd0160bc3d5e36b163344eb75", size = 5036795, upload-time = "2026-09-02T14:49:09.65Z" },
|
|
208
|
-
{ url = "https://files.pythonhosted.org/packages/31/6f/194bb00ffb89712c30f5a7e1b8e685590e140fad6c8261fec172c09a3dc0/lxml-6.1.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cfb398886a7eb4c719161c3efcff2a1248febc53a4d8e5072d2d8a87fed84ac9", size = 5658740, upload-time = "2026-09-02T14:49:11.9Z" },
|
|
209
|
-
{ url = "https://files.pythonhosted.org/packages/e9/44/27e3cee3dcdb3b7bc09727b642bdbfcd098490ea77df04611db9060d7722/lxml-6.1.3-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7eb78ba28b187e1e9203a55c60fcf70df2d22cb205fe6d51b9383d6097419f0", size = 5245991, upload-time = "2026-09-02T14:49:14.154Z" },
|
|
210
|
-
{ url = "https://files.pythonhosted.org/packages/ca/e9/8312560579fc980bbd2233a8a673cc46f7d613d3633f2bf08a21e8f4ad13/lxml-6.1.3-cp314-cp314-manylinux_2_28_i686.whl", hash = "sha256:ea6b1e9105b4b24a34c722432d9fb578f9ed83af21fa1abda639011e0f22bbb6", size = 5354136, upload-time = "2026-09-02T14:49:16.459Z" },
|
|
211
|
-
{ url = "https://files.pythonhosted.org/packages/74/d8/eda60f4f73a9c780b5d6e1175484f66e6c81a2c93346e2906a1fec9c7a02/lxml-6.1.3-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:e8b17e23df3e827a69d25af70990ca2420e92668aaffaeeb3cd2351d7916a023", size = 4704379, upload-time = "2026-09-02T14:49:19.032Z" },
|
|
212
|
-
{ url = "https://files.pythonhosted.org/packages/ba/c8/c9cc60057be78ac34bd2b842e45e6e88edbfe5e532e82c3b82381b7aab49/lxml-6.1.3-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b7c37339d7e75cab9a123a04248e243cefefb302ad6db566ea0c77cbcde421e", size = 5258676, upload-time = "2026-09-02T14:49:21.306Z" },
|
|
213
|
-
{ url = "https://files.pythonhosted.org/packages/41/7b/66894008fee8d1785b8db129747ae963fd427b68f456918df7f2f24a8b98/lxml-6.1.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:83e3a51e7933db700a0da0db31849db3a24022d9970da9bb73001e1d0326fd92", size = 5090069, upload-time = "2026-09-02T14:49:23.562Z" },
|
|
214
|
-
{ url = "https://files.pythonhosted.org/packages/8b/31/c1b60404859f4c3cd1f41f29c65a24e25cea78fde822d9574a21f66810be/lxml-6.1.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:9bde9ae026a55b9a192078dfa6e27dd0ca4a050171ab6272e92f97b757dfdf48", size = 4741958, upload-time = "2026-09-02T14:49:26.037Z" },
|
|
215
|
-
{ url = "https://files.pythonhosted.org/packages/23/b8/6285f0cf546f14da2554cabdeaf7c2c2ff3190c74807f0de2e8810a786f9/lxml-6.1.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1a635e837b50a1819bebfedaac5916498ea024120969da8790500148fb0a894d", size = 5683245, upload-time = "2026-09-02T14:49:28.438Z" },
|
|
216
|
-
{ url = "https://files.pythonhosted.org/packages/d3/f6/2168cab44336dcb15fed0f0b78577225b83297cdf0dee349c95420c3dcb0/lxml-6.1.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d0c5c362bc94f1929dc7e96e715bbe7bd17037f802e6d8f0d1545df9133c0559", size = 5246087, upload-time = "2026-09-02T14:49:30.955Z" },
|
|
217
|
-
{ url = "https://files.pythonhosted.org/packages/f5/89/32f5de69a0a31f30e6164981851f87b37ecb2c4ee838e504b88d49d4818e/lxml-6.1.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c59e4265608da6a041f54646ecc0c9ecdbb19aaf14c4c684bb6c2114998cc415", size = 5269352, upload-time = "2026-09-02T14:49:33.502Z" },
|
|
218
|
-
{ url = "https://files.pythonhosted.org/packages/a2/a1/741d952ed3a7ef7a50055c6415aec3f067015e97f72f4389ce77b09657ba/lxml-6.1.3-cp314-cp314-win32.whl", hash = "sha256:2e62c569ec7531b679b184cbfe335c501c1d13c4b363560013019962eb630e6d", size = 3662783, upload-time = "2026-09-02T14:50:23.751Z" },
|
|
219
|
-
{ url = "https://files.pythonhosted.org/packages/0f/bc/5811cc73cac05e324e05ba9b0924e1a163a317a167ede8a9c748b11db30a/lxml-6.1.3-cp314-cp314-win_amd64.whl", hash = "sha256:66299564c046bc7e0cc5de5106601eae907e9fa5904cd68a323380a8502f7861", size = 4073951, upload-time = "2026-09-02T14:50:26.348Z" },
|
|
220
|
-
{ url = "https://files.pythonhosted.org/packages/92/18/3768c8b01ac3a9bed1914715e6011711b00e2a11628ffa6f7fa37f8e0269/lxml-6.1.3-cp314-cp314-win_arm64.whl", hash = "sha256:ebd054ad1737a68fb7c5c073d405cef2b88bb824e294de3b4a4e995b47f0e376", size = 3749279, upload-time = "2026-09-02T14:50:28.749Z" },
|
|
221
|
-
{ url = "https://files.pythonhosted.org/packages/72/38/84684784738d9451db2b330de2483f496690c3a5c642071df24135739b37/lxml-6.1.3-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:5a143e6207579de8baeded4eaac9134413200359f1969d636f0bfb98ee8c3c8f", size = 8860296, upload-time = "2026-09-02T14:49:36.346Z" },
|
|
222
|
-
{ url = "https://files.pythonhosted.org/packages/24/b7/fc4c50bb1b38e864010ea396046cabe85129bf9e65b11edcfbc37d356241/lxml-6.1.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a1cec0f99b9b914d39176347a93b7610dc09324491aee1cbc57cd291a41a1d55", size = 4755190, upload-time = "2026-09-02T14:49:39.872Z" },
|
|
223
|
-
{ url = "https://files.pythonhosted.org/packages/94/e2/ee9aa6ed2b666b2db1f6f7fd48964ff9da39ebe827ef5eac0ab881f639d9/lxml-6.1.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f6b9d2aad499c769ee8287609ab0e6de99d8bcea99c6e6c2e64945259fd52fb2", size = 4979517, upload-time = "2026-09-02T14:49:42.153Z" },
|
|
224
|
-
{ url = "https://files.pythonhosted.org/packages/29/e3/e7763d1661b283ddd4fa36f91b9a497db6b8d2aff55028b16c7f642e0755/lxml-6.1.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a23fefdb345b2d4d0ff2860571b5ff9a89a28b6a120f720e8fb0324d346626", size = 5115270, upload-time = "2026-09-02T14:49:44.493Z" },
|
|
225
|
-
{ url = "https://files.pythonhosted.org/packages/2d/cd/22205d5b4d177e3f4156f780412426ee7c7f8107809f119f0dcc40fa51e3/lxml-6.1.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:545ccc14fb05485f48b4439ec35beb16d5b5280eb6c81c658bd4707a2a119414", size = 5032449, upload-time = "2026-09-02T14:49:46.841Z" },
|
|
226
|
-
{ url = "https://files.pythonhosted.org/packages/da/43/06a4626c3bb79ef8c501b674afab8100d64e798665bb2a97d1c960636a49/lxml-6.1.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:93476b6514b373fc6ca67d26c442784f7807c86f00635bfe79f935c3eab2af17", size = 5603325, upload-time = "2026-09-02T14:49:49.664Z" },
|
|
227
|
-
{ url = "https://files.pythonhosted.org/packages/d0/9c/733682a0c2de9f5779ba207bbb3f3f6be8c6bda863fc01739b186b38783a/lxml-6.1.3-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8db38ff3fb7aee7d6a82ae4da2eef1178656fe1216841fbd24870062a9d60473", size = 5229023, upload-time = "2026-09-02T14:49:52.447Z" },
|
|
228
|
-
{ url = "https://files.pythonhosted.org/packages/c6/8a/e69cdaca3fd33a647942925664f01b20908d41a6968c182305be9c38fb11/lxml-6.1.3-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:25f4118c438f96bb466e83108506d03d5c31b1bd2387e83e5b070bda6ded9c37", size = 5317811, upload-time = "2026-09-02T14:49:55.25Z" },
|
|
229
|
-
{ url = "https://files.pythonhosted.org/packages/2e/b2/0c397588174403c2ab68fc464abf97e03e7324f9c6cb6a99023104707195/lxml-6.1.3-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:1beb0f9909b26cee938df9ba56b15252a84429b1fc30ce6fca161390b9789a70", size = 4646516, upload-time = "2026-09-02T14:49:57.761Z" },
|
|
230
|
-
{ url = "https://files.pythonhosted.org/packages/56/7e/cfea25afafbe49db8b225764f7f74bb37c2a7f5e717d917d3d4a5e098ed4/lxml-6.1.3-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3a27ac6c780c8b8a1cd231b58407634cafc1c4cc28cd6c7141362df0f36351e7", size = 5240626, upload-time = "2026-09-02T14:50:00.279Z" },
|
|
231
|
-
{ url = "https://files.pythonhosted.org/packages/a1/75/7a587771bb52ebb0e2c57b6dbe9fd96a70fbb54d72ddd97d54c5f8ec18d5/lxml-6.1.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a1932d7ce78a561367512c594fe66eac2b2ec9b9264cfd9b5f950622f4a116e2", size = 5086619, upload-time = "2026-09-02T14:50:03.245Z" },
|
|
232
|
-
{ url = "https://files.pythonhosted.org/packages/1e/01/94c0ebe6d831861542d251e038052e52bf6d33f1d18f1cfffdc82851065a/lxml-6.1.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:7d0f5976aa2701996f759b30172925829867547bb073af0ae67d1307a0f0262c", size = 4758828, upload-time = "2026-09-02T14:50:05.873Z" },
|
|
233
|
-
{ url = "https://files.pythonhosted.org/packages/1f/f1/938d67bd0e5b1fdfa52be28aefdffbad57e1f6b8e921c2aab88542c75f40/lxml-6.1.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e7ce578aa8a80910a72a8ca0bbea3baae10100827249001999726a788456d8", size = 5627083, upload-time = "2026-09-02T14:50:08.555Z" },
|
|
234
|
-
{ url = "https://files.pythonhosted.org/packages/d8/65/4e51522f6c214650db0abb7b16ccd11b1238b8a05a8d59aa4ebed59c9f67/lxml-6.1.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d97c5227621af74b111882a290b10f371780a38eef9d9e730408fba2259b52fb", size = 5235170, upload-time = "2026-09-02T14:50:11.255Z" },
|
|
235
|
-
{ url = "https://files.pythonhosted.org/packages/92/c2/e73d19365665f6b16ef84df21199befc3b06e4c539046ad2d9595f6fb9ea/lxml-6.1.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:da707f14ea3c35ee463d50acd596d6488e4b2b4ae7cf77a5bf93f55c023d63e8", size = 5252273, upload-time = "2026-09-02T14:50:13.782Z" },
|
|
236
|
-
{ url = "https://files.pythonhosted.org/packages/48/a9/7f386c84c9fe2854e1ca6e231c285e1c8f392971ac353c6865e6ec49faff/lxml-6.1.3-cp314-cp314t-win32.whl", hash = "sha256:9efe56a68179f3adc4de41861c9358931db03837c48dd5e1c78077b84dd07f3a", size = 3902712, upload-time = "2026-09-02T14:50:16.171Z" },
|
|
237
|
-
{ url = "https://files.pythonhosted.org/packages/82/a6/8a3eb793f7900ef01c7f99e6f5fcbcfbdff35251cfaef66b32a4c16352d6/lxml-6.1.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c9389b3784b56c58d933b5e0aecdf28f901b073ff385358d8a7d40907f6e14b2", size = 4400979, upload-time = "2026-09-02T14:50:18.621Z" },
|
|
238
|
-
{ url = "https://files.pythonhosted.org/packages/cc/c4/3807bea283b4fe9e9d9f5dde46a73df91178472b335d2778e10b2a37aa22/lxml-6.1.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32a409be3190b088f960ac92bfedfbef2f86c49ff940765e1548177592d20026", size = 3823401, upload-time = "2026-09-02T14:50:21.119Z" },
|
|
239
|
-
]
|
|
240
|
-
|
|
241
|
-
[[package]]
|
|
242
|
-
name = "paper-docx"
|
|
243
|
-
version = "0.2.0"
|
|
244
|
-
source = { registry = "https://pypi.org/simple" }
|
|
245
|
-
dependencies = [
|
|
246
|
-
{ name = "lxml" },
|
|
247
|
-
{ name = "typing-extensions" },
|
|
248
|
-
]
|
|
249
|
-
sdist = { url = "https://files.pythonhosted.org/packages/70/dc/bdc50405502a1a92707284005c1fab3e9e61fd3a7894a18bd80e24ac1920/paper_docx-0.2.0.tar.gz", hash = "sha256:034a961dc42eb44d7676e3a5af7ded485e89eb97851f8ccb24c481355b2c9d7d", size = 7291150, upload-time = "2026-08-24T23:37:59.805Z" }
|
|
250
|
-
wheels = [
|
|
251
|
-
{ url = "https://files.pythonhosted.org/packages/f8/c6/b54eb65833f5c59e10be4d8f3f422eefba440aa805cca345f80410383975/paper_docx-0.2.0-py3-none-any.whl", hash = "sha256:d61b6c1e23c2e50364ca9ebf913b08121bba12dc9119ffd0047ad927ff29ace0", size = 439210, upload-time = "2026-08-24T23:37:58.225Z" },
|
|
252
|
-
]
|
|
253
|
-
|
|
254
|
-
[[package]]
|
|
255
|
-
name = "pillow"
|
|
256
|
-
version = "13.0.0"
|
|
257
|
-
source = { registry = "https://pypi.org/simple" }
|
|
258
|
-
sdist = { url = "https://files.pythonhosted.org/packages/ce/a4/9cc30690a394a8305e8be4c9036aa16d0dfddadd09079860b582f562496d/pillow-13.0.0.tar.gz", hash = "sha256:cdcd1ba258178f7356d74170c9a81ba4eab6a5d55748bc402a5a2a6fe6be3510", size = 47058631, upload-time = "2026-10-16T22:18:09.718Z" }
|
|
259
|
-
wheels = [
|
|
260
|
-
{ url = "https://files.pythonhosted.org/packages/7a/b8/58d79332229482eb0d27c82973850808c19d37e5bdc14443d3417bd373f5/pillow-13.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:67c8d44ad89fa7eb88de5d6ef6199b1e03dd24974f85a67639fc8badb801fe79", size = 5568643, upload-time = "2026-10-16T22:15:44.474Z" },
|
|
261
|
-
{ url = "https://files.pythonhosted.org/packages/39/4b/f2ed53d83aa44ac19599ac0a54897f867fafb95f406980d1e24083f8cbe3/pillow-13.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc481f742ccda20e9ed760b8f978dff50f2a4e9bc253ac167fb0a05b0783ef52", size = 4852329, upload-time = "2026-10-16T22:15:46.284Z" },
|
|
262
|
-
{ url = "https://files.pythonhosted.org/packages/3b/bb/9e30e8ed18c20800ee327a12107d5249ad8dc444867b3adfcc21654e3c71/pillow-13.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8bf295fe459343bc6093c8e5e0df60bfa189e0fcb775a22e2c2488fdeccc6c0d", size = 6519309, upload-time = "2026-10-16T22:15:48.14Z" },
|
|
263
|
-
{ url = "https://files.pythonhosted.org/packages/e6/99/fdf65cc539e266ab93546c261bdf98411fe165c6e4e13f9dbf597097192b/pillow-13.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42d63be3af4f9b951b199b0a9d23365d37ab14687e6d77b74940432c8515c4ca", size = 7144542, upload-time = "2026-10-16T22:15:50.093Z" },
|
|
264
|
-
{ url = "https://files.pythonhosted.org/packages/26/9b/f38b7c4d8f599537e2d1a6d546cec9beef7536ff8f5c49a3f9c78179d8ac/pillow-13.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4bd024d567eca931b668978d672dba914d4b8e2628e2c3073a2ad178de8a2620", size = 6618042, upload-time = "2026-10-16T22:15:52.054Z" },
|
|
265
|
-
{ url = "https://files.pythonhosted.org/packages/a8/7c/45ee28531f89ee4582967d8a17f7a26d71ca64cd902b93c269590cd60a00/pillow-13.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:23edf4ec4b6f4f240e8df6e4985e9ee2ced86474632433e55fb1e2548744bf40", size = 7228137, upload-time = "2026-10-16T22:15:54.009Z" },
|
|
266
|
-
{ url = "https://files.pythonhosted.org/packages/01/bc/9c2a969cb1b70201d04fa17fd5aedf02a732870b8da86bceaaa30b0ca385/pillow-13.0.0-cp312-cp312-win32.whl", hash = "sha256:02464da86f561f410e13b061ec37c3068a9cb557a095494157742d07b3c24a27", size = 6515423, upload-time = "2026-10-16T22:15:56.25Z" },
|
|
267
|
-
{ url = "https://files.pythonhosted.org/packages/ff/cd/73a79ecdc822076002eb24b5e1e4a530b0bb5310fcb6d239abbec877110b/pillow-13.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:ff3fe9eb621fbb9db4c4be33ab946f6bac5f98ab50ca8d3260503653656c961b", size = 7272166, upload-time = "2026-10-16T22:15:58.597Z" },
|
|
268
|
-
{ url = "https://files.pythonhosted.org/packages/4a/a3/be5a1236efd085b3984e4305da8f179ae9dab80c991d2ad78f2bd5c4c843/pillow-13.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:c3bc8ee0271387e0b1e3ad0ff893645990a656e79bf9c42f4f734a3642b11d51", size = 2698943, upload-time = "2026-10-16T22:16:00.637Z" },
|
|
269
|
-
{ url = "https://files.pythonhosted.org/packages/82/e2/9132d38df320e8099e2642d9fa538f18a7dfebf68a875a31725dc2a115aa/pillow-13.0.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:e98b4f91f99b24b1da72e10621ba181f7281922384a7403094debb4199de6c00", size = 4190620, upload-time = "2026-10-16T22:16:02.527Z" },
|
|
270
|
-
{ url = "https://files.pythonhosted.org/packages/cb/be/436dac0996876f65ef1916ffb711c5ef4af2ebc57414b6f16642e07f6b47/pillow-13.0.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:34fb3db1149c879343861831728c243c432d4a5afc8f1878ca7612ef8de2a033", size = 4290286, upload-time = "2026-10-16T22:16:04.861Z" },
|
|
271
|
-
{ url = "https://files.pythonhosted.org/packages/60/16/7c1007162e4169ea0d5bec47e2e0b2174f56c50cf5b8c02a1dc23e41037e/pillow-13.0.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:2d50500a4a3bc6469adcdb319cf05d688b08ca3bf0f22a05339f3b25b433a599", size = 3723169, upload-time = "2026-10-16T22:16:06.956Z" },
|
|
272
|
-
{ url = "https://files.pythonhosted.org/packages/08/bc/578ab2eaa04705a8978bd9be0fe15c3d43a8fc95097c4f7e39540e79e4fa/pillow-13.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ef5fe6b7db3f501c56000ba8fe7c7e1a35ca1d45824fbeb95a67daa85cff4dbe", size = 5568469, upload-time = "2026-10-16T22:16:08.664Z" },
|
|
273
|
-
{ url = "https://files.pythonhosted.org/packages/98/c8/ccede3dcc4f274b80fb49199eed1ef34ba05566c8b71976b9d1f111da2e3/pillow-13.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f11a3c1358bb3c68012a7b1f41b223c3db9f7bfde90b481df028cfe1c3363313", size = 4852187, upload-time = "2026-10-16T22:16:10.693Z" },
|
|
274
|
-
{ url = "https://files.pythonhosted.org/packages/fb/3c/cd0770e96d20bfd990db024bcbd43897ff3e88da1f4782cf90ea231b1d4f/pillow-13.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19b66ca0a4d25cc0200b381ce824c7ea090db61427315e73cfb05dbf1b35c369", size = 6515908, upload-time = "2026-10-16T22:16:12.896Z" },
|
|
275
|
-
{ url = "https://files.pythonhosted.org/packages/ef/fe/f5cdaa2d1c4086e757430f368c271a58ee29cfe7378e7ae7b9d964015c25/pillow-13.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5f56499c1a74d2b862beb0c33b8016f99d095858455df9d21583bbbc1c15b582", size = 7142544, upload-time = "2026-10-16T22:16:14.844Z" },
|
|
276
|
-
{ url = "https://files.pythonhosted.org/packages/fb/b5/a54f6d44adbcd23737c8c12953f42be107e4cca64e247c0ca3a5b563061c/pillow-13.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2a14cd73d5e6c927f644b0110ee81f59c4ef506259ec9183904747f2caacc81", size = 6613097, upload-time = "2026-10-16T22:16:16.893Z" },
|
|
277
|
-
{ url = "https://files.pythonhosted.org/packages/e6/b4/9e6c1207c21b2e91db0d15c16d30f3701ce5add1bd4da0e787761e66cb6e/pillow-13.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:08b826a9bf1265c76de04a42061d61ea6b109418b7826f28ff1ecdfaa26c5502", size = 7224846, upload-time = "2026-10-16T22:16:19.195Z" },
|
|
278
|
-
{ url = "https://files.pythonhosted.org/packages/78/9f/d3c3cb0518f3dd1eee0ef501535f53d15597a53c5c4118d178086143397a/pillow-13.0.0-cp313-cp313-win32.whl", hash = "sha256:12b0fa15879fe5a9d9eebe66e4e2d74128a773b1a4448010c9c714f45e04b9d8", size = 6516013, upload-time = "2026-10-16T22:16:21.389Z" },
|
|
279
|
-
{ url = "https://files.pythonhosted.org/packages/d7/ed/1b16fb66a37e1b9e41370b93b2c614c7da761a5b2a41dc333f7af4639962/pillow-13.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:9dda0788a9932776a75d8bcc020076edc308ce2508b51f6739a45e3158b3fc42", size = 7284777, upload-time = "2026-10-16T22:16:23.393Z" },
|
|
280
|
-
{ url = "https://files.pythonhosted.org/packages/87/7d/8d02eba9f7ecc87f8e90f731e032cc4773802f2a843763afd0c66a535ff4/pillow-13.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:40a266371ece581e5de13b6635ef78d7487824af80561b6ca27694a88c19bc0f", size = 2698826, upload-time = "2026-10-16T22:16:25.382Z" },
|
|
281
|
-
{ url = "https://files.pythonhosted.org/packages/8e/45/fbad9c7f5e2f1745c373a434d46072bc84eddfefaa28b852425ac957fda6/pillow-13.0.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:44629d4498c9cb6b2051806155f22141df0d8a929c56134b166655232dfb2f8c", size = 4190721, upload-time = "2026-10-16T22:16:27.524Z" },
|
|
282
|
-
{ url = "https://files.pythonhosted.org/packages/a2/bf/2074902a259a90692c5dbf132885d21671644cbbd3f690047516243a55db/pillow-13.0.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:bf97ba1b5542050e9b0c74e632323b6d8136cc99d64e193abebee22fe6013c76", size = 4290236, upload-time = "2026-10-16T22:16:29.562Z" },
|
|
283
|
-
{ url = "https://files.pythonhosted.org/packages/ff/a5/3d1bb93b8ea38d15d21356c1b8e9f50971ac592aaa248f7fb71739094c0e/pillow-13.0.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:aa694c49787040943570d61c9b8fc01271bd2a2cfdd55f0d896f8aecdce1a981", size = 3723093, upload-time = "2026-10-16T22:16:31.249Z" },
|
|
284
|
-
{ url = "https://files.pythonhosted.org/packages/84/a1/be060135d85187b25fa8b2573786c0e45c62ae27527fff5257675eb97f4a/pillow-13.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:49c12af515073e9bf511e4ef736743bf70d531a643668722279314b937742ba4", size = 5572253, upload-time = "2026-10-16T22:16:33.103Z" },
|
|
285
|
-
{ url = "https://files.pythonhosted.org/packages/b5/f4/0bf6f1ac9ba7ee2ffe9914aeb410a1035a0c1a3c42f122388d7fc950bc4b/pillow-13.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d9b0a2bee3f3e03e9f29057aedb807dbf1e1d96ee1b9d0f422d9db6c8583271d", size = 4852269, upload-time = "2026-10-16T22:16:35.102Z" },
|
|
286
|
-
{ url = "https://files.pythonhosted.org/packages/83/16/b603274617b3e6728da3a0133d4fba1ea8d7fbe0c4ea5fef9cbffa398b8b/pillow-13.0.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5933fcea5a5ba64c686f55c886a115cbfd92f2900460784a1e79909fdbafd7b6", size = 6516058, upload-time = "2026-10-16T22:16:37.228Z" },
|
|
287
|
-
{ url = "https://files.pythonhosted.org/packages/1d/f2/1371707ce438ba9a43f9d24089828494ec6f9396e28cd7903aa704dd6306/pillow-13.0.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e91c2b1cbeae768c98752e67e717e283d68dae45717b41f2d91eaee648e37b7d", size = 7142574, upload-time = "2026-10-16T22:16:39.172Z" },
|
|
288
|
-
{ url = "https://files.pythonhosted.org/packages/b9/a9/62cf68587f910bc87c5951bcb6e9430c7643a65076adf5f18b4bf350e2bd/pillow-13.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f6299e494e46253d40c34653cac369412f44ca53b5f85d848d3f95b1ed0546c", size = 6614295, upload-time = "2026-10-16T22:16:41.117Z" },
|
|
289
|
-
{ url = "https://files.pythonhosted.org/packages/6c/c9/9e9b48178649730299be0bafbf5f810a5b6977538f5a92d47e4ba5f5d608/pillow-13.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f9bd7d260d986f3553518c5d723544346fa48031f8aef3265d786aeb59845bc0", size = 7224841, upload-time = "2026-10-16T22:16:43.118Z" },
|
|
290
|
-
{ url = "https://files.pythonhosted.org/packages/8f/48/c44e91384b1b6c072a714a63d00608acc16a6a968735e478e4be4384e5ac/pillow-13.0.0-cp314-cp314-win32.whl", hash = "sha256:2e31c4e68cffd7b1f116127626813b82fcba19edf6b940a7b0c266d6484d0055", size = 6508694, upload-time = "2026-10-16T22:16:45.883Z" },
|
|
291
|
-
{ url = "https://files.pythonhosted.org/packages/50/e2/7ad17747517e4c813dca78257d6bb593466f8231baf1384bc98d92745edb/pillow-13.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:f7cbb7a64e7ec664775195e4f81923bc8a93d9451b963f844e59118f63147a7a", size = 7281830, upload-time = "2026-10-16T22:16:47.725Z" },
|
|
292
|
-
{ url = "https://files.pythonhosted.org/packages/41/9f/e5b51f2ce8ef4563215334035403ce61a244f93a2e65c24a940131618f87/pillow-13.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:a6aaa7871aebca081eb5c45f83e845bbd9712ae99fa9286dbfdcee835e63f4b4", size = 2695468, upload-time = "2026-10-16T22:16:49.515Z" },
|
|
293
|
-
{ url = "https://files.pythonhosted.org/packages/97/73/a53502f731f6c84805a4ce87a8881e86d07a65aee64728b900d112dc703e/pillow-13.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7b999816b5850a35ada08443e6e03945f1f6488144a83afe2d37b240a552aafa", size = 5578196, upload-time = "2026-10-16T22:16:51.291Z" },
|
|
294
|
-
{ url = "https://files.pythonhosted.org/packages/21/50/7e949959a56b5559c78ef172b70fc6025706acb289f3f648a15329e4fa6f/pillow-13.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:67871a13cf47275201553b536c025da777f997fa562a19eb798af4ad4b97c18f", size = 4857276, upload-time = "2026-10-16T22:16:53.399Z" },
|
|
295
|
-
{ url = "https://files.pythonhosted.org/packages/c9/52/43ded0ac08e77e39d17bd6d894162572201b5e8fdc4a022b14c55a1960a4/pillow-13.0.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e8ca8f69b7c77fa96dad99f8638c1fc4f1c0bed4acaa1baf7a3c31bdb80a0ab1", size = 6607008, upload-time = "2026-10-16T22:16:55.525Z" },
|
|
296
|
-
{ url = "https://files.pythonhosted.org/packages/0d/2e/4a57ed216d5bf877387cba4d44c02aa87abe51ad2e06404aa6b597c4da39/pillow-13.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6bce6a29c3898191f4c9998e4d4e8f69790caeabde46e54da4bc235ce5bde683", size = 7224281, upload-time = "2026-10-16T22:16:57.738Z" },
|
|
297
|
-
{ url = "https://files.pythonhosted.org/packages/5c/3d/2929b248e135752d63aaeabf53f6de797e905b7b6263f9c1e2adade20aba/pillow-13.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:816752a5ef76a80484c8c441c85593b7ea9304f6231fc5776ad1fbff7e773058", size = 6695600, upload-time = "2026-10-16T22:16:59.842Z" },
|
|
298
|
-
{ url = "https://files.pythonhosted.org/packages/bc/33/fb0da992cf084ed1ee6ee05e96b6191e35c351eb707ca2df874feb24ce47/pillow-13.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5bdb38ba220b61b4ec31dd1046dea6b016d3c6850a23f43ed8b58332b2fc668e", size = 7300589, upload-time = "2026-10-16T22:17:01.686Z" },
|
|
299
|
-
{ url = "https://files.pythonhosted.org/packages/bb/af/c30dd9ef6a3dce84ecb1b2393cac629047a32e66279056c6cb46c3ffd65c/pillow-13.0.0-cp314-cp314t-win32.whl", hash = "sha256:06903aac074d00c988e77a1fc435286dc498506d4ca8d6f69df9babddf4ecc15", size = 6517204, upload-time = "2026-10-16T22:17:03.722Z" },
|
|
300
|
-
{ url = "https://files.pythonhosted.org/packages/85/d5/ef3a8ae7609c8ab26570abf18194882534b480d245a9148b895a2262c004/pillow-13.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9a635068d9793c7f0d929f39f18b58f1bd86c236e8e7b64167b86af9232ebca0", size = 7286695, upload-time = "2026-10-16T22:17:05.543Z" },
|
|
301
|
-
{ url = "https://files.pythonhosted.org/packages/84/3c/0861db0c69a03689ebe3e7599d35668a414deb5aaafd8255215e4e62e3d3/pillow-13.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0d1a9cf7bc6917538b20f8d06b9ab2147e542f68849e96fc58eb66bdf6acc692", size = 2698098, upload-time = "2026-10-16T22:17:07.674Z" },
|
|
302
|
-
{ url = "https://files.pythonhosted.org/packages/60/da/f6d644e631c5b370c5d0b899f3ccadd2780aab070b29a110527cf4e1fd2c/pillow-13.0.0-pp312-pypy312_pp80-macosx_10_15_x86_64.whl", hash = "sha256:8619685cad8efc4c38c66d3b36aad854523297c43d748b3b6f0cc03c90ba3463", size = 5523188, upload-time = "2026-10-16T22:17:59.334Z" },
|
|
303
|
-
{ url = "https://files.pythonhosted.org/packages/e4/b0/2594f202d743a35d4fe80682bfd96f277e5ca7aecb27cf64ef5bfc1d000b/pillow-13.0.0-pp312-pypy312_pp80-macosx_11_0_arm64.whl", hash = "sha256:7e91e97a929232cdb828889ee6ad0e48d7f40f4ec38818f4e4a8968b2b1af22e", size = 4806808, upload-time = "2026-10-16T22:18:01.188Z" },
|
|
304
|
-
{ url = "https://files.pythonhosted.org/packages/8e/ed/d504165ef79af6fafe25c76726cf30f544cc236002f7ed054f1d51adc4ff/pillow-13.0.0-pp312-pypy312_pp80-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93ff9c9c3663ce23aaa5d0b6b6abac55359e2a0c06c7e30f3771829af816be63", size = 5464358, upload-time = "2026-10-16T22:18:02.779Z" },
|
|
305
|
-
{ url = "https://files.pythonhosted.org/packages/7b/fe/a10aba5503ca13e9e009b8bd0a1a4ce5584bdce246245fd6f3a83701369c/pillow-13.0.0-pp312-pypy312_pp80-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e65dd6e75de67b2362a4fa3e16aa627595f65054dc4ec73d64680c84d592fa61", size = 6043514, upload-time = "2026-10-16T22:18:04.538Z" },
|
|
306
|
-
{ url = "https://files.pythonhosted.org/packages/c0/37/66b12dc476041fe523bca29c9d58fbf1ea92a4eaf73acfb9e993948f1191/pillow-13.0.0-pp312-pypy312_pp80-win_amd64.whl", hash = "sha256:567f20f1c75897d7663830da6ea8af719e03d712b1d9ee7f813319f9ece42e5a", size = 7366030, upload-time = "2026-10-16T22:18:06.638Z" },
|
|
307
|
-
]
|
|
308
|
-
|
|
309
|
-
[[package]]
|
|
310
|
-
name = "pycparser"
|
|
311
|
-
version = "3.12"
|
|
312
|
-
source = { registry = "https://pypi.org/simple" }
|
|
313
|
-
sdist = { url = "https://files.pythonhosted.org/packages/cb/27/eeb9f307bf07060f3d9f9aa0fb8c15b01bdfded0a941e4b2719c7f94cacd/pycparser-3.12.tar.gz", hash = "sha256:f03387877eab82ce01bbdfd0ba7252ee55a90b1c708d5129e2ce915475cf1db6", size = 158785, upload-time = "2026-10-22T13:40:03.56Z" }
|
|
314
|
-
wheels = [
|
|
315
|
-
{ url = "https://files.pythonhosted.org/packages/b6/ae/315bbeee126a769cbde43cf4908acb4b40408d8bf8bbf334dd7368d8dadf/pycparser-3.12-py3-none-any.whl", hash = "sha256:a076f3f489b39b43ed13563a1dafe42447445bec2e294154ec5c57fcdda4c85e", size = 62600, upload-time = "2026-10-22T13:40:02.021Z" },
|
|
316
|
-
]
|
|
317
|
-
|
|
318
|
-
[[package]]
|
|
319
|
-
name = "pypdf"
|
|
320
|
-
version = "6.21.4"
|
|
321
|
-
source = { registry = "https://pypi.org/simple" }
|
|
322
|
-
sdist = { url = "https://files.pythonhosted.org/packages/1e/e1/ec8f4d155c997c45917153a5521e60d6ee6389d68abdcbc8e44e564caffc/pypdf-6.21.4.tar.gz", hash = "sha256:c8817e3f888d47a087872ded69812c1ef30cacb871d6e053e0c00bbaf0bc2163", size = 7109255, upload-time = "2026-10-28T17:00:54.81Z" }
|
|
323
|
-
wheels = [
|
|
324
|
-
{ url = "https://files.pythonhosted.org/packages/3f/4b/77e8ad4ac42c9d93600f40541a50e9feb3a61d2bbee2d76f659346072051/pypdf-6.21.4-py3-none-any.whl", hash = "sha256:33e4fb41ca352810eb4e9838aa0d82d6888a5f8bf682f43e99cce5faa666255c", size = 410430, upload-time = "2026-10-28T17:00:53.146Z" },
|
|
325
|
-
]
|
|
326
|
-
|
|
327
|
-
[package.optional-dependencies]
|
|
328
|
-
crypto = [
|
|
329
|
-
{ name = "cryptography" },
|
|
330
|
-
]
|
|
331
|
-
|
|
332
|
-
[[package]]
|
|
333
|
-
name = "pypdfium2"
|
|
334
|
-
version = "5.14.0"
|
|
335
|
-
source = { registry = "https://pypi.org/simple" }
|
|
336
|
-
sdist = { url = "https://files.pythonhosted.org/packages/95/d0/c81d3a7c2a9af37b817ace1de0acd40cf44d15f12407c5e86b3668364a5c/pypdfium2-5.14.0.tar.gz", hash = "sha256:c5f009b3157f10e97dceb55963f5910eff92feb00587ba10a76f12b87ce1a4b6", size = 376498, upload-time = "2026-10-04T15:19:19.835Z" }
|
|
337
|
-
wheels = [
|
|
338
|
-
{ url = "https://files.pythonhosted.org/packages/91/03/79e89eac9d811e83d606342e129f5f39e168442ddf23b024fea4a7ee4762/pypdfium2-5.14.0-py3-none-android_23_arm64_v8a.whl", hash = "sha256:bed597b2cea3990164e43f9003f71db18959d0abd5d73adc9c176e7be2d84b98", size = 3453370, upload-time = "2026-10-04T15:18:40.79Z" },
|
|
339
|
-
{ url = "https://files.pythonhosted.org/packages/cc/68/369b80e408017b18eaecaa3c730bded07d90bfb65562215df200b56fb8e2/pypdfium2-5.14.0-py3-none-android_23_armeabi_v7a.whl", hash = "sha256:1951f0aed469150b13c62eabd501a9839e608ab9983ca8579be9eb73213b72b6", size = 2889924, upload-time = "2026-10-04T15:18:42.825Z" },
|
|
340
|
-
{ url = "https://files.pythonhosted.org/packages/d1/ea/14673bc9d8b7beeaa1eb46e9951b22543edaf2a4676c586e3b1e032ff6ee/pypdfium2-5.14.0-py3-none-macosx_13_0_arm64.whl", hash = "sha256:2de384df66ba55fcaab0775f30f28ec1090af3dfa60276a07821efc96d993118", size = 3542294, upload-time = "2026-10-04T15:18:44.345Z" },
|
|
341
|
-
{ url = "https://files.pythonhosted.org/packages/a6/11/b720097b01fa0874854f2f6669cbea4e4ea4e075769687714fac64d68964/pypdfium2-5.14.0-py3-none-macosx_13_0_x86_64.whl", hash = "sha256:e4e203ea9710fd00e5448edb6f1615dc8587035357f75f40b432dde0c33e8da1", size = 3735845, upload-time = "2026-10-04T15:18:45.975Z" },
|
|
342
|
-
{ url = "https://files.pythonhosted.org/packages/92/b4/0c31aa51887cd6cd032191dfe010a6d01ed43cf03204cfbd2184ebe4b715/pypdfium2-5.14.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1b696e6901e16f114a2ec6332e5e3f8f5033a901614ead28499ab18ca6024f5", size = 3719672, upload-time = "2026-10-04T15:18:47.455Z" },
|
|
343
|
-
{ url = "https://files.pythonhosted.org/packages/93/a8/ae6ef96bf66559328d07b9e402ea704352ea00c49b6a73573da57e1fb378/pypdfium2-5.14.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:593f2c952ae3ffdca0efcbb3d9464fbccb876254386114ff900cabef21157c3f", size = 3435593, upload-time = "2026-10-04T15:18:49.131Z" },
|
|
344
|
-
{ url = "https://files.pythonhosted.org/packages/59/ff/a78405fab4c8bad0ec25b49c5efba2c85ed14609ec73645f95220560bd81/pypdfium2-5.14.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d436ee9e024f981e68f5775f5a9d115f93ea14ee6c2c6efd35dd17d83edf4942", size = 3868604, upload-time = "2026-10-04T15:18:51.304Z" },
|
|
345
|
-
{ url = "https://files.pythonhosted.org/packages/5d/6e/09e9b62ab66c9acef5ad14f8a8c0d7b4d8d6ea6492e4e65b612ef146d373/pypdfium2-5.14.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f6f13bbcc5f4adabc2676e52f662c6cb375de86b314790b0ae08f3ab62eb116a", size = 4279333, upload-time = "2026-10-04T15:18:52.948Z" },
|
|
346
|
-
{ url = "https://files.pythonhosted.org/packages/4f/a3/c9cc797fc8bdfb8f37b9b0f8b9d02a5fc196b2015f408d53624cab5b0519/pypdfium2-5.14.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f281613fa22313d9c7ab89947665e84eccf8ebe40e1198a84a88352305648d", size = 3799581, upload-time = "2026-10-04T15:18:54.913Z" },
|
|
347
|
-
{ url = "https://files.pythonhosted.org/packages/b9/76/54355a4bbd88bdd5ed3f4405bdc345eb593df9995daf90d285cbdf5c1410/pypdfium2-5.14.0-py3-none-manylinux_2_27_s390x.manylinux_2_28_s390x.whl", hash = "sha256:51d9e9b64ebc34effaf57f9b6d4511b3f66ad3744bd1690d2cc6700853173dcf", size = 4113022, upload-time = "2026-10-04T15:18:56.774Z" },
|
|
348
|
-
{ url = "https://files.pythonhosted.org/packages/7d/bc/ea461961ed0e0c4866df7a5610e76f769ef468bff28cd007e2aeecc8b882/pypdfium2-5.14.0-py3-none-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:605ab9d0d4c5e223599c9065b88d16b2c1f131c807c80dea8adbb16f1433e95b", size = 4062832, upload-time = "2026-10-04T15:18:58.471Z" },
|
|
349
|
-
{ url = "https://files.pythonhosted.org/packages/32/30/dde99bc8cb3f8ace1d856095c2b4a29c80eecf9089b186a3b0845d0abc69/pypdfium2-5.14.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:382de7fe20d32c42993a274d7b6c555a5623a97570dfc1d2f5e0a16fe0d5d482", size = 5058436, upload-time = "2026-10-04T15:18:59.993Z" },
|
|
350
|
-
{ url = "https://files.pythonhosted.org/packages/ec/16/5314182dda2695fdf5bd414a450ee866087068cca4725703932770d4be04/pypdfium2-5.14.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dbfd6deff68cc46b134acd6be380d98d694a9f018fbb622c07229225c85db389", size = 4595505, upload-time = "2026-10-04T15:19:01.835Z" },
|
|
351
|
-
{ url = "https://files.pythonhosted.org/packages/63/3f/474c42e726f0020095c7d5f3fb88cfd4e5d39c1361105a72899ada0ecd1b/pypdfium2-5.14.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9f4d77db5232826dd03a63481f32164331b96c21fd68f0667b2e43dbae141a93", size = 5309775, upload-time = "2026-10-04T15:19:03.564Z" },
|
|
352
|
-
{ url = "https://files.pythonhosted.org/packages/6b/0c/723a6cf11cff00f125310d8c2c08362dc6c100d05fff8f92285a4df1bd41/pypdfium2-5.14.0-py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:b40a0913196a1483f0fdc22a53f8719c3aef87f1c4d8d9c38d2ad4e207500fdf", size = 5224565, upload-time = "2026-10-04T15:19:05.264Z" },
|
|
353
|
-
{ url = "https://files.pythonhosted.org/packages/5c/c5/86ab02a41e77a7aa962af6545a406815aeb9abaecd9f25dec34dbc336b72/pypdfium2-5.14.0-py3-none-musllinux_1_2_riscv64.whl", hash = "sha256:790e2cac1641a65912b73bd7243f45195d36f1663c85a3e1a126a8f5867c82a3", size = 4704416, upload-time = "2026-10-04T15:19:07.05Z" },
|
|
354
|
-
{ url = "https://files.pythonhosted.org/packages/ac/de/fb75013f924c5a4dde4a4a41ec13e7495f9b80022bf35dd51baa54e05910/pypdfium2-5.14.0-py3-none-musllinux_1_2_s390x.whl", hash = "sha256:09b99c8f0cb427eb17fec13c0862ed598bba34b4843df153f70fff806a2820bc", size = 5163621, upload-time = "2026-10-04T15:19:09.021Z" },
|
|
355
|
-
{ url = "https://files.pythonhosted.org/packages/cd/77/e59c814f10b533bc4565abe90ccef888ba29be45ada4627ebbf710961f0d/pypdfium2-5.14.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e70d87cb0577eab38f2106f9c9606b458930beef612a1b5f298772ed259f5ec0", size = 5121606, upload-time = "2026-10-04T15:19:10.609Z" },
|
|
356
|
-
{ url = "https://files.pythonhosted.org/packages/21/25/e067396b4bdd26c19f0997bfa3422d3975a49ceec2c59668e7599f2adcba/pypdfium2-5.14.0-py3-none-pyemscripten_2026_0_wasm32.whl", hash = "sha256:c73be14076bedebd9bcaf9b062579c95c668580043bccd29eb0db502101d5716", size = 2675501, upload-time = "2026-10-04T15:19:12.588Z" },
|
|
357
|
-
{ url = "https://files.pythonhosted.org/packages/7f/0c/6c21f68a57d0c4c506b9e5f72506ba91d8dde47eef699f3fd9561f7bff0e/pypdfium2-5.14.0-py3-none-win32.whl", hash = "sha256:9fd5cc94a389d50298e4d8cb79af6b9b8e0d785606e2a937725dc6e271c9c6e6", size = 3805374, upload-time = "2026-10-04T15:19:14.357Z" },
|
|
358
|
-
{ url = "https://files.pythonhosted.org/packages/00/dc/ca7874924c9cfd701ad53f89529968523790e70473e0b71e834668316148/pypdfium2-5.14.0-py3-none-win_amd64.whl", hash = "sha256:149fd5c6397b8df8bf7911a93506eff0be874f877afe7ac936cf5d37d21a6a06", size = 3947280, upload-time = "2026-10-04T15:19:16.302Z" },
|
|
359
|
-
{ url = "https://files.pythonhosted.org/packages/46/ab/35f2276deeeebb781925e2647dd88a39f8ea1a910104a0dbb28218473502/pypdfium2-5.14.0-py3-none-win_arm64.whl", hash = "sha256:eb8aeca157808f323e39ea298cc6d6c8e080c192ea2efb1ca81daa0f0ff4d095", size = 3745021, upload-time = "2026-10-04T15:19:18.276Z" },
|
|
360
|
-
]
|
|
361
|
-
|
|
362
|
-
[[package]]
|
|
363
|
-
name = "typing-extensions"
|
|
364
|
-
version = "4.16.0"
|
|
365
|
-
source = { registry = "https://pypi.org/simple" }
|
|
366
|
-
sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
|
|
367
|
-
wheels = [
|
|
368
|
-
{ url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
|
|
369
|
-
]
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
"""Word text with tracked changes and comments inline, as a reviewer sees them.
|
|
2
|
-
|
|
3
|
-
python view_docx.py <file>
|
|
4
|
-
|
|
5
|
-
[+new+] and [-old-] carry author and date; a space at the edge of a change stays
|
|
6
|
-
inside the marks. «text»[comment ...] marks what a comment is anchored to.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import sys
|
|
10
|
-
|
|
11
|
-
import docx
|
|
12
|
-
from docx.table import Table
|
|
13
|
-
|
|
14
|
-
W = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
|
|
15
|
-
ADDED = {f"{W}ins": "+", f"{W}moveTo": "+"}
|
|
16
|
-
REMOVED = {f"{W}del": "-", f"{W}moveFrom": "-"}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def signed(author, date) -> str:
|
|
20
|
-
return f"{author or 'unknown author'}, {str(date or 'no date')[:10]}"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def run_text(run) -> str:
|
|
24
|
-
parts = []
|
|
25
|
-
for node in run:
|
|
26
|
-
if node.tag in (f"{W}t", f"{W}delText"):
|
|
27
|
-
parts.append(node.text or "")
|
|
28
|
-
elif node.tag == f"{W}tab":
|
|
29
|
-
parts.append("\t")
|
|
30
|
-
elif node.tag in (f"{W}br", f"{W}cr"):
|
|
31
|
-
parts.append("\n")
|
|
32
|
-
return "".join(parts)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def walk(element, comments: dict, seen: set) -> str:
|
|
36
|
-
"""Read only: the order of runs and changes in a paragraph. Never edit through it."""
|
|
37
|
-
parts = []
|
|
38
|
-
for node in element:
|
|
39
|
-
if node.tag == f"{W}r":
|
|
40
|
-
parts.append(run_text(node))
|
|
41
|
-
elif node.tag in ADDED or node.tag in REMOVED:
|
|
42
|
-
mark = ADDED.get(node.tag) or REMOVED[node.tag]
|
|
43
|
-
who = signed(node.get(f"{W}author"), node.get(f"{W}date"))
|
|
44
|
-
parts.append(f"[{mark}{walk(node, comments, seen)}{mark}]({who})")
|
|
45
|
-
elif node.tag == f"{W}commentRangeStart":
|
|
46
|
-
parts.append("«")
|
|
47
|
-
elif node.tag == f"{W}commentRangeEnd":
|
|
48
|
-
number = int(node.get(f"{W}id"))
|
|
49
|
-
seen.add(number)
|
|
50
|
-
comment = comments.get(number)
|
|
51
|
-
who = signed(comment.author, comment.timestamp) if comment else "unknown author"
|
|
52
|
-
body = comment.text if comment else ""
|
|
53
|
-
parts.append(f"»[comment {number}, {who}: {body}]")
|
|
54
|
-
elif node.tag in (f"{W}hyperlink", f"{W}smartTag", f"{W}sdt", f"{W}sdtContent"):
|
|
55
|
-
parts.append(walk(node, comments, seen))
|
|
56
|
-
return "".join(parts)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def line(paragraph, comments: dict, seen: set) -> str:
|
|
60
|
-
text = walk(paragraph._p, comments, seen)
|
|
61
|
-
style = paragraph.style.name if paragraph.style is not None else ""
|
|
62
|
-
return f"# {text}" if text and style.startswith("Heading") else text
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def table_lines(table, comments: dict, seen: set) -> list[str]:
|
|
66
|
-
lines = []
|
|
67
|
-
for row in table.rows:
|
|
68
|
-
cells = (" ".join(walk(p, comments, seen) for p in cell._tc.iter(f"{W}p")) for cell in row.cells)
|
|
69
|
-
lines.append(" | ".join(cells))
|
|
70
|
-
return lines
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def body_lines(document, comments: dict, seen: set) -> list[str]:
|
|
74
|
-
lines = []
|
|
75
|
-
for block in document.iter_inner_content():
|
|
76
|
-
if isinstance(block, Table):
|
|
77
|
-
lines += table_lines(block, comments, seen)
|
|
78
|
-
else:
|
|
79
|
-
lines.append(line(block, comments, seen))
|
|
80
|
-
return [text for text in lines if text]
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def margin_lines(document, kind: str, comments: dict, seen: set) -> list[str]:
|
|
84
|
-
"""Each section's headers or footers that apply. A linked one resolves to a part already shown."""
|
|
85
|
-
even_pages = document.settings.odd_and_even_pages_header_footer
|
|
86
|
-
lines = []
|
|
87
|
-
shown = set()
|
|
88
|
-
for number, section in enumerate(document.sections, 1):
|
|
89
|
-
where = f", section {number}" if number > 1 else ""
|
|
90
|
-
variants = [("", getattr(section, kind))]
|
|
91
|
-
if section.different_first_page_header_footer:
|
|
92
|
-
variants.append(("first-page ", getattr(section, f"first_page_{kind}")))
|
|
93
|
-
if even_pages:
|
|
94
|
-
variants.append(("even-page ", getattr(section, f"even_page_{kind}")))
|
|
95
|
-
for variant, margin in variants:
|
|
96
|
-
if margin.part.partname not in shown:
|
|
97
|
-
shown.add(margin.part.partname)
|
|
98
|
-
for block in margin.iter_inner_content():
|
|
99
|
-
if isinstance(block, Table):
|
|
100
|
-
rows = [row for row in table_lines(block, comments, seen) if row.strip(" |")]
|
|
101
|
-
else:
|
|
102
|
-
rows = [block.text] if block.text.strip() else []
|
|
103
|
-
lines += [f"[{variant}{kind}{where}] {row}" for row in rows]
|
|
104
|
-
return lines
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def view(path, out=None, pages=None) -> dict:
|
|
108
|
-
document = docx.Document(str(path))
|
|
109
|
-
comments = {comment.comment_id: comment for comment in document.comments}
|
|
110
|
-
seen: set[int] = set()
|
|
111
|
-
lines = margin_lines(document, "header", comments, seen)
|
|
112
|
-
lines += body_lines(document, comments, seen)
|
|
113
|
-
lines += margin_lines(document, "footer", comments, seen)
|
|
114
|
-
revisions = list(document.revisions)
|
|
115
|
-
# What the walk above cannot place: changes in headers and notes, formatting, paragraph marks.
|
|
116
|
-
elsewhere = [
|
|
117
|
-
r for r in revisions
|
|
118
|
-
if r.story != "word/document.xml"
|
|
119
|
-
or r.is_paragraph_mark
|
|
120
|
-
or r.revision_type not in ("insertion", "deletion", "move_from", "move_to")
|
|
121
|
-
]
|
|
122
|
-
if elsewhere:
|
|
123
|
-
lines.append("--- other tracked changes")
|
|
124
|
-
lines += [f"{r.story} {r.revision_type} ({signed(r.author, r.date)}): {r.text}" for r in elsewhere]
|
|
125
|
-
unplaced = [c for number, c in comments.items() if number not in seen]
|
|
126
|
-
if unplaced:
|
|
127
|
-
lines.append("--- comments with no anchor")
|
|
128
|
-
lines += [f"comment {c.comment_id}, {signed(c.author, c.timestamp)}: {c.text}" for c in unplaced]
|
|
129
|
-
lines.insert(0, f"{len(revisions)} tracked change(s), {len(comments)} comment(s).")
|
|
130
|
-
return {
|
|
131
|
-
"text": "\n".join(lines),
|
|
132
|
-
"images": [],
|
|
133
|
-
"note": "Text only: Word files are not rendered here. List numbers and footnote bodies are not shown.",
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if __name__ == "__main__":
|
|
138
|
-
print(view(sys.argv[1])["text"])
|