From 79e829a503a38b1ca8abb1f60108ecde3b7cbf5a Mon Sep 17 00:00:00 2001 From: leynos Date: Fri, 10 Jul 2026 10:25:05 +0200 Subject: [PATCH 1/2] Enforce shared Oxford spelling Generate parent and rendered-project typos configuration from the shared estate dictionary plus narrow local overlays. Add pinned local and CI gates, contract and behavioural coverage, and correct the spelling findings exposed in generated guidance. --- .github/workflows/ci.yml | 3 + .gitignore | 4 + Makefile | 13 +- docs/adr-001-template-quality-gates.md | 5 +- docs/adr-003-shared-oxford-spelling-base.md | 37 + docs/developers-guide.md | 31 +- pytest.ini | 1 + scripts/generate_typos_config.py | 63 + scripts/typos_rollout.py | 395 +++ template/.github/workflows/ci.yml.jinja | 3 + template/.gitignore | 4 + ...ion-design-raising-handling-and-logging.md | 4 +- template/.rules/python-pyproject.md | 2 +- template/.rules/python-typing.md | 2 +- template/AGENTS.md.jinja | 15 +- template/Makefile.jinja | 16 +- ...antipatterns-and-refactoring-strategies.md | 2 +- template/docs/developers-guide.md | 32 +- template/docs/users-guide.md.jinja | 6 + template/scripts/generate_typos_config.py | 63 + template/scripts/typos_rollout.py | 395 +++ template/typos.local.toml | 19 + template/typos.toml | 2631 ++++++++++++++++ tests/__snapshots__/test_template.ambr | 3 +- tests/helpers/agents_contracts.py | 6 + tests/helpers/ci_contracts.py | 3 + tests/helpers/makefile_contracts.py | 11 + tests/test_helpers.py | 12 +- tests/test_parent_ci.py | 3 + tests/test_template.py | 11 +- tests/test_typos_rollout.py | 245 ++ typos.local.toml | 22 + typos.toml | 2633 +++++++++++++++++ 33 files changed, 6653 insertions(+), 42 deletions(-) create mode 100644 docs/adr-003-shared-oxford-spelling-base.md create mode 100644 scripts/generate_typos_config.py create mode 100644 scripts/typos_rollout.py create mode 100644 template/scripts/generate_typos_config.py create mode 100644 template/scripts/typos_rollout.py create mode 100644 template/typos.local.toml create mode 100644 template/typos.toml create mode 100644 tests/test_typos_rollout.py create mode 100644 typos.local.toml create mode 100644 typos.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25f2fd9..ee6f964 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,3 +41,6 @@ jobs: - name: Run template tests run: make test + + - name: Check spelling + run: make spelling diff --git a/.gitignore b/.gitignore index 6c56ff1..b309d4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ __pycache__/ .pytest_cache/ + +# Untracked cache of the estate-wide en-GB-oxendict dictionary. +.typos-oxendict-base.json +.typos-oxendict-base.toml diff --git a/Makefile b/Makefile index e0ce73d..0ddc5ed 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,20 @@ -.PHONY: help check-fmt lint test typecheck +.PHONY: help check-fmt lint spelling test typecheck MAKEFLAGS += --no-print-directory UV := $(shell command -v uvx 2>/dev/null) WITH_ACT ?= 0 ACT_TEST_ENV = $(if $(filter 1 true yes on,$(WITH_ACT)),RUN_ACT_VALIDATION=1,) +TYPOS_VERSION ?= 1.48.0 +TYPOS = uv tool run typos@$(TYPOS_VERSION) +MD_FILES_FIND = find . -type f \( -name '*.md' -o -name '*.md.jinja' \) -not -path './.git/*' -print0 ifeq ($(strip $(UV)),) $(error uvx is required to run template tests. Install uv from https://docs.astral.sh/uv/getting-started/installation/) endif test: ## Run template tests - $(ACT_TEST_ENV) $(UV) --with pytest-copier --with pyyaml --with syrupy --with make-parser pytest tests/ + $(ACT_TEST_ENV) $(UV) --with hypothesis --with pytest-copier --with pyyaml --with syrupy --with make-parser pytest tests/ check-fmt: ## Verify template test formatting $(UV) ruff format --check tests/ @@ -20,8 +23,12 @@ lint: ## Run template test lint checks $(UV) ruff check tests/ $(UV) --with interrogate interrogate --fail-under 100 tests/ +spelling: ## Enforce en-GB-oxendict spelling + uv run scripts/generate_typos_config.py + $(MD_FILES_FIND) | xargs -0 $(TYPOS) --config typos.toml --force-exclude + typecheck: ## Run template test type checks - $(UV) --with pytest --with pytest-copier --with pyyaml --with syrupy --with make-parser ty check tests/ + $(UV) --with hypothesis --with pytest --with pytest-copier --with pyyaml --with syrupy --with make-parser ty check tests/ help: ## Show available targets @grep -E '^[a-zA-Z_-]+:.*?##' $(MAKEFILE_LIST) | \ diff --git a/docs/adr-001-template-quality-gates.md b/docs/adr-001-template-quality-gates.md index 2905fd7..fd8db77 100644 --- a/docs/adr-001-template-quality-gates.md +++ b/docs/adr-001-template-quality-gates.md @@ -16,9 +16,12 @@ failures are predictable. Generated projects use `make all` as the public aggregate gate. The `lint` target delegates to language-specific targets: -- `lint-python` runs Ruff, Interrogate (`--fail-under 100`), and Pylint through the PyPy-backed runner. +- `lint-python` runs Ruff, Interrogate (`--fail-under 100`), and Pylint through + the PyPy-backed runner. - `lint-rust` is rendered only when `use_rust` is enabled and runs rustdoc, Clippy, and Whitaker. +- `spelling` generates shared en-GB-oxendict policy and runs the pinned + `typos` binary after the other aggregate prerequisites complete. Tool revision pins are exposed as Makefile variables where the generated Makefile owns installation or invocation. Generated Continuous Integration diff --git a/docs/adr-003-shared-oxford-spelling-base.md b/docs/adr-003-shared-oxford-spelling-base.md new file mode 100644 index 0000000..86b0451 --- /dev/null +++ b/docs/adr-003-shared-oxford-spelling-base.md @@ -0,0 +1,37 @@ +# ADR-003: Generate spelling policy from a shared base + +## Status + +Accepted. + +## Context + +Generated projects need the same en-GB-oxendict policy as the wider `leynos` +estate. The `typos` `en-gb` locale enforces British `-our` and `-yse` forms but +prefers plain-British `-ise` over Oxford `-ize`. Copying curated overrides into +each generated project would cause drift, while making every exception global +would hide repository-specific mistakes. + +## Decision + +Generated projects refresh the tracked shared dictionary published by +`leynos/agent-helper-scripts` into ignored `.typos-oxendict-base.toml`, using +`.typos-oxendict-base.json` for source identity and freshness validators. The +generator merges that base with tracked `typos.local.toml` and writes a +deterministic, tracked `typos.toml`. + +The refresh validates data before atomic replacement, keeps a valid cache when +its authority is not newer, and supports explicit offline reuse. The generated +Makefile pins `typos`, exposes `make spelling`, includes spelling in `make all`, +and runs it through Continuous Integration (CI). The template repository uses +the same mechanism for its own Markdown and rendered Markdown sources. + +## Consequences + +- Generic Oxford stems are curated once for the estate. +- Generated projects retain reviewable, reproducible configuration and work + offline after their cache is populated. +- Product names, upstream quotations, and deliberate fixtures remain narrow + local exceptions. +- A fresh checkout needs network access to collect the shared base before its + first spelling run. diff --git a/docs/developers-guide.md b/docs/developers-guide.md index 0f9869b..19c6318 100644 --- a/docs/developers-guide.md +++ b/docs/developers-guide.md @@ -15,10 +15,13 @@ template itself. - `make lint` — runs Ruff lint checks and `interrogate --fail-under 100` against the `tests/` directory in the parent template test suite. - `make typecheck` — runs `ty check` against the parent template test suite, - supplying the test dependencies through `uvx`. + supplying the test dependencies, including Hypothesis, through `uvx`. - `make test` — runs the template test suite via `uvx`, supplying - `pytest-copier`, `pyyaml`, `syrupy`, and `make-parser` without a manually - managed virtual environment. + Hypothesis, `pytest-copier`, `pyyaml`, `syrupy`, and `make-parser` without a + manually managed virtual environment. +- `make spelling` — refreshes the ignored estate-wide dictionary cache, merges + `typos.local.toml`, generates `typos.toml`, and checks Markdown plus rendered + Markdown template sources with the pinned `typos` version. - `make test WITH_ACT=1` — sets `RUN_ACT_VALIDATION=1` inside the pytest invocation, enabling the act-backed integration tests that run generated CI workflows locally. Requires `act` and Docker to be available. @@ -31,9 +34,9 @@ template itself. The parent repository uses two separate GitHub Actions workflows to keep Docker-dependent tests isolated from the standard template test gate: -- `.github/workflows/ci.yml` runs `make test` on every push to `main` and on - all pull requests. It installs `markdownlint-cli2` and `mbake` at pinned - versions. +- `.github/workflows/ci.yml` runs `make test` and `make spelling` on every push + to `main` and on all pull requests. It installs `markdownlint-cli2` and + `mbake` at pinned versions. - `.github/workflows/act-validation.yml` runs `make test WITH_ACT=1`. It additionally downloads the `act` binary at a pinned `ACT_VERSION`, verifies its SHA-256 checksum before extraction, and confirms Docker availability via @@ -44,7 +47,9 @@ Docker-dependent tests isolated from the standard template test gate: ## Makefile Template `template/Makefile.jinja` defines the generated developer workflow. The default -`all` target runs build, formatting, linting, typechecking, and tests. +`all` target runs build, formatting, linting, typechecking, tests, and spelling. +The spelling recipe runs last so generated configuration cannot race tests when +callers enable parallel Make execution. The generated `audit` target is an explicit security gate run by CI. It runs `pip-audit` for every rendered project and, when `use_rust` is enabled, also runs `cargo audit` in the Rust extension crate. @@ -68,7 +73,7 @@ override pins without editing target recipes. `template/.github/workflows/ci.yml.jinja` mirrors the generated local gates. It sets up Python, optionally sets up Rust, runs `make check-fmt`, `make lint`, -`make typecheck`, and `make audit`, then delegates coverage to +`make typecheck`, `make spelling`, and `make audit`, then delegates coverage to `leynos/shared-actions/.github/actions/generate-coverage`. The shared coverage action runs Python coverage through xdist-backed SlipCover @@ -83,6 +88,16 @@ Docker availability, and runs `make test WITH_ACT=1`. Rust-enabled workflows pass `rust_extension/Cargo.toml` to the coverage action because the generated Python project root does not contain a Rust manifest. +## Shared Spelling Configuration + +[ADR-003](adr-003-shared-oxford-spelling-base.md) records the shared-base +decision. Both the parent and generated project keep +`.typos-oxendict-base.toml` and `.typos-oxendict-base.json` untracked. Generic +Oxford stems belong in `leynos/agent-helper-scripts`; repository-only accepted +words, patterns, and file exclusions belong in `typos.local.toml`. Regenerate +tracked configuration with `uv run scripts/generate_typos_config.py` rather +than editing `typos.toml`. + ## Rust Integration When `use_rust` is enabled, the template renders a PyO3 extension under diff --git a/pytest.ini b/pytest.ini index 064079c..360046c 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,4 @@ [pytest] markers = act: local GitHub Actions workflow validation through act + slow: exercises an external tool or process boundary diff --git a/scripts/generate_typos_config.py b/scripts/generate_typos_config.py new file mode 100644 index 0000000..9c91be4 --- /dev/null +++ b/scripts/generate_typos_config.py @@ -0,0 +1,63 @@ +#!/usr/bin/env -S uv run python +# /// script +# requires-python = ">=3.13" +# dependencies = [] +# /// +"""Generate ``typos.toml`` from the shared en-GB-oxendict dictionary. + +The shared dictionary is refreshed into an untracked repository-local cache +only when the authoritative copy is newer. A valid cache remains usable when +the network is unavailable, and ``typos.local.toml`` supplies the narrow +repository-specific policy that must not weaken the estate-wide base. +""" + +from pathlib import Path + +import typos_rollout as rollout + +DEFAULT_BASE_URL = ( + "https://raw.githubusercontent.com/leynos/agent-helper-scripts/" + "refs/heads/main/data/typos-oxendict-base.toml" +) +REPOSITORY_ROOT = Path(__file__).resolve().parent.parent + + +def dictionary_from_cache(repository: Path = REPOSITORY_ROOT) -> rollout.Dictionary: + """Load the cached shared base merged with local repository policy.""" + dictionary = rollout.load_dictionary(repository / ".typos-oxendict-base.toml") + local_overlay = repository / "typos.local.toml" + if local_overlay.exists(): + dictionary = rollout.merge_dictionaries( + dictionary, + rollout.load_dictionary(local_overlay), + ) + return dictionary + + +def render_config(repository: Path = REPOSITORY_ROOT) -> str: + """Render deterministic configuration from the populated local cache.""" + return rollout.render_typos_config(dictionary_from_cache(repository)) + + +def main( + output: Path | None = None, + *, + repository: Path = REPOSITORY_ROOT, + source: str | Path = DEFAULT_BASE_URL, + offline: bool = False, +) -> rollout.RefreshResult: + """Refresh the shared base cache and write the merged configuration.""" + result = rollout.refresh_base( + source, + repository / ".typos-oxendict-base.toml", + metadata=repository / ".typos-oxendict-base.json", + offline=offline, + ) + destination = output if output is not None else repository / "typos.toml" + rollout.write_config(destination, dictionary_from_cache(repository)) + return result + + +if __name__ == "__main__": + refresh = main() + print(f"{refresh.status}: {REPOSITORY_ROOT / 'typos.toml'}") diff --git a/scripts/typos_rollout.py b/scripts/typos_rollout.py new file mode 100644 index 0000000..298b734 --- /dev/null +++ b/scripts/typos_rollout.py @@ -0,0 +1,395 @@ +"""Refresh and render shared en-GB-oxendict ``typos`` configuration.""" + +from __future__ import annotations + +import dataclasses +import email.utils +import json +import pathlib +import tempfile +import tomllib +import typing as typ +import urllib.error +import urllib.parse +import urllib.request + +if typ.TYPE_CHECKING: + import collections.abc as cabc + +SCHEMA_VERSION = 1 +HTTP_NOT_MODIFIED = 304 +SUFFIX_PAIRS = ( + ("ise", "ize"), + ("ises", "izes"), + ("ised", "ized"), + ("ising", "izing"), + ("iser", "izer"), + ("isers", "izers"), + ("isable", "izable"), + ("isation", "ization"), + ("isations", "izations"), +) + + +@dataclasses.dataclass(frozen=True) +class Dictionary: + """Curated words and exclusions used to generate a ``typos`` config.""" + + stems: tuple[str, ...] = () + accepted: tuple[str, ...] = () + corrections: tuple[tuple[str, str], ...] = () + ignore_patterns: tuple[str, ...] = () + excluded_files: tuple[str, ...] = () + + +@dataclasses.dataclass(frozen=True) +class RefreshResult: + """Describe whether the untracked shared dictionary cache changed.""" + + status: str + cache: pathlib.Path + + +@dataclasses.dataclass(frozen=True) +class _CacheTargets: + """Group the untracked dictionary cache and metadata sidecar paths.""" + + cache: pathlib.Path + metadata: pathlib.Path + + +def _string_list(table: cabc.Mapping[str, object], key: str) -> tuple[str, ...]: + """Read and validate a list of strings from a TOML table.""" + value = table.get(key, []) + if not isinstance(value, list) or not all(isinstance(item, str) for item in value): + message = f"{key!r} must be a list of strings" + raise TypeError(message) + return tuple(sorted(set(value))) + + +def _table( + document: cabc.Mapping[str, object], + key: str, +) -> cabc.Mapping[str, object]: + """Read and validate a TOML table.""" + value = document.get(key, {}) + if not isinstance(value, dict): + message = f"{key!r} must be a table" + raise TypeError(message) + return value + + +def _dictionary_from_text(text: str) -> Dictionary: + """Parse and validate shared dictionary text.""" + document = tomllib.loads(text) + schema = document.get("schema") + if schema != SCHEMA_VERSION: + message = f"unsupported dictionary schema {schema!r}" + raise ValueError(message) + oxford = _table(document, "oxford") + words = _table(document, "words") + patterns = _table(document, "patterns") + files = _table(document, "files") + corrections_table = _table(words, "corrections") + if not all( + isinstance(key, str) and isinstance(value, str) + for key, value in corrections_table.items() + ): + message = "word corrections must map strings to strings" + raise TypeError(message) + return Dictionary( + stems=_string_list(oxford, "stems"), + accepted=_string_list(words, "accepted"), + corrections=tuple(sorted(corrections_table.items())), + ignore_patterns=_string_list(patterns, "ignore"), + excluded_files=_string_list(files, "exclude"), + ) + + +def load_dictionary(path: pathlib.Path) -> Dictionary: + """Load a validated shared dictionary from *path*.""" + return _dictionary_from_text(path.read_text(encoding="utf-8")) + + +def merge_dictionaries(base: Dictionary, local: Dictionary) -> Dictionary: + """Merge a shared dictionary with a non-conflicting local overlay.""" + corrections = dict(base.corrections) + for word, correction in local.corrections: + existing = corrections.get(word) + if existing is not None and existing != correction: + message = ( + f"conflicting correction for {word!r}: {existing!r} != {correction!r}" + ) + raise ValueError(message) + corrections[word] = correction + return Dictionary( + stems=tuple(sorted(set(base.stems) | set(local.stems))), + accepted=tuple(sorted(set(base.accepted) | set(local.accepted))), + corrections=tuple(sorted(corrections.items())), + ignore_patterns=tuple( + sorted(set(base.ignore_patterns) | set(local.ignore_patterns)) + ), + excluded_files=tuple( + sorted(set(base.excluded_files) | set(local.excluded_files)) + ), + ) + + +def generate_word_mappings(dictionary: Dictionary) -> dict[str, str]: + """Expand Oxford stems and explicit words into deterministic mappings.""" + mappings = {word: word for word in dictionary.accepted} + + def add(word: str, correction: str) -> None: + existing = mappings.get(word) + if existing is not None and existing != correction: + message = ( + f"conflicting generated correction for {word!r}: " + f"{existing!r} != {correction!r}" + ) + raise ValueError(message) + mappings[word] = correction + + for word, correction in dictionary.corrections: + add(word, correction) + for stem in dictionary.stems: + for plain_british, oxford in SUFFIX_PAIRS: + add(f"{stem}{plain_british}", f"{stem}{oxford}") + add(f"{stem}{oxford}", f"{stem}{oxford}") + return dict(sorted(mappings.items())) + + +def _toml_string(value: str) -> str: + """Render a string using TOML-compatible JSON quoting.""" + return json.dumps(value, ensure_ascii=False) + + +def _render_array(name: str, values: tuple[str, ...]) -> list[str]: + """Render a deterministic TOML string array.""" + lines = [f"{name} = ["] + lines.extend(f" {_toml_string(value)}," for value in values) + lines.append("]") + return lines + + +def render_typos_config(dictionary: Dictionary) -> str: + """Render a deterministic, parse-checked ``typos.toml`` document.""" + lines = [ + "# Generated from the shared en-GB-oxendict dictionary.", + "# Regenerate with scripts/generate_typos_config.py; do not edit by hand.", + "", + "[files]", + *_render_array("extend-exclude", dictionary.excluded_files), + "", + "[default]", + 'locale = "en-gb"', + *_render_array("extend-ignore-re", dictionary.ignore_patterns), + "", + "[default.extend-words]", + ] + lines.extend( + f"{_toml_string(word)} = {_toml_string(correction)}" + for word, correction in generate_word_mappings(dictionary).items() + ) + rendered = "\n".join(lines) + "\n" + tomllib.loads(rendered) + return rendered + + +def _atomic_write(path: pathlib.Path, content: bytes) -> None: + """Write *content* beside *path* and atomically replace the destination.""" + path.parent.mkdir(parents=True, exist_ok=True) + with tempfile.NamedTemporaryFile( + delete=False, dir=path.parent, prefix=f".{path.name}." + ) as stream: + stream.write(content) + temporary = pathlib.Path(stream.name) + try: + temporary.replace(path) + finally: + temporary.unlink(missing_ok=True) + + +def write_config(path: pathlib.Path, dictionary: Dictionary) -> None: + """Atomically write validated generated configuration to *path*.""" + _atomic_write(path, render_typos_config(dictionary).encode()) + + +def _read_metadata(path: pathlib.Path) -> dict[str, object]: + """Read best-effort HTTP freshness metadata.""" + try: + value = json.loads(path.read_text(encoding="utf-8")) + except FileNotFoundError, json.JSONDecodeError: + return {} + return value if isinstance(value, dict) else {} + + +def _write_metadata( + path: pathlib.Path, + metadata: cabc.Mapping[str, object], +) -> None: + """Atomically write HTTP freshness metadata.""" + _atomic_write(path, (json.dumps(metadata, sort_keys=True) + "\n").encode()) + + +def _valid_cache(cache: pathlib.Path) -> bool: + """Return whether *cache* contains a valid shared dictionary.""" + try: + load_dictionary(cache) + except FileNotFoundError, OSError, TypeError, ValueError, tomllib.TOMLDecodeError: + return False + return True + + +def _remote_is_not_newer( + saved: cabc.Mapping[str, object], + headers: cabc.Mapping[str, str], +) -> bool: + """Return whether HTTP validators prove the response is not newer.""" + etag = headers.get("ETag") + if etag is not None and etag == saved.get("etag"): + return True + modified = headers.get("Last-Modified") + saved_modified = saved.get("last_modified") + if not isinstance(modified, str) or not isinstance(saved_modified, str): + return False + try: + return email.utils.parsedate_to_datetime( + modified + ) <= email.utils.parsedate_to_datetime(saved_modified) + except TypeError, ValueError: + return modified == saved_modified + + +def _local_cache_is_current( + cache: pathlib.Path, + saved: cabc.Mapping[str, object], + source_name: str, + source_mtime_ns: int, +) -> bool: + """Return whether metadata proves a valid local-source cache is current.""" + saved_mtime = saved.get("mtime_ns") + has_matching_source = saved.get("source") == source_name + has_new_enough_mtime = ( + isinstance(saved_mtime, int) and source_mtime_ns <= saved_mtime + ) + return _valid_cache(cache) and has_matching_source and has_new_enough_mtime + + +def _refresh_local( + source: pathlib.Path, + cache: pathlib.Path, + metadata: pathlib.Path, +) -> RefreshResult: + """Refresh from a local authoritative copy when it is newer.""" + source_stat = source.stat() + source_name = str(source.resolve()) + saved = _read_metadata(metadata) + if _local_cache_is_current( + cache, + saved, + source_name, + source_stat.st_mtime_ns, + ): + return RefreshResult("current", cache) + content = source.read_bytes() + _dictionary_from_text(content.decode()) + _atomic_write(cache, content) + _write_metadata( + metadata, + {"source": source_name, "mtime_ns": source_stat.st_mtime_ns}, + ) + return RefreshResult("refreshed", cache) + + +def _conditional_headers(saved: cabc.Mapping[str, object]) -> dict[str, str]: + """Build conditional HTTP headers from persisted validators.""" + headers = {} + if isinstance(saved.get("etag"), str): + headers["If-None-Match"] = saved["etag"] + if isinstance(saved.get("last_modified"), str): + headers["If-Modified-Since"] = saved["last_modified"] + return headers + + +def _https_request( + source: str, + headers: cabc.Mapping[str, str], +) -> urllib.request.Request: + """Build a request after constraining the shared source to HTTPS.""" + if urllib.parse.urlsplit(source).scheme != "https": + message = f"shared dictionary URL must use HTTPS: {source}" + raise ValueError(message) + return urllib.request.Request(source, headers=dict(headers)) # noqa: S310 - HTTPS is required above. + + +def _write_remote_cache( + source: str, + targets: _CacheTargets, + content: bytes, + headers: cabc.Mapping[str, str], +) -> RefreshResult: + """Validate and atomically persist an HTTP dictionary response.""" + _dictionary_from_text(content.decode()) + _atomic_write(targets.cache, content) + _write_metadata( + targets.metadata, + { + "source": source, + "etag": headers.get("ETag"), + "last_modified": headers.get("Last-Modified"), + }, + ) + return RefreshResult("refreshed", targets.cache) + + +def _refresh_http( + source: str, + cache: pathlib.Path, + metadata: pathlib.Path, +) -> RefreshResult: + """Refresh a cache from a validated HTTPS source with stale fallback.""" + saved = _read_metadata(metadata) + request = _https_request(source, _conditional_headers(saved)) + try: + with urllib.request.urlopen( # noqa: S310 - _https_request rejects non-HTTPS URLs. + request, + timeout=30.0, + ) as response: + if response.status == HTTP_NOT_MODIFIED and _valid_cache(cache): + return RefreshResult("current", cache) + if _valid_cache(cache) and _remote_is_not_newer(saved, response.headers): + return RefreshResult("current", cache) + return _write_remote_cache( + source, + _CacheTargets(cache, metadata), + response.read(), + response.headers, + ) + except urllib.error.HTTPError as error: + if error.code == HTTP_NOT_MODIFIED and _valid_cache(cache): + return RefreshResult("current", cache) + if _valid_cache(cache): + return RefreshResult("stale-cache", cache) + raise + except OSError, urllib.error.URLError: + if _valid_cache(cache): + return RefreshResult("stale-cache", cache) + raise + + +def refresh_base( + source: str | pathlib.Path, + cache: pathlib.Path, + *, + metadata: pathlib.Path, + offline: bool = False, +) -> RefreshResult: + """Refresh an untracked base cache when the authoritative copy is newer.""" + if offline: + if not _valid_cache(cache): + message = f"no cached shared dictionary at {cache}" + raise FileNotFoundError(message) + return RefreshResult("offline-cache", cache) + if isinstance(source, pathlib.Path) or "://" not in str(source): + return _refresh_local(pathlib.Path(source), cache, metadata) + return _refresh_http(str(source), cache, metadata) diff --git a/template/.github/workflows/ci.yml.jinja b/template/.github/workflows/ci.yml.jinja index 1a3b7fe..b071af7 100644 --- a/template/.github/workflows/ci.yml.jinja +++ b/template/.github/workflows/ci.yml.jinja @@ -76,6 +76,9 @@ jobs: - name: Run typechecker run: make typecheck + - name: Check spelling + run: make spelling + - name: Audit dependencies run: make audit diff --git a/template/.gitignore b/template/.gitignore index 4e9999a..70b5992 100644 --- a/template/.gitignore +++ b/template/.gitignore @@ -204,3 +204,7 @@ target/ **/mutants.out*/ .crush/ + +# Untracked cache of the estate-wide en-GB-oxendict dictionary. +.typos-oxendict-base.json +.typos-oxendict-base.toml diff --git a/template/.rules/python-exception-design-raising-handling-and-logging.md b/template/.rules/python-exception-design-raising-handling-and-logging.md index e33d50a..e39da2e 100644 --- a/template/.rules/python-exception-design-raising-handling-and-logging.md +++ b/template/.rules/python-exception-design-raising-handling-and-logging.md @@ -90,7 +90,7 @@ def reciprocal(n: float) -> float: return result ``` -`else` emphasises the happy path and avoids odd control‑flow within `try` +`else` emphasizes the happy path and avoids odd control‑flow within `try` blocks. ## 4) Message construction for raises (EM101/EM102) and logging practice (LOG004/LOG007/LOG009/LOG014/LOG015, TRY401) @@ -110,7 +110,7 @@ raise RuntimeError(msg) EM101/EM102 prefer a single message object; this reduces duplication and clarifies intent. -### Logging: parameterised messages, module loggers, correct APIs +### Logging: parameterized messages, module loggers, correct APIs ```python import logging diff --git a/template/.rules/python-pyproject.md b/template/.rules/python-pyproject.md index 89f8f76..50b20fc 100644 --- a/template/.rules/python-pyproject.md +++ b/template/.rules/python-pyproject.md @@ -228,7 +228,7 @@ package = true Reddit[^5]) - `description`, `readme`, `requires-python`: provide clarity about the project and help tools like PyPI. (Python Packaging[^4], Reddit[^5]) - - `license`, `authors`, `keywords`, `classifiers`: standardised metadata, + - `license`, `authors`, `keywords`, `classifiers`: standardized metadata, which improves discoverability. (Python Packaging[^4], Reddit[^5]) - `dependencies`: runtime requirements, expressed in PEP 508 syntax. (Astral Docs[^1], RidgeRun.ai[^2]) diff --git a/template/.rules/python-typing.md b/template/.rules/python-typing.md index 7962287..8110e7a 100644 --- a/template/.rules/python-typing.md +++ b/template/.rules/python-typing.md @@ -8,7 +8,7 @@ Use `Enum` for fixed sets of related constants. Use `enum.auto()` to avoid repeating values manually. Use `IntEnum` or `StrEnum` when interoperability -with integers or strings is required (e.g. for database or JSON serialisation). +with integers or strings is required (e.g. for database or JSON serialization). ```python import enum diff --git a/template/AGENTS.md.jinja b/template/AGENTS.md.jinja index 220f1e9..520fe98 100644 --- a/template/AGENTS.md.jinja +++ b/template/AGENTS.md.jinja @@ -64,7 +64,7 @@ commit, ensure all of the following are met: - New functionality or behaviour changes are fully validated by relevant unit and behavioural tests. - - Bug fixes include a failing test before the fix and a passing test afterward. + - Bug fixes include a failing test before the fix and a passing test afterwards. - Code passes lint checks. - Formatting is correct and validated. - **For Python files:** @@ -100,10 +100,11 @@ {% endif %} - **Markdown files (`.md` only):** - **Linting:** Passes markdown lint checks (`make markdownlint`). + - **Spelling:** Passes the en-GB-oxendict gate (`make spelling`). - **Mermaid diagrams:** Passes validation using nixie (`make nixie`). - **Committing:** - Only changes that meet all quality gates should be committed. - - Write clear, descriptive commit messages that summarise the change, following: + - Write clear, descriptive commit messages that summarize the change, following: - **Imperative mood** in the subject line (for example, "Fix bug", "Add feature"). - **Subject line length:** around 50 characters or fewer. - **Body:** Separate subject from body with a blank line. Explain *what* and @@ -288,7 +289,7 @@ project: - Use `pytest` fixtures for shared setup in Python work. Use `rstest` fixtures for shared setup in Rust work. - Replace duplicated tests with `#[rstest(...)]` parameterized cases in Rust and - equivalent fixture-driven parameterisation in Python. + equivalent fixture-driven parameterization in Python. - Prefer `mockall` for ad hoc mocks and stubs. - For testing reliant on environment variables, use dependency injection and the `mockable` crate where feasible. If mockable cannot be used, environment @@ -352,7 +353,13 @@ project: ## Markdown guidance -- Validate Markdown files using `make markdownlint`. +- Validate Markdown files using `make markdownlint`. This also runs the pinned + en-GB-oxendict spelling gate. +- The spelling configuration `typos.toml` is generated. Generic Oxford stems + belong in the shared base in `leynos/agent-helper-scripts`; project-specific + accepted words, patterns, and exclusions belong in `typos.local.toml`. + Regenerate with `uv run scripts/generate_typos_config.py` rather than editing + `typos.toml` by hand. - Run `make fmt` after documentation changes to format Markdown and fix table markup. - Validate Mermaid diagrams in Markdown by running `make nixie`. diff --git a/template/Makefile.jinja b/template/Makefile.jinja index 8f1639f..03b565f 100644 --- a/template/Makefile.jinja +++ b/template/Makefile.jinja @@ -9,6 +9,9 @@ USER_BIN_PATH := $(HOME)/.cargo/bin:$(HOME)/.local/bin:$(HOME)/.bun/bin TOOLS = $(MDFORMAT_ALL) $(MDLINT) VENV_TOOLS = pytest UV_ENV = PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 UV_CACHE_DIR=.uv-cache UV_TOOL_DIR=.uv-tools +TYPOS_VERSION ?= 1.48.0 +TYPOS = env $(UV_ENV) $(UV) tool run typos@$(TYPOS_VERSION) +MD_FILES_FIND = find . -type f -name '*.md' -not -path './.git/*' -print0 WITH_ACT ?= 0 ACT_TEST_ENV = $(if $(filter 1 true yes on,$(WITH_ACT)),RUN_ACT_VALIDATION=1,) PYTEST_XDIST_WORKERS ?= auto @@ -37,11 +40,12 @@ WHITAKER ?= $(or $(shell command -v whitaker 2>/dev/null),$(wildcard $(USER_WHIT {% endif %} .PHONY: help all audit clean build build-release lint lint-python fmt check-fmt \ - markdownlint nixie test typecheck $(TOOLS) $(VENV_TOOLS){% if use_rust %} lint-rust rust-audit whitaker{% endif %} + markdownlint nixie spelling test typecheck $(TOOLS) $(VENV_TOOLS){% if use_rust %} lint-rust rust-audit whitaker{% endif %} .DEFAULT_GOAL := all all: build check-fmt lint typecheck test + +$(MAKE) spelling define ensure_uv @command -v $(UV) >/dev/null 2>&1 || { \ @@ -64,7 +68,8 @@ build-release: ## Build artefacts (sdist & wheel) clean: ## Remove build artifacts rm -rf build dist *.egg-info \ .mypy_cache .pytest_cache .coverage coverage.* \ - lcov.info htmlcov .venv .uv-cache .uv-tools{% if use_rust %} $(RUST_CRATE_DIR)/target{% endif %} + lcov.info htmlcov .venv .uv-cache .uv-tools \ + .typos-oxendict-base.json .typos-oxendict-base.toml{% if use_rust %} $(RUST_CRATE_DIR)/target{% endif %} find . -type d -name '__pycache__' -print0 | xargs -0 -r rm -rf define ensure_tool @@ -159,8 +164,13 @@ rust-audit: ## Audit Rust extension dependencies for known vulnerabilities cd $(RUST_CRATE_DIR) && $(CARGO) audit {% endif %} -markdownlint: $(MDLINT) ## Lint Markdown files +markdownlint: $(MDLINT) ## Lint Markdown files and spelling env -u NO_COLOR $(MDLINT) '**/*.md' + +$(MAKE) spelling + +spelling: ## Enforce en-GB-oxendict spelling + $(UV) run scripts/generate_typos_config.py + $(MD_FILES_FIND) | xargs -0 $(TYPOS) --config typos.toml --force-exclude nixie: ## Validate Mermaid diagrams $(call ensure_tool,$(NIXIE)) diff --git a/template/docs/complexity-antipatterns-and-refactoring-strategies.md b/template/docs/complexity-antipatterns-and-refactoring-strategies.md index 7c0d207..d9a7c3d 100644 --- a/template/docs/complexity-antipatterns-and-refactoring-strategies.md +++ b/template/docs/complexity-antipatterns-and-refactoring-strategies.md @@ -111,7 +111,7 @@ Thresholds and Implications: Code with high Cognitive Complexity is harder to read, understand, test, and modify.[^8] SonarQube, for example, raises issues when a function's Cognitive -Complexity exceeds a certain threshold, signaling that the code should likely +Complexity exceeds a certain threshold, signalling that the code should likely be refactored into smaller, more manageable pieces.[^8] The primary impact of high Cognitive Complexity is a slowdown in development and an increase in maintenance costs.[^8] diff --git a/template/docs/developers-guide.md b/template/docs/developers-guide.md index 98ff017..f92893d 100644 --- a/template/docs/developers-guide.md +++ b/template/docs/developers-guide.md @@ -4,10 +4,10 @@ This guide explains the contributor workflow for the generated project. ## Local workflow -The public entrypoint for formatting, linting, typechecking, and tests is -`make all`. Narrower Make targets may be invoked when investigating a specific -failure, and changes should be reconciled with the aggregate gate before being -considered complete. +The public entrypoint for formatting, linting, typechecking, tests, and spelling +is `make all`. Narrower Make targets may be invoked when investigating a +specific failure, and changes should be reconciled with the aggregate gate +before being considered complete. `make lint` runs Ruff, `interrogate --fail-under 100 $(PYTHON_TARGETS)` for 100% docstring coverage across `$(PYTHON_TARGETS)`, and Pylint. @@ -36,17 +36,17 @@ actions under `.github/`. - `.github/workflows/ci.yml` runs on pushes to `main` and on pull requests. It sets up Python 3.13, installs `uv`, validates the generated `Makefile` with `mbake`, runs `make build`, `make check-fmt`, - `make lint` (Ruff + `interrogate --fail-under 100 $(PYTHON_TARGETS)` + Pylint), `make - typecheck`, and `make audit`, then delegates coverage generation to the shared - coverage action. When the Rust extension is enabled, it also sets up Rust, - installs Rust lint and test tools, and passes `rust_extension/Cargo.toml` to - coverage. + `make lint` (Ruff + `interrogate --fail-under 100 $(PYTHON_TARGETS)` + Pylint), + `make typecheck`, `make spelling`, and `make audit`, then delegates coverage + generation to the shared coverage action. When the Rust extension is enabled, + it also sets up Rust, installs Rust lint and test tools, and passes + `rust_extension/Cargo.toml` to coverage. - `.github/workflows/act-validation.yml` runs rendered workflow validation in a separate workflow. It installs `act`, checks Docker availability, and runs `make test WITH_ACT=1` outside the coverage path. - `.github/workflows/release.yml` publishes wheels when a `v*.*.*` tag is pushed. It builds a pure Python wheel, creates a GitHub release with generated - release notes, downloads wheel artifacts, and uploads them to the tag release. + release notes, downloads wheel artefacts, and uploads them to the tag release. - `.github/workflows/build-wheels.yml` is a reusable workflow for extension builds. It accepts a Python version and builds wheels across Linux, Windows, and macOS architectures via `.github/actions/build-wheels`. @@ -54,9 +54,9 @@ actions under `.github/`. the CodeScene coverage CLI installer, computes its SHA-256 digest, and writes the result to the `CODESCENE_CLI_SHA256` repository variable. - `.github/actions/build-wheels` wraps `cibuildwheel` with `uvx` and uploads - architecture-specific wheel artifacts. + architecture-specific wheel artefacts. - `.github/actions/pure-python-wheel` builds a pure Python wheel with - `uv build --wheel` and uploads the resulting artifact. + `uv build --wheel` and uploads the resulting artefact. - `.github/dependabot.yml` enables dependency update pull requests for GitHub Actions and Python packages. Rust-enabled projects also receive Cargo updates. @@ -64,3 +64,11 @@ The `CS_ACCESS_TOKEN` secret must be configured when CodeScene coverage upload is required. The `CODESCENE_CLI_SHA256` variable should be populated using the refresh workflow, so CI can verify the downloaded CodeScene installer before upload. + +## Shared spelling configuration + +Run `make spelling` to enforce en-GB-oxendict spelling. The generator fetches +the estate-wide base from `leynos/agent-helper-scripts` only when its authority +is newer than the ignored local cache. A populated cache supports offline +generation. Add only project-specific terms and exclusions to +`typos.local.toml`; never edit generated `typos.toml` by hand. diff --git a/template/docs/users-guide.md.jinja b/template/docs/users-guide.md.jinja index ab295e9..c0972b1 100644 --- a/template/docs/users-guide.md.jinja +++ b/template/docs/users-guide.md.jinja @@ -12,6 +12,8 @@ these targets in order: - `lint`: run `lint-python` and, when Rust is enabled, `lint-rust`. - `typecheck`: run `ty check`. - `test`: run pytest and, when Rust is enabled, Rust tests. +- `spelling`: generate shared en-GB-oxendict policy and check Markdown with the + pinned `typos` version. - `audit`: run `pip-audit` and, when Rust is enabled, `cargo audit`. The `lint-python` target runs Ruff, then Interrogate with @@ -20,6 +22,10 @@ coverage for the Python targets, then Pylint via a PyPy-backed runner. The Pylin runner is installed through `uv tool run` from the pinned `pylint-pypy-shim` repository. +The spelling target keeps an ignored shared-base cache and a tracked generated +`typos.toml`. Run `make spelling` directly when updating documentation; a +populated cache remains usable when the shared source is temporarily offline. + Pytest discovery is limited to the top-level `tests/` tree. Keep generated project unit tests there rather than in package module directories or `unittests/` subdirectories, because CI coverage runs through xdist-backed diff --git a/template/scripts/generate_typos_config.py b/template/scripts/generate_typos_config.py new file mode 100644 index 0000000..9c91be4 --- /dev/null +++ b/template/scripts/generate_typos_config.py @@ -0,0 +1,63 @@ +#!/usr/bin/env -S uv run python +# /// script +# requires-python = ">=3.13" +# dependencies = [] +# /// +"""Generate ``typos.toml`` from the shared en-GB-oxendict dictionary. + +The shared dictionary is refreshed into an untracked repository-local cache +only when the authoritative copy is newer. A valid cache remains usable when +the network is unavailable, and ``typos.local.toml`` supplies the narrow +repository-specific policy that must not weaken the estate-wide base. +""" + +from pathlib import Path + +import typos_rollout as rollout + +DEFAULT_BASE_URL = ( + "https://raw.githubusercontent.com/leynos/agent-helper-scripts/" + "refs/heads/main/data/typos-oxendict-base.toml" +) +REPOSITORY_ROOT = Path(__file__).resolve().parent.parent + + +def dictionary_from_cache(repository: Path = REPOSITORY_ROOT) -> rollout.Dictionary: + """Load the cached shared base merged with local repository policy.""" + dictionary = rollout.load_dictionary(repository / ".typos-oxendict-base.toml") + local_overlay = repository / "typos.local.toml" + if local_overlay.exists(): + dictionary = rollout.merge_dictionaries( + dictionary, + rollout.load_dictionary(local_overlay), + ) + return dictionary + + +def render_config(repository: Path = REPOSITORY_ROOT) -> str: + """Render deterministic configuration from the populated local cache.""" + return rollout.render_typos_config(dictionary_from_cache(repository)) + + +def main( + output: Path | None = None, + *, + repository: Path = REPOSITORY_ROOT, + source: str | Path = DEFAULT_BASE_URL, + offline: bool = False, +) -> rollout.RefreshResult: + """Refresh the shared base cache and write the merged configuration.""" + result = rollout.refresh_base( + source, + repository / ".typos-oxendict-base.toml", + metadata=repository / ".typos-oxendict-base.json", + offline=offline, + ) + destination = output if output is not None else repository / "typos.toml" + rollout.write_config(destination, dictionary_from_cache(repository)) + return result + + +if __name__ == "__main__": + refresh = main() + print(f"{refresh.status}: {REPOSITORY_ROOT / 'typos.toml'}") diff --git a/template/scripts/typos_rollout.py b/template/scripts/typos_rollout.py new file mode 100644 index 0000000..298b734 --- /dev/null +++ b/template/scripts/typos_rollout.py @@ -0,0 +1,395 @@ +"""Refresh and render shared en-GB-oxendict ``typos`` configuration.""" + +from __future__ import annotations + +import dataclasses +import email.utils +import json +import pathlib +import tempfile +import tomllib +import typing as typ +import urllib.error +import urllib.parse +import urllib.request + +if typ.TYPE_CHECKING: + import collections.abc as cabc + +SCHEMA_VERSION = 1 +HTTP_NOT_MODIFIED = 304 +SUFFIX_PAIRS = ( + ("ise", "ize"), + ("ises", "izes"), + ("ised", "ized"), + ("ising", "izing"), + ("iser", "izer"), + ("isers", "izers"), + ("isable", "izable"), + ("isation", "ization"), + ("isations", "izations"), +) + + +@dataclasses.dataclass(frozen=True) +class Dictionary: + """Curated words and exclusions used to generate a ``typos`` config.""" + + stems: tuple[str, ...] = () + accepted: tuple[str, ...] = () + corrections: tuple[tuple[str, str], ...] = () + ignore_patterns: tuple[str, ...] = () + excluded_files: tuple[str, ...] = () + + +@dataclasses.dataclass(frozen=True) +class RefreshResult: + """Describe whether the untracked shared dictionary cache changed.""" + + status: str + cache: pathlib.Path + + +@dataclasses.dataclass(frozen=True) +class _CacheTargets: + """Group the untracked dictionary cache and metadata sidecar paths.""" + + cache: pathlib.Path + metadata: pathlib.Path + + +def _string_list(table: cabc.Mapping[str, object], key: str) -> tuple[str, ...]: + """Read and validate a list of strings from a TOML table.""" + value = table.get(key, []) + if not isinstance(value, list) or not all(isinstance(item, str) for item in value): + message = f"{key!r} must be a list of strings" + raise TypeError(message) + return tuple(sorted(set(value))) + + +def _table( + document: cabc.Mapping[str, object], + key: str, +) -> cabc.Mapping[str, object]: + """Read and validate a TOML table.""" + value = document.get(key, {}) + if not isinstance(value, dict): + message = f"{key!r} must be a table" + raise TypeError(message) + return value + + +def _dictionary_from_text(text: str) -> Dictionary: + """Parse and validate shared dictionary text.""" + document = tomllib.loads(text) + schema = document.get("schema") + if schema != SCHEMA_VERSION: + message = f"unsupported dictionary schema {schema!r}" + raise ValueError(message) + oxford = _table(document, "oxford") + words = _table(document, "words") + patterns = _table(document, "patterns") + files = _table(document, "files") + corrections_table = _table(words, "corrections") + if not all( + isinstance(key, str) and isinstance(value, str) + for key, value in corrections_table.items() + ): + message = "word corrections must map strings to strings" + raise TypeError(message) + return Dictionary( + stems=_string_list(oxford, "stems"), + accepted=_string_list(words, "accepted"), + corrections=tuple(sorted(corrections_table.items())), + ignore_patterns=_string_list(patterns, "ignore"), + excluded_files=_string_list(files, "exclude"), + ) + + +def load_dictionary(path: pathlib.Path) -> Dictionary: + """Load a validated shared dictionary from *path*.""" + return _dictionary_from_text(path.read_text(encoding="utf-8")) + + +def merge_dictionaries(base: Dictionary, local: Dictionary) -> Dictionary: + """Merge a shared dictionary with a non-conflicting local overlay.""" + corrections = dict(base.corrections) + for word, correction in local.corrections: + existing = corrections.get(word) + if existing is not None and existing != correction: + message = ( + f"conflicting correction for {word!r}: {existing!r} != {correction!r}" + ) + raise ValueError(message) + corrections[word] = correction + return Dictionary( + stems=tuple(sorted(set(base.stems) | set(local.stems))), + accepted=tuple(sorted(set(base.accepted) | set(local.accepted))), + corrections=tuple(sorted(corrections.items())), + ignore_patterns=tuple( + sorted(set(base.ignore_patterns) | set(local.ignore_patterns)) + ), + excluded_files=tuple( + sorted(set(base.excluded_files) | set(local.excluded_files)) + ), + ) + + +def generate_word_mappings(dictionary: Dictionary) -> dict[str, str]: + """Expand Oxford stems and explicit words into deterministic mappings.""" + mappings = {word: word for word in dictionary.accepted} + + def add(word: str, correction: str) -> None: + existing = mappings.get(word) + if existing is not None and existing != correction: + message = ( + f"conflicting generated correction for {word!r}: " + f"{existing!r} != {correction!r}" + ) + raise ValueError(message) + mappings[word] = correction + + for word, correction in dictionary.corrections: + add(word, correction) + for stem in dictionary.stems: + for plain_british, oxford in SUFFIX_PAIRS: + add(f"{stem}{plain_british}", f"{stem}{oxford}") + add(f"{stem}{oxford}", f"{stem}{oxford}") + return dict(sorted(mappings.items())) + + +def _toml_string(value: str) -> str: + """Render a string using TOML-compatible JSON quoting.""" + return json.dumps(value, ensure_ascii=False) + + +def _render_array(name: str, values: tuple[str, ...]) -> list[str]: + """Render a deterministic TOML string array.""" + lines = [f"{name} = ["] + lines.extend(f" {_toml_string(value)}," for value in values) + lines.append("]") + return lines + + +def render_typos_config(dictionary: Dictionary) -> str: + """Render a deterministic, parse-checked ``typos.toml`` document.""" + lines = [ + "# Generated from the shared en-GB-oxendict dictionary.", + "# Regenerate with scripts/generate_typos_config.py; do not edit by hand.", + "", + "[files]", + *_render_array("extend-exclude", dictionary.excluded_files), + "", + "[default]", + 'locale = "en-gb"', + *_render_array("extend-ignore-re", dictionary.ignore_patterns), + "", + "[default.extend-words]", + ] + lines.extend( + f"{_toml_string(word)} = {_toml_string(correction)}" + for word, correction in generate_word_mappings(dictionary).items() + ) + rendered = "\n".join(lines) + "\n" + tomllib.loads(rendered) + return rendered + + +def _atomic_write(path: pathlib.Path, content: bytes) -> None: + """Write *content* beside *path* and atomically replace the destination.""" + path.parent.mkdir(parents=True, exist_ok=True) + with tempfile.NamedTemporaryFile( + delete=False, dir=path.parent, prefix=f".{path.name}." + ) as stream: + stream.write(content) + temporary = pathlib.Path(stream.name) + try: + temporary.replace(path) + finally: + temporary.unlink(missing_ok=True) + + +def write_config(path: pathlib.Path, dictionary: Dictionary) -> None: + """Atomically write validated generated configuration to *path*.""" + _atomic_write(path, render_typos_config(dictionary).encode()) + + +def _read_metadata(path: pathlib.Path) -> dict[str, object]: + """Read best-effort HTTP freshness metadata.""" + try: + value = json.loads(path.read_text(encoding="utf-8")) + except FileNotFoundError, json.JSONDecodeError: + return {} + return value if isinstance(value, dict) else {} + + +def _write_metadata( + path: pathlib.Path, + metadata: cabc.Mapping[str, object], +) -> None: + """Atomically write HTTP freshness metadata.""" + _atomic_write(path, (json.dumps(metadata, sort_keys=True) + "\n").encode()) + + +def _valid_cache(cache: pathlib.Path) -> bool: + """Return whether *cache* contains a valid shared dictionary.""" + try: + load_dictionary(cache) + except FileNotFoundError, OSError, TypeError, ValueError, tomllib.TOMLDecodeError: + return False + return True + + +def _remote_is_not_newer( + saved: cabc.Mapping[str, object], + headers: cabc.Mapping[str, str], +) -> bool: + """Return whether HTTP validators prove the response is not newer.""" + etag = headers.get("ETag") + if etag is not None and etag == saved.get("etag"): + return True + modified = headers.get("Last-Modified") + saved_modified = saved.get("last_modified") + if not isinstance(modified, str) or not isinstance(saved_modified, str): + return False + try: + return email.utils.parsedate_to_datetime( + modified + ) <= email.utils.parsedate_to_datetime(saved_modified) + except TypeError, ValueError: + return modified == saved_modified + + +def _local_cache_is_current( + cache: pathlib.Path, + saved: cabc.Mapping[str, object], + source_name: str, + source_mtime_ns: int, +) -> bool: + """Return whether metadata proves a valid local-source cache is current.""" + saved_mtime = saved.get("mtime_ns") + has_matching_source = saved.get("source") == source_name + has_new_enough_mtime = ( + isinstance(saved_mtime, int) and source_mtime_ns <= saved_mtime + ) + return _valid_cache(cache) and has_matching_source and has_new_enough_mtime + + +def _refresh_local( + source: pathlib.Path, + cache: pathlib.Path, + metadata: pathlib.Path, +) -> RefreshResult: + """Refresh from a local authoritative copy when it is newer.""" + source_stat = source.stat() + source_name = str(source.resolve()) + saved = _read_metadata(metadata) + if _local_cache_is_current( + cache, + saved, + source_name, + source_stat.st_mtime_ns, + ): + return RefreshResult("current", cache) + content = source.read_bytes() + _dictionary_from_text(content.decode()) + _atomic_write(cache, content) + _write_metadata( + metadata, + {"source": source_name, "mtime_ns": source_stat.st_mtime_ns}, + ) + return RefreshResult("refreshed", cache) + + +def _conditional_headers(saved: cabc.Mapping[str, object]) -> dict[str, str]: + """Build conditional HTTP headers from persisted validators.""" + headers = {} + if isinstance(saved.get("etag"), str): + headers["If-None-Match"] = saved["etag"] + if isinstance(saved.get("last_modified"), str): + headers["If-Modified-Since"] = saved["last_modified"] + return headers + + +def _https_request( + source: str, + headers: cabc.Mapping[str, str], +) -> urllib.request.Request: + """Build a request after constraining the shared source to HTTPS.""" + if urllib.parse.urlsplit(source).scheme != "https": + message = f"shared dictionary URL must use HTTPS: {source}" + raise ValueError(message) + return urllib.request.Request(source, headers=dict(headers)) # noqa: S310 - HTTPS is required above. + + +def _write_remote_cache( + source: str, + targets: _CacheTargets, + content: bytes, + headers: cabc.Mapping[str, str], +) -> RefreshResult: + """Validate and atomically persist an HTTP dictionary response.""" + _dictionary_from_text(content.decode()) + _atomic_write(targets.cache, content) + _write_metadata( + targets.metadata, + { + "source": source, + "etag": headers.get("ETag"), + "last_modified": headers.get("Last-Modified"), + }, + ) + return RefreshResult("refreshed", targets.cache) + + +def _refresh_http( + source: str, + cache: pathlib.Path, + metadata: pathlib.Path, +) -> RefreshResult: + """Refresh a cache from a validated HTTPS source with stale fallback.""" + saved = _read_metadata(metadata) + request = _https_request(source, _conditional_headers(saved)) + try: + with urllib.request.urlopen( # noqa: S310 - _https_request rejects non-HTTPS URLs. + request, + timeout=30.0, + ) as response: + if response.status == HTTP_NOT_MODIFIED and _valid_cache(cache): + return RefreshResult("current", cache) + if _valid_cache(cache) and _remote_is_not_newer(saved, response.headers): + return RefreshResult("current", cache) + return _write_remote_cache( + source, + _CacheTargets(cache, metadata), + response.read(), + response.headers, + ) + except urllib.error.HTTPError as error: + if error.code == HTTP_NOT_MODIFIED and _valid_cache(cache): + return RefreshResult("current", cache) + if _valid_cache(cache): + return RefreshResult("stale-cache", cache) + raise + except OSError, urllib.error.URLError: + if _valid_cache(cache): + return RefreshResult("stale-cache", cache) + raise + + +def refresh_base( + source: str | pathlib.Path, + cache: pathlib.Path, + *, + metadata: pathlib.Path, + offline: bool = False, +) -> RefreshResult: + """Refresh an untracked base cache when the authoritative copy is newer.""" + if offline: + if not _valid_cache(cache): + message = f"no cached shared dictionary at {cache}" + raise FileNotFoundError(message) + return RefreshResult("offline-cache", cache) + if isinstance(source, pathlib.Path) or "://" not in str(source): + return _refresh_local(pathlib.Path(source), cache, metadata) + return _refresh_http(str(source), cache, metadata) diff --git a/template/typos.local.toml b/template/typos.local.toml new file mode 100644 index 0000000..f9a595d --- /dev/null +++ b/template/typos.local.toml @@ -0,0 +1,19 @@ +# Repository-specific identifiers, quotations and deliberate fixtures. + +schema = 1 + +[oxford] +stems = [] + +[words] +accepted = [] + +[words.corrections] + +[patterns] +ignore = [ + 'Center \| Microsoft Learn', +] + +[files] +exclude = [] diff --git a/template/typos.toml b/template/typos.toml new file mode 100644 index 0000000..c85d624 --- /dev/null +++ b/template/typos.toml @@ -0,0 +1,2631 @@ +# Generated from the shared en-GB-oxendict dictionary. +# Regenerate with scripts/generate_typos_config.py; do not edit by hand. + +[files] +extend-exclude = [ + ".git", + ".hypothesis", + ".pytest_cache", + ".tox", + ".typos-oxendict-base.json", + ".typos-oxendict-base.toml", + ".uv-cache", + ".uv-tools", + ".venv", + "Cargo.lock", + "bun.lock", + "data/typos-oxendict-base.toml", + "dist", + "node_modules", + "package-lock.json", + "pnpm-lock.yaml", + "target", + "typos.local.toml", + "typos.toml", + "uv.lock", + "yarn.lock", +] + +[default] +locale = "en-gb" +extend-ignore-re = [ + "(?s)```.*?```", + "Center \\| Microsoft Learn", + "`[^`\\n]+`", +] + +[default.extend-words] +"absolutisable" = "absolutizable" +"absolutisation" = "absolutization" +"absolutisations" = "absolutizations" +"absolutise" = "absolutize" +"absolutised" = "absolutized" +"absolutiser" = "absolutizer" +"absolutisers" = "absolutizers" +"absolutises" = "absolutizes" +"absolutising" = "absolutizing" +"absolutizable" = "absolutizable" +"absolutization" = "absolutization" +"absolutizations" = "absolutizations" +"absolutize" = "absolutize" +"absolutized" = "absolutized" +"absolutizer" = "absolutizer" +"absolutizers" = "absolutizers" +"absolutizes" = "absolutizes" +"absolutizing" = "absolutizing" +"actualisable" = "actualizable" +"actualisation" = "actualization" +"actualisations" = "actualizations" +"actualise" = "actualize" +"actualised" = "actualized" +"actualiser" = "actualizer" +"actualisers" = "actualizers" +"actualises" = "actualizes" +"actualising" = "actualizing" +"actualizable" = "actualizable" +"actualization" = "actualization" +"actualizations" = "actualizations" +"actualize" = "actualize" +"actualized" = "actualized" +"actualizer" = "actualizer" +"actualizers" = "actualizers" +"actualizes" = "actualizes" +"actualizing" = "actualizing" +"alphabetisable" = "alphabetizable" +"alphabetisation" = "alphabetization" +"alphabetisations" = "alphabetizations" +"alphabetise" = "alphabetize" +"alphabetised" = "alphabetized" +"alphabetiser" = "alphabetizer" +"alphabetisers" = "alphabetizers" +"alphabetises" = "alphabetizes" +"alphabetising" = "alphabetizing" +"alphabetizable" = "alphabetizable" +"alphabetization" = "alphabetization" +"alphabetizations" = "alphabetizations" +"alphabetize" = "alphabetize" +"alphabetized" = "alphabetized" +"alphabetizer" = "alphabetizer" +"alphabetizers" = "alphabetizers" +"alphabetizes" = "alphabetizes" +"alphabetizing" = "alphabetizing" +"amortisable" = "amortizable" +"amortisation" = "amortization" +"amortisations" = "amortizations" +"amortise" = "amortize" +"amortised" = "amortized" +"amortiser" = "amortizer" +"amortisers" = "amortizers" +"amortises" = "amortizes" +"amortising" = "amortizing" +"amortizable" = "amortizable" +"amortization" = "amortization" +"amortizations" = "amortizations" +"amortize" = "amortize" +"amortized" = "amortized" +"amortizer" = "amortizer" +"amortizers" = "amortizers" +"amortizes" = "amortizes" +"amortizing" = "amortizing" +"anonymisable" = "anonymizable" +"anonymisation" = "anonymization" +"anonymisations" = "anonymizations" +"anonymise" = "anonymize" +"anonymised" = "anonymized" +"anonymiser" = "anonymizer" +"anonymisers" = "anonymizers" +"anonymises" = "anonymizes" +"anonymising" = "anonymizing" +"anonymizable" = "anonymizable" +"anonymization" = "anonymization" +"anonymizations" = "anonymizations" +"anonymize" = "anonymize" +"anonymized" = "anonymized" +"anonymizer" = "anonymizer" +"anonymizers" = "anonymizers" +"anonymizes" = "anonymizes" +"anonymizing" = "anonymizing" +"apologisable" = "apologizable" +"apologisation" = "apologization" +"apologisations" = "apologizations" +"apologise" = "apologize" +"apologised" = "apologized" +"apologiser" = "apologizer" +"apologisers" = "apologizers" +"apologises" = "apologizes" +"apologising" = "apologizing" +"apologizable" = "apologizable" +"apologization" = "apologization" +"apologizations" = "apologizations" +"apologize" = "apologize" +"apologized" = "apologized" +"apologizer" = "apologizer" +"apologizers" = "apologizers" +"apologizes" = "apologizes" +"apologizing" = "apologizing" +"atomisable" = "atomizable" +"atomisation" = "atomization" +"atomisations" = "atomizations" +"atomise" = "atomize" +"atomised" = "atomized" +"atomiser" = "atomizer" +"atomisers" = "atomizers" +"atomises" = "atomizes" +"atomising" = "atomizing" +"atomizable" = "atomizable" +"atomization" = "atomization" +"atomizations" = "atomizations" +"atomize" = "atomize" +"atomized" = "atomized" +"atomizer" = "atomizer" +"atomizers" = "atomizers" +"atomizes" = "atomizes" +"atomizing" = "atomizing" +"authorisable" = "authorizable" +"authorisation" = "authorization" +"authorisations" = "authorizations" +"authorise" = "authorize" +"authorised" = "authorized" +"authoriser" = "authorizer" +"authorisers" = "authorizers" +"authorises" = "authorizes" +"authorising" = "authorizing" +"authorizable" = "authorizable" +"authorization" = "authorization" +"authorizations" = "authorizations" +"authorize" = "authorize" +"authorized" = "authorized" +"authorizer" = "authorizer" +"authorizers" = "authorizers" +"authorizes" = "authorizes" +"authorizing" = "authorizing" +"canonicalisable" = "canonicalizable" +"canonicalisation" = "canonicalization" +"canonicalisations" = "canonicalizations" +"canonicalise" = "canonicalize" +"canonicalised" = "canonicalized" +"canonicaliser" = "canonicalizer" +"canonicalisers" = "canonicalizers" +"canonicalises" = "canonicalizes" +"canonicalising" = "canonicalizing" +"canonicalizable" = "canonicalizable" +"canonicalization" = "canonicalization" +"canonicalizations" = "canonicalizations" +"canonicalize" = "canonicalize" +"canonicalized" = "canonicalized" +"canonicalizer" = "canonicalizer" +"canonicalizers" = "canonicalizers" +"canonicalizes" = "canonicalizes" +"canonicalizing" = "canonicalizing" +"capitalisable" = "capitalizable" +"capitalisation" = "capitalization" +"capitalisations" = "capitalizations" +"capitalise" = "capitalize" +"capitalised" = "capitalized" +"capitaliser" = "capitalizer" +"capitalisers" = "capitalizers" +"capitalises" = "capitalizes" +"capitalising" = "capitalizing" +"capitalizable" = "capitalizable" +"capitalization" = "capitalization" +"capitalizations" = "capitalizations" +"capitalize" = "capitalize" +"capitalized" = "capitalized" +"capitalizer" = "capitalizer" +"capitalizers" = "capitalizers" +"capitalizes" = "capitalizes" +"capitalizing" = "capitalizing" +"categorisable" = "categorizable" +"categorisation" = "categorization" +"categorisations" = "categorizations" +"categorise" = "categorize" +"categorised" = "categorized" +"categoriser" = "categorizer" +"categorisers" = "categorizers" +"categorises" = "categorizes" +"categorising" = "categorizing" +"categorizable" = "categorizable" +"categorization" = "categorization" +"categorizations" = "categorizations" +"categorize" = "categorize" +"categorized" = "categorized" +"categorizer" = "categorizer" +"categorizers" = "categorizers" +"categorizes" = "categorizes" +"categorizing" = "categorizing" +"centralisable" = "centralizable" +"centralisation" = "centralization" +"centralisations" = "centralizations" +"centralise" = "centralize" +"centralised" = "centralized" +"centraliser" = "centralizer" +"centralisers" = "centralizers" +"centralises" = "centralizes" +"centralising" = "centralizing" +"centralizable" = "centralizable" +"centralization" = "centralization" +"centralizations" = "centralizations" +"centralize" = "centralize" +"centralized" = "centralized" +"centralizer" = "centralizer" +"centralizers" = "centralizers" +"centralizes" = "centralizes" +"centralizing" = "centralizing" +"characterisable" = "characterizable" +"characterisation" = "characterization" +"characterisations" = "characterizations" +"characterise" = "characterize" +"characterised" = "characterized" +"characteriser" = "characterizer" +"characterisers" = "characterizers" +"characterises" = "characterizes" +"characterising" = "characterizing" +"characterizable" = "characterizable" +"characterization" = "characterization" +"characterizations" = "characterizations" +"characterize" = "characterize" +"characterized" = "characterized" +"characterizer" = "characterizer" +"characterizers" = "characterizers" +"characterizes" = "characterizes" +"characterizing" = "characterizing" +"civilisable" = "civilizable" +"civilisation" = "civilization" +"civilisations" = "civilizations" +"civilise" = "civilize" +"civilised" = "civilized" +"civiliser" = "civilizer" +"civilisers" = "civilizers" +"civilises" = "civilizes" +"civilising" = "civilizing" +"civilizable" = "civilizable" +"civilization" = "civilization" +"civilizations" = "civilizations" +"civilize" = "civilize" +"civilized" = "civilized" +"civilizer" = "civilizer" +"civilizers" = "civilizers" +"civilizes" = "civilizes" +"civilizing" = "civilizing" +"colonisable" = "colonizable" +"colonisation" = "colonization" +"colonisations" = "colonizations" +"colonise" = "colonize" +"colonised" = "colonized" +"coloniser" = "colonizer" +"colonisers" = "colonizers" +"colonises" = "colonizes" +"colonising" = "colonizing" +"colonizable" = "colonizable" +"colonization" = "colonization" +"colonizations" = "colonizations" +"colonize" = "colonize" +"colonized" = "colonized" +"colonizer" = "colonizer" +"colonizers" = "colonizers" +"colonizes" = "colonizes" +"colonizing" = "colonizing" +"colourisable" = "colourizable" +"colourisation" = "colourization" +"colourisations" = "colourizations" +"colourise" = "colourize" +"colourised" = "colourized" +"colouriser" = "colourizer" +"colourisers" = "colourizers" +"colourises" = "colourizes" +"colourising" = "colourizing" +"colourizable" = "colourizable" +"colourization" = "colourization" +"colourizations" = "colourizations" +"colourize" = "colourize" +"colourized" = "colourized" +"colourizer" = "colourizer" +"colourizers" = "colourizers" +"colourizes" = "colourizes" +"colourizing" = "colourizing" +"commonisable" = "commonizable" +"commonisation" = "commonization" +"commonisations" = "commonizations" +"commonise" = "commonize" +"commonised" = "commonized" +"commoniser" = "commonizer" +"commonisers" = "commonizers" +"commonises" = "commonizes" +"commonising" = "commonizing" +"commonizable" = "commonizable" +"commonization" = "commonization" +"commonizations" = "commonizations" +"commonize" = "commonize" +"commonized" = "commonized" +"commonizer" = "commonizer" +"commonizers" = "commonizers" +"commonizes" = "commonizes" +"commonizing" = "commonizing" +"conceptualisable" = "conceptualizable" +"conceptualisation" = "conceptualization" +"conceptualisations" = "conceptualizations" +"conceptualise" = "conceptualize" +"conceptualised" = "conceptualized" +"conceptualiser" = "conceptualizer" +"conceptualisers" = "conceptualizers" +"conceptualises" = "conceptualizes" +"conceptualising" = "conceptualizing" +"conceptualizable" = "conceptualizable" +"conceptualization" = "conceptualization" +"conceptualizations" = "conceptualizations" +"conceptualize" = "conceptualize" +"conceptualized" = "conceptualized" +"conceptualizer" = "conceptualizer" +"conceptualizers" = "conceptualizers" +"conceptualizes" = "conceptualizes" +"conceptualizing" = "conceptualizing" +"concretisable" = "concretizable" +"concretisation" = "concretization" +"concretisations" = "concretizations" +"concretise" = "concretize" +"concretised" = "concretized" +"concretiser" = "concretizer" +"concretisers" = "concretizers" +"concretises" = "concretizes" +"concretising" = "concretizing" +"concretizable" = "concretizable" +"concretization" = "concretization" +"concretizations" = "concretizations" +"concretize" = "concretize" +"concretized" = "concretized" +"concretizer" = "concretizer" +"concretizers" = "concretizers" +"concretizes" = "concretizes" +"concretizing" = "concretizing" +"containerisable" = "containerizable" +"containerisation" = "containerization" +"containerisations" = "containerizations" +"containerise" = "containerize" +"containerised" = "containerized" +"containeriser" = "containerizer" +"containerisers" = "containerizers" +"containerises" = "containerizes" +"containerising" = "containerizing" +"containerizable" = "containerizable" +"containerization" = "containerization" +"containerizations" = "containerizations" +"containerize" = "containerize" +"containerized" = "containerized" +"containerizer" = "containerizer" +"containerizers" = "containerizers" +"containerizes" = "containerizes" +"containerizing" = "containerizing" +"contextualisable" = "contextualizable" +"contextualisation" = "contextualization" +"contextualisations" = "contextualizations" +"contextualise" = "contextualize" +"contextualised" = "contextualized" +"contextualiser" = "contextualizer" +"contextualisers" = "contextualizers" +"contextualises" = "contextualizes" +"contextualising" = "contextualizing" +"contextualizable" = "contextualizable" +"contextualization" = "contextualization" +"contextualizations" = "contextualizations" +"contextualize" = "contextualize" +"contextualized" = "contextualized" +"contextualizer" = "contextualizer" +"contextualizers" = "contextualizers" +"contextualizes" = "contextualizes" +"contextualizing" = "contextualizing" +"criticisable" = "criticizable" +"criticisation" = "criticization" +"criticisations" = "criticizations" +"criticise" = "criticize" +"criticised" = "criticized" +"criticiser" = "criticizer" +"criticisers" = "criticizers" +"criticises" = "criticizes" +"criticising" = "criticizing" +"criticizable" = "criticizable" +"criticization" = "criticization" +"criticizations" = "criticizations" +"criticize" = "criticize" +"criticized" = "criticized" +"criticizer" = "criticizer" +"criticizers" = "criticizers" +"criticizes" = "criticizes" +"criticizing" = "criticizing" +"crystallisable" = "crystallizable" +"crystallisation" = "crystallization" +"crystallisations" = "crystallizations" +"crystallise" = "crystallize" +"crystallised" = "crystallized" +"crystalliser" = "crystallizer" +"crystallisers" = "crystallizers" +"crystallises" = "crystallizes" +"crystallising" = "crystallizing" +"crystallizable" = "crystallizable" +"crystallization" = "crystallization" +"crystallizations" = "crystallizations" +"crystallize" = "crystallize" +"crystallized" = "crystallized" +"crystallizer" = "crystallizer" +"crystallizers" = "crystallizers" +"crystallizes" = "crystallizes" +"crystallizing" = "crystallizing" +"customisable" = "customizable" +"customisation" = "customization" +"customisations" = "customizations" +"customise" = "customize" +"customised" = "customized" +"customiser" = "customizer" +"customisers" = "customizers" +"customises" = "customizes" +"customising" = "customizing" +"customizable" = "customizable" +"customization" = "customization" +"customizations" = "customizations" +"customize" = "customize" +"customized" = "customized" +"customizer" = "customizer" +"customizers" = "customizers" +"customizes" = "customizes" +"customizing" = "customizing" +"daemonisable" = "daemonizable" +"daemonisation" = "daemonization" +"daemonisations" = "daemonizations" +"daemonise" = "daemonize" +"daemonised" = "daemonized" +"daemoniser" = "daemonizer" +"daemonisers" = "daemonizers" +"daemonises" = "daemonizes" +"daemonising" = "daemonizing" +"daemonizable" = "daemonizable" +"daemonization" = "daemonization" +"daemonizations" = "daemonizations" +"daemonize" = "daemonize" +"daemonized" = "daemonized" +"daemonizer" = "daemonizer" +"daemonizers" = "daemonizers" +"daemonizes" = "daemonizes" +"daemonizing" = "daemonizing" +"decentralisable" = "decentralizable" +"decentralisation" = "decentralization" +"decentralisations" = "decentralizations" +"decentralise" = "decentralize" +"decentralised" = "decentralized" +"decentraliser" = "decentralizer" +"decentralisers" = "decentralizers" +"decentralises" = "decentralizes" +"decentralising" = "decentralizing" +"decentralizable" = "decentralizable" +"decentralization" = "decentralization" +"decentralizations" = "decentralizations" +"decentralize" = "decentralize" +"decentralized" = "decentralized" +"decentralizer" = "decentralizer" +"decentralizers" = "decentralizers" +"decentralizes" = "decentralizes" +"decentralizing" = "decentralizing" +"denormalisable" = "denormalizable" +"denormalisation" = "denormalization" +"denormalisations" = "denormalizations" +"denormalise" = "denormalize" +"denormalised" = "denormalized" +"denormaliser" = "denormalizer" +"denormalisers" = "denormalizers" +"denormalises" = "denormalizes" +"denormalising" = "denormalizing" +"denormalizable" = "denormalizable" +"denormalization" = "denormalization" +"denormalizations" = "denormalizations" +"denormalize" = "denormalize" +"denormalized" = "denormalized" +"denormalizer" = "denormalizer" +"denormalizers" = "denormalizers" +"denormalizes" = "denormalizes" +"denormalizing" = "denormalizing" +"derandomisable" = "derandomizable" +"derandomisation" = "derandomization" +"derandomisations" = "derandomizations" +"derandomise" = "derandomize" +"derandomised" = "derandomized" +"derandomiser" = "derandomizer" +"derandomisers" = "derandomizers" +"derandomises" = "derandomizes" +"derandomising" = "derandomizing" +"derandomizable" = "derandomizable" +"derandomization" = "derandomization" +"derandomizations" = "derandomizations" +"derandomize" = "derandomize" +"derandomized" = "derandomized" +"derandomizer" = "derandomizer" +"derandomizers" = "derandomizers" +"derandomizes" = "derandomizes" +"derandomizing" = "derandomizing" +"deserialisable" = "deserializable" +"deserialisation" = "deserialization" +"deserialisations" = "deserializations" +"deserialise" = "deserialize" +"deserialised" = "deserialized" +"deserialiser" = "deserializer" +"deserialisers" = "deserializers" +"deserialises" = "deserializes" +"deserialising" = "deserializing" +"deserializable" = "deserializable" +"deserialization" = "deserialization" +"deserializations" = "deserializations" +"deserialize" = "deserialize" +"deserialized" = "deserialized" +"deserializer" = "deserializer" +"deserializers" = "deserializers" +"deserializes" = "deserializes" +"deserializing" = "deserializing" +"destabilisable" = "destabilizable" +"destabilisation" = "destabilization" +"destabilisations" = "destabilizations" +"destabilise" = "destabilize" +"destabilised" = "destabilized" +"destabiliser" = "destabilizer" +"destabilisers" = "destabilizers" +"destabilises" = "destabilizes" +"destabilising" = "destabilizing" +"destabilizable" = "destabilizable" +"destabilization" = "destabilization" +"destabilizations" = "destabilizations" +"destabilize" = "destabilize" +"destabilized" = "destabilized" +"destabilizer" = "destabilizer" +"destabilizers" = "destabilizers" +"destabilizes" = "destabilizes" +"destabilizing" = "destabilizing" +"desynchronisable" = "desynchronizable" +"desynchronisation" = "desynchronization" +"desynchronisations" = "desynchronizations" +"desynchronise" = "desynchronize" +"desynchronised" = "desynchronized" +"desynchroniser" = "desynchronizer" +"desynchronisers" = "desynchronizers" +"desynchronises" = "desynchronizes" +"desynchronising" = "desynchronizing" +"desynchronizable" = "desynchronizable" +"desynchronization" = "desynchronization" +"desynchronizations" = "desynchronizations" +"desynchronize" = "desynchronize" +"desynchronized" = "desynchronized" +"desynchronizer" = "desynchronizer" +"desynchronizers" = "desynchronizers" +"desynchronizes" = "desynchronizes" +"desynchronizing" = "desynchronizing" +"dockerisable" = "dockerizable" +"dockerisation" = "dockerization" +"dockerisations" = "dockerizations" +"dockerise" = "dockerize" +"dockerised" = "dockerized" +"dockeriser" = "dockerizer" +"dockerisers" = "dockerizers" +"dockerises" = "dockerizes" +"dockerising" = "dockerizing" +"dockerizable" = "dockerizable" +"dockerization" = "dockerization" +"dockerizations" = "dockerizations" +"dockerize" = "dockerize" +"dockerized" = "dockerized" +"dockerizer" = "dockerizer" +"dockerizers" = "dockerizers" +"dockerizes" = "dockerizes" +"dockerizing" = "dockerizing" +"dramatisable" = "dramatizable" +"dramatisation" = "dramatization" +"dramatisations" = "dramatizations" +"dramatise" = "dramatize" +"dramatised" = "dramatized" +"dramatiser" = "dramatizer" +"dramatisers" = "dramatizers" +"dramatises" = "dramatizes" +"dramatising" = "dramatizing" +"dramatizable" = "dramatizable" +"dramatization" = "dramatization" +"dramatizations" = "dramatizations" +"dramatize" = "dramatize" +"dramatized" = "dramatized" +"dramatizer" = "dramatizer" +"dramatizers" = "dramatizers" +"dramatizes" = "dramatizes" +"dramatizing" = "dramatizing" +"emphasisable" = "emphasizable" +"emphasisation" = "emphasization" +"emphasisations" = "emphasizations" +"emphasise" = "emphasize" +"emphasised" = "emphasized" +"emphasiser" = "emphasizer" +"emphasisers" = "emphasizers" +"emphasises" = "emphasizes" +"emphasising" = "emphasizing" +"emphasizable" = "emphasizable" +"emphasization" = "emphasization" +"emphasizations" = "emphasizations" +"emphasize" = "emphasize" +"emphasized" = "emphasized" +"emphasizer" = "emphasizer" +"emphasizers" = "emphasizers" +"emphasizes" = "emphasizes" +"emphasizing" = "emphasizing" +"energisable" = "energizable" +"energisation" = "energization" +"energisations" = "energizations" +"energise" = "energize" +"energised" = "energized" +"energiser" = "energizer" +"energisers" = "energizers" +"energises" = "energizes" +"energising" = "energizing" +"energizable" = "energizable" +"energization" = "energization" +"energizations" = "energizations" +"energize" = "energize" +"energized" = "energized" +"energizer" = "energizer" +"energizers" = "energizers" +"energizes" = "energizes" +"energizing" = "energizing" +"equalisable" = "equalizable" +"equalisation" = "equalization" +"equalisations" = "equalizations" +"equalise" = "equalize" +"equalised" = "equalized" +"equaliser" = "equalizer" +"equalisers" = "equalizers" +"equalises" = "equalizes" +"equalising" = "equalizing" +"equalizable" = "equalizable" +"equalization" = "equalization" +"equalizations" = "equalizations" +"equalize" = "equalize" +"equalized" = "equalized" +"equalizer" = "equalizer" +"equalizers" = "equalizers" +"equalizes" = "equalizes" +"equalizing" = "equalizing" +"externalisable" = "externalizable" +"externalisation" = "externalization" +"externalisations" = "externalizations" +"externalise" = "externalize" +"externalised" = "externalized" +"externaliser" = "externalizer" +"externalisers" = "externalizers" +"externalises" = "externalizes" +"externalising" = "externalizing" +"externalizable" = "externalizable" +"externalization" = "externalization" +"externalizations" = "externalizations" +"externalize" = "externalize" +"externalized" = "externalized" +"externalizer" = "externalizer" +"externalizers" = "externalizers" +"externalizes" = "externalizes" +"externalizing" = "externalizing" +"factorisable" = "factorizable" +"factorisation" = "factorization" +"factorisations" = "factorizations" +"factorise" = "factorize" +"factorised" = "factorized" +"factoriser" = "factorizer" +"factorisers" = "factorizers" +"factorises" = "factorizes" +"factorising" = "factorizing" +"factorizable" = "factorizable" +"factorization" = "factorization" +"factorizations" = "factorizations" +"factorize" = "factorize" +"factorized" = "factorized" +"factorizer" = "factorizer" +"factorizers" = "factorizers" +"factorizes" = "factorizes" +"factorizing" = "factorizing" +"familiarisable" = "familiarizable" +"familiarisation" = "familiarization" +"familiarisations" = "familiarizations" +"familiarise" = "familiarize" +"familiarised" = "familiarized" +"familiariser" = "familiarizer" +"familiarisers" = "familiarizers" +"familiarises" = "familiarizes" +"familiarising" = "familiarizing" +"familiarizable" = "familiarizable" +"familiarization" = "familiarization" +"familiarizations" = "familiarizations" +"familiarize" = "familiarize" +"familiarized" = "familiarized" +"familiarizer" = "familiarizer" +"familiarizers" = "familiarizers" +"familiarizes" = "familiarizes" +"familiarizing" = "familiarizing" +"finalisable" = "finalizable" +"finalisation" = "finalization" +"finalisations" = "finalizations" +"finalise" = "finalize" +"finalised" = "finalized" +"finaliser" = "finalizer" +"finalisers" = "finalizers" +"finalises" = "finalizes" +"finalising" = "finalizing" +"finalizable" = "finalizable" +"finalization" = "finalization" +"finalizations" = "finalizations" +"finalize" = "finalize" +"finalized" = "finalized" +"finalizer" = "finalizer" +"finalizers" = "finalizers" +"finalizes" = "finalizes" +"finalizing" = "finalizing" +"formalisable" = "formalizable" +"formalisation" = "formalization" +"formalisations" = "formalizations" +"formalise" = "formalize" +"formalised" = "formalized" +"formaliser" = "formalizer" +"formalisers" = "formalizers" +"formalises" = "formalizes" +"formalising" = "formalizing" +"formalizable" = "formalizable" +"formalization" = "formalization" +"formalizations" = "formalizations" +"formalize" = "formalize" +"formalized" = "formalized" +"formalizer" = "formalizer" +"formalizers" = "formalizers" +"formalizes" = "formalizes" +"formalizing" = "formalizing" +"fossilisable" = "fossilizable" +"fossilisation" = "fossilization" +"fossilisations" = "fossilizations" +"fossilise" = "fossilize" +"fossilised" = "fossilized" +"fossiliser" = "fossilizer" +"fossilisers" = "fossilizers" +"fossilises" = "fossilizes" +"fossilising" = "fossilizing" +"fossilizable" = "fossilizable" +"fossilization" = "fossilization" +"fossilizations" = "fossilizations" +"fossilize" = "fossilize" +"fossilized" = "fossilized" +"fossilizer" = "fossilizer" +"fossilizers" = "fossilizers" +"fossilizes" = "fossilizes" +"fossilizing" = "fossilizing" +"generalisable" = "generalizable" +"generalisation" = "generalization" +"generalisations" = "generalizations" +"generalise" = "generalize" +"generalised" = "generalized" +"generaliser" = "generalizer" +"generalisers" = "generalizers" +"generalises" = "generalizes" +"generalising" = "generalizing" +"generalizable" = "generalizable" +"generalization" = "generalization" +"generalizations" = "generalizations" +"generalize" = "generalize" +"generalized" = "generalized" +"generalizer" = "generalizer" +"generalizers" = "generalizers" +"generalizes" = "generalizes" +"generalizing" = "generalizing" +"globalisable" = "globalizable" +"globalisation" = "globalization" +"globalisations" = "globalizations" +"globalise" = "globalize" +"globalised" = "globalized" +"globaliser" = "globalizer" +"globalisers" = "globalizers" +"globalises" = "globalizes" +"globalising" = "globalizing" +"globalizable" = "globalizable" +"globalization" = "globalization" +"globalizations" = "globalizations" +"globalize" = "globalize" +"globalized" = "globalized" +"globalizer" = "globalizer" +"globalizers" = "globalizers" +"globalizes" = "globalizes" +"globalizing" = "globalizing" +"harmonisable" = "harmonizable" +"harmonisation" = "harmonization" +"harmonisations" = "harmonizations" +"harmonise" = "harmonize" +"harmonised" = "harmonized" +"harmoniser" = "harmonizer" +"harmonisers" = "harmonizers" +"harmonises" = "harmonizes" +"harmonising" = "harmonizing" +"harmonizable" = "harmonizable" +"harmonization" = "harmonization" +"harmonizations" = "harmonizations" +"harmonize" = "harmonize" +"harmonized" = "harmonized" +"harmonizer" = "harmonizer" +"harmonizers" = "harmonizers" +"harmonizes" = "harmonizes" +"harmonizing" = "harmonizing" +"homogenisable" = "homogenizable" +"homogenisation" = "homogenization" +"homogenisations" = "homogenizations" +"homogenise" = "homogenize" +"homogenised" = "homogenized" +"homogeniser" = "homogenizer" +"homogenisers" = "homogenizers" +"homogenises" = "homogenizes" +"homogenising" = "homogenizing" +"homogenizable" = "homogenizable" +"homogenization" = "homogenization" +"homogenizations" = "homogenizations" +"homogenize" = "homogenize" +"homogenized" = "homogenized" +"homogenizer" = "homogenizer" +"homogenizers" = "homogenizers" +"homogenizes" = "homogenizes" +"homogenizing" = "homogenizing" +"humanisable" = "humanizable" +"humanisation" = "humanization" +"humanisations" = "humanizations" +"humanise" = "humanize" +"humanised" = "humanized" +"humaniser" = "humanizer" +"humanisers" = "humanizers" +"humanises" = "humanizes" +"humanising" = "humanizing" +"humanizable" = "humanizable" +"humanization" = "humanization" +"humanizations" = "humanizations" +"humanize" = "humanize" +"humanized" = "humanized" +"humanizer" = "humanizer" +"humanizers" = "humanizers" +"humanizes" = "humanizes" +"humanizing" = "humanizing" +"hypothesisable" = "hypothesizable" +"hypothesisation" = "hypothesization" +"hypothesisations" = "hypothesizations" +"hypothesise" = "hypothesize" +"hypothesised" = "hypothesized" +"hypothesiser" = "hypothesizer" +"hypothesisers" = "hypothesizers" +"hypothesises" = "hypothesizes" +"hypothesising" = "hypothesizing" +"hypothesizable" = "hypothesizable" +"hypothesization" = "hypothesization" +"hypothesizations" = "hypothesizations" +"hypothesize" = "hypothesize" +"hypothesized" = "hypothesized" +"hypothesizer" = "hypothesizer" +"hypothesizers" = "hypothesizers" +"hypothesizes" = "hypothesizes" +"hypothesizing" = "hypothesizing" +"idealisable" = "idealizable" +"idealisation" = "idealization" +"idealisations" = "idealizations" +"idealise" = "idealize" +"idealised" = "idealized" +"idealiser" = "idealizer" +"idealisers" = "idealizers" +"idealises" = "idealizes" +"idealising" = "idealizing" +"idealizable" = "idealizable" +"idealization" = "idealization" +"idealizations" = "idealizations" +"idealize" = "idealize" +"idealized" = "idealized" +"idealizer" = "idealizer" +"idealizers" = "idealizers" +"idealizes" = "idealizes" +"idealizing" = "idealizing" +"industrialisable" = "industrializable" +"industrialisation" = "industrialization" +"industrialisations" = "industrializations" +"industrialise" = "industrialize" +"industrialised" = "industrialized" +"industrialiser" = "industrializer" +"industrialisers" = "industrializers" +"industrialises" = "industrializes" +"industrialising" = "industrializing" +"industrializable" = "industrializable" +"industrialization" = "industrialization" +"industrializations" = "industrializations" +"industrialize" = "industrialize" +"industrialized" = "industrialized" +"industrializer" = "industrializer" +"industrializers" = "industrializers" +"industrializes" = "industrializes" +"industrializing" = "industrializing" +"initialisable" = "initializable" +"initialisation" = "initialization" +"initialisations" = "initializations" +"initialise" = "initialize" +"initialised" = "initialized" +"initialiser" = "initializer" +"initialisers" = "initializers" +"initialises" = "initializes" +"initialising" = "initializing" +"initializable" = "initializable" +"initialization" = "initialization" +"initializations" = "initializations" +"initialize" = "initialize" +"initialized" = "initialized" +"initializer" = "initializer" +"initializers" = "initializers" +"initializes" = "initializes" +"initializing" = "initializing" +"institutionalisable" = "institutionalizable" +"institutionalisation" = "institutionalization" +"institutionalisations" = "institutionalizations" +"institutionalise" = "institutionalize" +"institutionalised" = "institutionalized" +"institutionaliser" = "institutionalizer" +"institutionalisers" = "institutionalizers" +"institutionalises" = "institutionalizes" +"institutionalising" = "institutionalizing" +"institutionalizable" = "institutionalizable" +"institutionalization" = "institutionalization" +"institutionalizations" = "institutionalizations" +"institutionalize" = "institutionalize" +"institutionalized" = "institutionalized" +"institutionalizer" = "institutionalizer" +"institutionalizers" = "institutionalizers" +"institutionalizes" = "institutionalizes" +"institutionalizing" = "institutionalizing" +"internalisable" = "internalizable" +"internalisation" = "internalization" +"internalisations" = "internalizations" +"internalise" = "internalize" +"internalised" = "internalized" +"internaliser" = "internalizer" +"internalisers" = "internalizers" +"internalises" = "internalizes" +"internalising" = "internalizing" +"internalizable" = "internalizable" +"internalization" = "internalization" +"internalizations" = "internalizations" +"internalize" = "internalize" +"internalized" = "internalized" +"internalizer" = "internalizer" +"internalizers" = "internalizers" +"internalizes" = "internalizes" +"internalizing" = "internalizing" +"internationalisable" = "internationalizable" +"internationalisation" = "internationalization" +"internationalisations" = "internationalizations" +"internationalise" = "internationalize" +"internationalised" = "internationalized" +"internationaliser" = "internationalizer" +"internationalisers" = "internationalizers" +"internationalises" = "internationalizes" +"internationalising" = "internationalizing" +"internationalizable" = "internationalizable" +"internationalization" = "internationalization" +"internationalizations" = "internationalizations" +"internationalize" = "internationalize" +"internationalized" = "internationalized" +"internationalizer" = "internationalizer" +"internationalizers" = "internationalizers" +"internationalizes" = "internationalizes" +"internationalizing" = "internationalizing" +"itemisable" = "itemizable" +"itemisation" = "itemization" +"itemisations" = "itemizations" +"itemise" = "itemize" +"itemised" = "itemized" +"itemiser" = "itemizer" +"itemisers" = "itemizers" +"itemises" = "itemizes" +"itemising" = "itemizing" +"itemizable" = "itemizable" +"itemization" = "itemization" +"itemizations" = "itemizations" +"itemize" = "itemize" +"itemized" = "itemized" +"itemizer" = "itemizer" +"itemizers" = "itemizers" +"itemizes" = "itemizes" +"itemizing" = "itemizing" +"jeopardisable" = "jeopardizable" +"jeopardisation" = "jeopardization" +"jeopardisations" = "jeopardizations" +"jeopardise" = "jeopardize" +"jeopardised" = "jeopardized" +"jeopardiser" = "jeopardizer" +"jeopardisers" = "jeopardizers" +"jeopardises" = "jeopardizes" +"jeopardising" = "jeopardizing" +"jeopardizable" = "jeopardizable" +"jeopardization" = "jeopardization" +"jeopardizations" = "jeopardizations" +"jeopardize" = "jeopardize" +"jeopardized" = "jeopardized" +"jeopardizer" = "jeopardizer" +"jeopardizers" = "jeopardizers" +"jeopardizes" = "jeopardizes" +"jeopardizing" = "jeopardizing" +"kernelisable" = "kernelizable" +"kernelisation" = "kernelization" +"kernelisations" = "kernelizations" +"kernelise" = "kernelize" +"kernelised" = "kernelized" +"kerneliser" = "kernelizer" +"kernelisers" = "kernelizers" +"kernelises" = "kernelizes" +"kernelising" = "kernelizing" +"kernelizable" = "kernelizable" +"kernelization" = "kernelization" +"kernelizations" = "kernelizations" +"kernelize" = "kernelize" +"kernelized" = "kernelized" +"kernelizer" = "kernelizer" +"kernelizers" = "kernelizers" +"kernelizes" = "kernelizes" +"kernelizing" = "kernelizing" +"legitimisable" = "legitimizable" +"legitimisation" = "legitimization" +"legitimisations" = "legitimizations" +"legitimise" = "legitimize" +"legitimised" = "legitimized" +"legitimiser" = "legitimizer" +"legitimisers" = "legitimizers" +"legitimises" = "legitimizes" +"legitimising" = "legitimizing" +"legitimizable" = "legitimizable" +"legitimization" = "legitimization" +"legitimizations" = "legitimizations" +"legitimize" = "legitimize" +"legitimized" = "legitimized" +"legitimizer" = "legitimizer" +"legitimizers" = "legitimizers" +"legitimizes" = "legitimizes" +"legitimizing" = "legitimizing" +"lemmatisable" = "lemmatizable" +"lemmatisation" = "lemmatization" +"lemmatisations" = "lemmatizations" +"lemmatise" = "lemmatize" +"lemmatised" = "lemmatized" +"lemmatiser" = "lemmatizer" +"lemmatisers" = "lemmatizers" +"lemmatises" = "lemmatizes" +"lemmatising" = "lemmatizing" +"lemmatizable" = "lemmatizable" +"lemmatization" = "lemmatization" +"lemmatizations" = "lemmatizations" +"lemmatize" = "lemmatize" +"lemmatized" = "lemmatized" +"lemmatizer" = "lemmatizer" +"lemmatizers" = "lemmatizers" +"lemmatizes" = "lemmatizes" +"lemmatizing" = "lemmatizing" +"linearisable" = "linearizable" +"linearisation" = "linearization" +"linearisations" = "linearizations" +"linearise" = "linearize" +"linearised" = "linearized" +"lineariser" = "linearizer" +"linearisers" = "linearizers" +"linearises" = "linearizes" +"linearising" = "linearizing" +"linearizable" = "linearizable" +"linearization" = "linearization" +"linearizations" = "linearizations" +"linearize" = "linearize" +"linearized" = "linearized" +"linearizer" = "linearizer" +"linearizers" = "linearizers" +"linearizes" = "linearizes" +"linearizing" = "linearizing" +"localisable" = "localizable" +"localisation" = "localization" +"localisations" = "localizations" +"localise" = "localize" +"localised" = "localized" +"localiser" = "localizer" +"localisers" = "localizers" +"localises" = "localizes" +"localising" = "localizing" +"localizable" = "localizable" +"localization" = "localization" +"localizations" = "localizations" +"localize" = "localize" +"localized" = "localized" +"localizer" = "localizer" +"localizers" = "localizers" +"localizes" = "localizes" +"localizing" = "localizing" +"materialisable" = "materializable" +"materialisation" = "materialization" +"materialisations" = "materializations" +"materialise" = "materialize" +"materialised" = "materialized" +"materialiser" = "materializer" +"materialisers" = "materializers" +"materialises" = "materializes" +"materialising" = "materializing" +"materializable" = "materializable" +"materialization" = "materialization" +"materializations" = "materializations" +"materialize" = "materialize" +"materialized" = "materialized" +"materializer" = "materializer" +"materializers" = "materializers" +"materializes" = "materializes" +"materializing" = "materializing" +"maximisable" = "maximizable" +"maximisation" = "maximization" +"maximisations" = "maximizations" +"maximise" = "maximize" +"maximised" = "maximized" +"maximiser" = "maximizer" +"maximisers" = "maximizers" +"maximises" = "maximizes" +"maximising" = "maximizing" +"maximizable" = "maximizable" +"maximization" = "maximization" +"maximizations" = "maximizations" +"maximize" = "maximize" +"maximized" = "maximized" +"maximizer" = "maximizer" +"maximizers" = "maximizers" +"maximizes" = "maximizes" +"maximizing" = "maximizing" +"mechanisable" = "mechanizable" +"mechanisation" = "mechanization" +"mechanisations" = "mechanizations" +"mechanise" = "mechanize" +"mechanised" = "mechanized" +"mechaniser" = "mechanizer" +"mechanisers" = "mechanizers" +"mechanises" = "mechanizes" +"mechanising" = "mechanizing" +"mechanizable" = "mechanizable" +"mechanization" = "mechanization" +"mechanizations" = "mechanizations" +"mechanize" = "mechanize" +"mechanized" = "mechanized" +"mechanizer" = "mechanizer" +"mechanizers" = "mechanizers" +"mechanizes" = "mechanizes" +"mechanizing" = "mechanizing" +"memoisable" = "memoizable" +"memoisation" = "memoization" +"memoisations" = "memoizations" +"memoise" = "memoize" +"memoised" = "memoized" +"memoiser" = "memoizer" +"memoisers" = "memoizers" +"memoises" = "memoizes" +"memoising" = "memoizing" +"memoizable" = "memoizable" +"memoization" = "memoization" +"memoizations" = "memoizations" +"memoize" = "memoize" +"memoized" = "memoized" +"memoizer" = "memoizer" +"memoizers" = "memoizers" +"memoizes" = "memoizes" +"memoizing" = "memoizing" +"memorisable" = "memorizable" +"memorisation" = "memorization" +"memorisations" = "memorizations" +"memorise" = "memorize" +"memorised" = "memorized" +"memoriser" = "memorizer" +"memorisers" = "memorizers" +"memorises" = "memorizes" +"memorising" = "memorizing" +"memorizable" = "memorizable" +"memorization" = "memorization" +"memorizations" = "memorizations" +"memorize" = "memorize" +"memorized" = "memorized" +"memorizer" = "memorizer" +"memorizers" = "memorizers" +"memorizes" = "memorizes" +"memorizing" = "memorizing" +"miniaturisable" = "miniaturizable" +"miniaturisation" = "miniaturization" +"miniaturisations" = "miniaturizations" +"miniaturise" = "miniaturize" +"miniaturised" = "miniaturized" +"miniaturiser" = "miniaturizer" +"miniaturisers" = "miniaturizers" +"miniaturises" = "miniaturizes" +"miniaturising" = "miniaturizing" +"miniaturizable" = "miniaturizable" +"miniaturization" = "miniaturization" +"miniaturizations" = "miniaturizations" +"miniaturize" = "miniaturize" +"miniaturized" = "miniaturized" +"miniaturizer" = "miniaturizer" +"miniaturizers" = "miniaturizers" +"miniaturizes" = "miniaturizes" +"miniaturizing" = "miniaturizing" +"minimisable" = "minimizable" +"minimisation" = "minimization" +"minimisations" = "minimizations" +"minimise" = "minimize" +"minimised" = "minimized" +"minimiser" = "minimizer" +"minimisers" = "minimizers" +"minimises" = "minimizes" +"minimising" = "minimizing" +"minimizable" = "minimizable" +"minimization" = "minimization" +"minimizations" = "minimizations" +"minimize" = "minimize" +"minimized" = "minimized" +"minimizer" = "minimizer" +"minimizers" = "minimizers" +"minimizes" = "minimizes" +"minimizing" = "minimizing" +"mobilisable" = "mobilizable" +"mobilisation" = "mobilization" +"mobilisations" = "mobilizations" +"mobilise" = "mobilize" +"mobilised" = "mobilized" +"mobiliser" = "mobilizer" +"mobilisers" = "mobilizers" +"mobilises" = "mobilizes" +"mobilising" = "mobilizing" +"mobilizable" = "mobilizable" +"mobilization" = "mobilization" +"mobilizations" = "mobilizations" +"mobilize" = "mobilize" +"mobilized" = "mobilized" +"mobilizer" = "mobilizer" +"mobilizers" = "mobilizers" +"mobilizes" = "mobilizes" +"mobilizing" = "mobilizing" +"modernisable" = "modernizable" +"modernisation" = "modernization" +"modernisations" = "modernizations" +"modernise" = "modernize" +"modernised" = "modernized" +"moderniser" = "modernizer" +"modernisers" = "modernizers" +"modernises" = "modernizes" +"modernising" = "modernizing" +"modernizable" = "modernizable" +"modernization" = "modernization" +"modernizations" = "modernizations" +"modernize" = "modernize" +"modernized" = "modernized" +"modernizer" = "modernizer" +"modernizers" = "modernizers" +"modernizes" = "modernizes" +"modernizing" = "modernizing" +"modularisable" = "modularizable" +"modularisation" = "modularization" +"modularisations" = "modularizations" +"modularise" = "modularize" +"modularised" = "modularized" +"modulariser" = "modularizer" +"modularisers" = "modularizers" +"modularises" = "modularizes" +"modularising" = "modularizing" +"modularizable" = "modularizable" +"modularization" = "modularization" +"modularizations" = "modularizations" +"modularize" = "modularize" +"modularized" = "modularized" +"modularizer" = "modularizer" +"modularizers" = "modularizers" +"modularizes" = "modularizes" +"modularizing" = "modularizing" +"monetisable" = "monetizable" +"monetisation" = "monetization" +"monetisations" = "monetizations" +"monetise" = "monetize" +"monetised" = "monetized" +"monetiser" = "monetizer" +"monetisers" = "monetizers" +"monetises" = "monetizes" +"monetising" = "monetizing" +"monetizable" = "monetizable" +"monetization" = "monetization" +"monetizations" = "monetizations" +"monetize" = "monetize" +"monetized" = "monetized" +"monetizer" = "monetizer" +"monetizers" = "monetizers" +"monetizes" = "monetizes" +"monetizing" = "monetizing" +"monomorphisable" = "monomorphizable" +"monomorphisation" = "monomorphization" +"monomorphisations" = "monomorphizations" +"monomorphise" = "monomorphize" +"monomorphised" = "monomorphized" +"monomorphiser" = "monomorphizer" +"monomorphisers" = "monomorphizers" +"monomorphises" = "monomorphizes" +"monomorphising" = "monomorphizing" +"monomorphizable" = "monomorphizable" +"monomorphization" = "monomorphization" +"monomorphizations" = "monomorphizations" +"monomorphize" = "monomorphize" +"monomorphized" = "monomorphized" +"monomorphizer" = "monomorphizer" +"monomorphizers" = "monomorphizers" +"monomorphizes" = "monomorphizes" +"monomorphizing" = "monomorphizing" +"monopolisable" = "monopolizable" +"monopolisation" = "monopolization" +"monopolisations" = "monopolizations" +"monopolise" = "monopolize" +"monopolised" = "monopolized" +"monopoliser" = "monopolizer" +"monopolisers" = "monopolizers" +"monopolises" = "monopolizes" +"monopolising" = "monopolizing" +"monopolizable" = "monopolizable" +"monopolization" = "monopolization" +"monopolizations" = "monopolizations" +"monopolize" = "monopolize" +"monopolized" = "monopolized" +"monopolizer" = "monopolizer" +"monopolizers" = "monopolizers" +"monopolizes" = "monopolizes" +"monopolizing" = "monopolizing" +"moralisable" = "moralizable" +"moralisation" = "moralization" +"moralisations" = "moralizations" +"moralise" = "moralize" +"moralised" = "moralized" +"moraliser" = "moralizer" +"moralisers" = "moralizers" +"moralises" = "moralizes" +"moralising" = "moralizing" +"moralizable" = "moralizable" +"moralization" = "moralization" +"moralizations" = "moralizations" +"moralize" = "moralize" +"moralized" = "moralized" +"moralizer" = "moralizer" +"moralizers" = "moralizers" +"moralizes" = "moralizes" +"moralizing" = "moralizing" +"neutralisable" = "neutralizable" +"neutralisation" = "neutralization" +"neutralisations" = "neutralizations" +"neutralise" = "neutralize" +"neutralised" = "neutralized" +"neutraliser" = "neutralizer" +"neutralisers" = "neutralizers" +"neutralises" = "neutralizes" +"neutralising" = "neutralizing" +"neutralizable" = "neutralizable" +"neutralization" = "neutralization" +"neutralizations" = "neutralizations" +"neutralize" = "neutralize" +"neutralized" = "neutralized" +"neutralizer" = "neutralizer" +"neutralizers" = "neutralizers" +"neutralizes" = "neutralizes" +"neutralizing" = "neutralizing" +"normalisable" = "normalizable" +"normalisation" = "normalization" +"normalisations" = "normalizations" +"normalise" = "normalize" +"normalised" = "normalized" +"normaliser" = "normalizer" +"normalisers" = "normalizers" +"normalises" = "normalizes" +"normalising" = "normalizing" +"normalizable" = "normalizable" +"normalization" = "normalization" +"normalizations" = "normalizations" +"normalize" = "normalize" +"normalized" = "normalized" +"normalizer" = "normalizer" +"normalizers" = "normalizers" +"normalizes" = "normalizes" +"normalizing" = "normalizing" +"notarisable" = "notarizable" +"notarisation" = "notarization" +"notarisations" = "notarizations" +"notarise" = "notarize" +"notarised" = "notarized" +"notariser" = "notarizer" +"notarisers" = "notarizers" +"notarises" = "notarizes" +"notarising" = "notarizing" +"notarizable" = "notarizable" +"notarization" = "notarization" +"notarizations" = "notarizations" +"notarize" = "notarize" +"notarized" = "notarized" +"notarizer" = "notarizer" +"notarizers" = "notarizers" +"notarizes" = "notarizes" +"notarizing" = "notarizing" +"operationalisable" = "operationalizable" +"operationalisation" = "operationalization" +"operationalisations" = "operationalizations" +"operationalise" = "operationalize" +"operationalised" = "operationalized" +"operationaliser" = "operationalizer" +"operationalisers" = "operationalizers" +"operationalises" = "operationalizes" +"operationalising" = "operationalizing" +"operationalizable" = "operationalizable" +"operationalization" = "operationalization" +"operationalizations" = "operationalizations" +"operationalize" = "operationalize" +"operationalized" = "operationalized" +"operationalizer" = "operationalizer" +"operationalizers" = "operationalizers" +"operationalizes" = "operationalizes" +"operationalizing" = "operationalizing" +"optimisable" = "optimizable" +"optimisation" = "optimization" +"optimisations" = "optimizations" +"optimise" = "optimize" +"optimised" = "optimized" +"optimiser" = "optimizer" +"optimisers" = "optimizers" +"optimises" = "optimizes" +"optimising" = "optimizing" +"optimizable" = "optimizable" +"optimization" = "optimization" +"optimizations" = "optimizations" +"optimize" = "optimize" +"optimized" = "optimized" +"optimizer" = "optimizer" +"optimizers" = "optimizers" +"optimizes" = "optimizes" +"optimizing" = "optimizing" +"ordinalisable" = "ordinalizable" +"ordinalisation" = "ordinalization" +"ordinalisations" = "ordinalizations" +"ordinalise" = "ordinalize" +"ordinalised" = "ordinalized" +"ordinaliser" = "ordinalizer" +"ordinalisers" = "ordinalizers" +"ordinalises" = "ordinalizes" +"ordinalising" = "ordinalizing" +"ordinalizable" = "ordinalizable" +"ordinalization" = "ordinalization" +"ordinalizations" = "ordinalizations" +"ordinalize" = "ordinalize" +"ordinalized" = "ordinalized" +"ordinalizer" = "ordinalizer" +"ordinalizers" = "ordinalizers" +"ordinalizes" = "ordinalizes" +"ordinalizing" = "ordinalizing" +"organisable" = "organizable" +"organisation" = "organization" +"organisations" = "organizations" +"organise" = "organize" +"organised" = "organized" +"organiser" = "organizer" +"organisers" = "organizers" +"organises" = "organizes" +"organising" = "organizing" +"organizable" = "organizable" +"organization" = "organization" +"organizations" = "organizations" +"organize" = "organize" +"organized" = "organized" +"organizer" = "organizer" +"organizers" = "organizers" +"organizes" = "organizes" +"organizing" = "organizing" +"oxendict" = "oxendict" +"palettisable" = "palettizable" +"palettisation" = "palettization" +"palettisations" = "palettizations" +"palettise" = "palettize" +"palettised" = "palettized" +"palettiser" = "palettizer" +"palettisers" = "palettizers" +"palettises" = "palettizes" +"palettising" = "palettizing" +"palettizable" = "palettizable" +"palettization" = "palettization" +"palettizations" = "palettizations" +"palettize" = "palettize" +"palettized" = "palettized" +"palettizer" = "palettizer" +"palettizers" = "palettizers" +"palettizes" = "palettizes" +"palettizing" = "palettizing" +"parallelisable" = "parallelizable" +"parallelisation" = "parallelization" +"parallelisations" = "parallelizations" +"parallelise" = "parallelize" +"parallelised" = "parallelized" +"paralleliser" = "parallelizer" +"parallelisers" = "parallelizers" +"parallelises" = "parallelizes" +"parallelising" = "parallelizing" +"parallelizable" = "parallelizable" +"parallelization" = "parallelization" +"parallelizations" = "parallelizations" +"parallelize" = "parallelize" +"parallelized" = "parallelized" +"parallelizer" = "parallelizer" +"parallelizers" = "parallelizers" +"parallelizes" = "parallelizes" +"parallelizing" = "parallelizing" +"parameterisable" = "parameterizable" +"parameterisation" = "parameterization" +"parameterisations" = "parameterizations" +"parameterise" = "parameterize" +"parameterised" = "parameterized" +"parameteriser" = "parameterizer" +"parameterisers" = "parameterizers" +"parameterises" = "parameterizes" +"parameterising" = "parameterizing" +"parameterizable" = "parameterizable" +"parameterization" = "parameterization" +"parameterizations" = "parameterizations" +"parameterize" = "parameterize" +"parameterized" = "parameterized" +"parameterizer" = "parameterizer" +"parameterizers" = "parameterizers" +"parameterizes" = "parameterizes" +"parameterizing" = "parameterizing" +"parametrisable" = "parametrizable" +"parametrisation" = "parametrization" +"parametrisations" = "parametrizations" +"parametrise" = "parametrize" +"parametrised" = "parametrized" +"parametriser" = "parametrizer" +"parametrisers" = "parametrizers" +"parametrises" = "parametrizes" +"parametrising" = "parametrizing" +"parametrizable" = "parametrizable" +"parametrization" = "parametrization" +"parametrizations" = "parametrizations" +"parametrize" = "parametrize" +"parametrized" = "parametrized" +"parametrizer" = "parametrizer" +"parametrizers" = "parametrizers" +"parametrizes" = "parametrizes" +"parametrizing" = "parametrizing" +"parenthesisable" = "parenthesizable" +"parenthesisation" = "parenthesization" +"parenthesisations" = "parenthesizations" +"parenthesise" = "parenthesize" +"parenthesised" = "parenthesized" +"parenthesiser" = "parenthesizer" +"parenthesisers" = "parenthesizers" +"parenthesises" = "parenthesizes" +"parenthesising" = "parenthesizing" +"parenthesizable" = "parenthesizable" +"parenthesization" = "parenthesization" +"parenthesizations" = "parenthesizations" +"parenthesize" = "parenthesize" +"parenthesized" = "parenthesized" +"parenthesizer" = "parenthesizer" +"parenthesizers" = "parenthesizers" +"parenthesizes" = "parenthesizes" +"parenthesizing" = "parenthesizing" +"penalisable" = "penalizable" +"penalisation" = "penalization" +"penalisations" = "penalizations" +"penalise" = "penalize" +"penalised" = "penalized" +"penaliser" = "penalizer" +"penalisers" = "penalizers" +"penalises" = "penalizes" +"penalising" = "penalizing" +"penalizable" = "penalizable" +"penalization" = "penalization" +"penalizations" = "penalizations" +"penalize" = "penalize" +"penalized" = "penalized" +"penalizer" = "penalizer" +"penalizers" = "penalizers" +"penalizes" = "penalizes" +"penalizing" = "penalizing" +"personalisable" = "personalizable" +"personalisation" = "personalization" +"personalisations" = "personalizations" +"personalise" = "personalize" +"personalised" = "personalized" +"personaliser" = "personalizer" +"personalisers" = "personalizers" +"personalises" = "personalizes" +"personalising" = "personalizing" +"personalizable" = "personalizable" +"personalization" = "personalization" +"personalizations" = "personalizations" +"personalize" = "personalize" +"personalized" = "personalized" +"personalizer" = "personalizer" +"personalizers" = "personalizers" +"personalizes" = "personalizes" +"personalizing" = "personalizing" +"pluralisable" = "pluralizable" +"pluralisation" = "pluralization" +"pluralisations" = "pluralizations" +"pluralise" = "pluralize" +"pluralised" = "pluralized" +"pluraliser" = "pluralizer" +"pluralisers" = "pluralizers" +"pluralises" = "pluralizes" +"pluralising" = "pluralizing" +"pluralizable" = "pluralizable" +"pluralization" = "pluralization" +"pluralizations" = "pluralizations" +"pluralize" = "pluralize" +"pluralized" = "pluralized" +"pluralizer" = "pluralizer" +"pluralizers" = "pluralizers" +"pluralizes" = "pluralizes" +"pluralizing" = "pluralizing" +"popularisable" = "popularizable" +"popularisation" = "popularization" +"popularisations" = "popularizations" +"popularise" = "popularize" +"popularised" = "popularized" +"populariser" = "popularizer" +"popularisers" = "popularizers" +"popularises" = "popularizes" +"popularising" = "popularizing" +"popularizable" = "popularizable" +"popularization" = "popularization" +"popularizations" = "popularizations" +"popularize" = "popularize" +"popularized" = "popularized" +"popularizer" = "popularizer" +"popularizers" = "popularizers" +"popularizes" = "popularizes" +"popularizing" = "popularizing" +"prioritisable" = "prioritizable" +"prioritisation" = "prioritization" +"prioritisations" = "prioritizations" +"prioritise" = "prioritize" +"prioritised" = "prioritized" +"prioritiser" = "prioritizer" +"prioritisers" = "prioritizers" +"prioritises" = "prioritizes" +"prioritising" = "prioritizing" +"prioritizable" = "prioritizable" +"prioritization" = "prioritization" +"prioritizations" = "prioritizations" +"prioritize" = "prioritize" +"prioritized" = "prioritized" +"prioritizer" = "prioritizer" +"prioritizers" = "prioritizers" +"prioritizes" = "prioritizes" +"prioritizing" = "prioritizing" +"privatisable" = "privatizable" +"privatisation" = "privatization" +"privatisations" = "privatizations" +"privatise" = "privatize" +"privatised" = "privatized" +"privatiser" = "privatizer" +"privatisers" = "privatizers" +"privatises" = "privatizes" +"privatising" = "privatizing" +"privatizable" = "privatizable" +"privatization" = "privatization" +"privatizations" = "privatizations" +"privatize" = "privatize" +"privatized" = "privatized" +"privatizer" = "privatizer" +"privatizers" = "privatizers" +"privatizes" = "privatizes" +"privatizing" = "privatizing" +"productisable" = "productizable" +"productisation" = "productization" +"productisations" = "productizations" +"productise" = "productize" +"productised" = "productized" +"productiser" = "productizer" +"productisers" = "productizers" +"productises" = "productizes" +"productising" = "productizing" +"productizable" = "productizable" +"productization" = "productization" +"productizations" = "productizations" +"productize" = "productize" +"productized" = "productized" +"productizer" = "productizer" +"productizers" = "productizers" +"productizes" = "productizes" +"productizing" = "productizing" +"publicisable" = "publicizable" +"publicisation" = "publicization" +"publicisations" = "publicizations" +"publicise" = "publicize" +"publicised" = "publicized" +"publiciser" = "publicizer" +"publicisers" = "publicizers" +"publicises" = "publicizes" +"publicising" = "publicizing" +"publicizable" = "publicizable" +"publicization" = "publicization" +"publicizations" = "publicizations" +"publicize" = "publicize" +"publicized" = "publicized" +"publicizer" = "publicizer" +"publicizers" = "publicizers" +"publicizes" = "publicizes" +"publicizing" = "publicizing" +"quantisable" = "quantizable" +"quantisation" = "quantization" +"quantisations" = "quantizations" +"quantise" = "quantize" +"quantised" = "quantized" +"quantiser" = "quantizer" +"quantisers" = "quantizers" +"quantises" = "quantizes" +"quantising" = "quantizing" +"quantizable" = "quantizable" +"quantization" = "quantization" +"quantizations" = "quantizations" +"quantize" = "quantize" +"quantized" = "quantized" +"quantizer" = "quantizer" +"quantizers" = "quantizers" +"quantizes" = "quantizes" +"quantizing" = "quantizing" +"randomisable" = "randomizable" +"randomisation" = "randomization" +"randomisations" = "randomizations" +"randomise" = "randomize" +"randomised" = "randomized" +"randomiser" = "randomizer" +"randomisers" = "randomizers" +"randomises" = "randomizes" +"randomising" = "randomizing" +"randomizable" = "randomizable" +"randomization" = "randomization" +"randomizations" = "randomizations" +"randomize" = "randomize" +"randomized" = "randomized" +"randomizer" = "randomizer" +"randomizers" = "randomizers" +"randomizes" = "randomizes" +"randomizing" = "randomizing" +"rasterisable" = "rasterizable" +"rasterisation" = "rasterization" +"rasterisations" = "rasterizations" +"rasterise" = "rasterize" +"rasterised" = "rasterized" +"rasteriser" = "rasterizer" +"rasterisers" = "rasterizers" +"rasterises" = "rasterizes" +"rasterising" = "rasterizing" +"rasterizable" = "rasterizable" +"rasterization" = "rasterization" +"rasterizations" = "rasterizations" +"rasterize" = "rasterize" +"rasterized" = "rasterized" +"rasterizer" = "rasterizer" +"rasterizers" = "rasterizers" +"rasterizes" = "rasterizes" +"rasterizing" = "rasterizing" +"rationalisable" = "rationalizable" +"rationalisation" = "rationalization" +"rationalisations" = "rationalizations" +"rationalise" = "rationalize" +"rationalised" = "rationalized" +"rationaliser" = "rationalizer" +"rationalisers" = "rationalizers" +"rationalises" = "rationalizes" +"rationalising" = "rationalizing" +"rationalizable" = "rationalizable" +"rationalization" = "rationalization" +"rationalizations" = "rationalizations" +"rationalize" = "rationalize" +"rationalized" = "rationalized" +"rationalizer" = "rationalizer" +"rationalizers" = "rationalizers" +"rationalizes" = "rationalizes" +"rationalizing" = "rationalizing" +"realisable" = "realizable" +"realisation" = "realization" +"realisations" = "realizations" +"realise" = "realize" +"realised" = "realized" +"realiser" = "realizer" +"realisers" = "realizers" +"realises" = "realizes" +"realising" = "realizing" +"realizable" = "realizable" +"realization" = "realization" +"realizations" = "realizations" +"realize" = "realize" +"realized" = "realized" +"realizer" = "realizer" +"realizers" = "realizers" +"realizes" = "realizes" +"realizing" = "realizing" +"recognisable" = "recognizable" +"recognisation" = "recognization" +"recognisations" = "recognizations" +"recognise" = "recognize" +"recognised" = "recognized" +"recogniser" = "recognizer" +"recognisers" = "recognizers" +"recognises" = "recognizes" +"recognising" = "recognizing" +"recognizable" = "recognizable" +"recognization" = "recognization" +"recognizations" = "recognizations" +"recognize" = "recognize" +"recognized" = "recognized" +"recognizer" = "recognizer" +"recognizers" = "recognizers" +"recognizes" = "recognizes" +"recognizing" = "recognizing" +"regularisable" = "regularizable" +"regularisation" = "regularization" +"regularisations" = "regularizations" +"regularise" = "regularize" +"regularised" = "regularized" +"regulariser" = "regularizer" +"regularisers" = "regularizers" +"regularises" = "regularizes" +"regularising" = "regularizing" +"regularizable" = "regularizable" +"regularization" = "regularization" +"regularizations" = "regularizations" +"regularize" = "regularize" +"regularized" = "regularized" +"regularizer" = "regularizer" +"regularizers" = "regularizers" +"regularizes" = "regularizes" +"regularizing" = "regularizing" +"reinitialisable" = "reinitializable" +"reinitialisation" = "reinitialization" +"reinitialisations" = "reinitializations" +"reinitialise" = "reinitialize" +"reinitialised" = "reinitialized" +"reinitialiser" = "reinitializer" +"reinitialisers" = "reinitializers" +"reinitialises" = "reinitializes" +"reinitialising" = "reinitializing" +"reinitializable" = "reinitializable" +"reinitialization" = "reinitialization" +"reinitializations" = "reinitializations" +"reinitialize" = "reinitialize" +"reinitialized" = "reinitialized" +"reinitializer" = "reinitializer" +"reinitializers" = "reinitializers" +"reinitializes" = "reinitializes" +"reinitializing" = "reinitializing" +"reorganisable" = "reorganizable" +"reorganisation" = "reorganization" +"reorganisations" = "reorganizations" +"reorganise" = "reorganize" +"reorganised" = "reorganized" +"reorganiser" = "reorganizer" +"reorganisers" = "reorganizers" +"reorganises" = "reorganizes" +"reorganising" = "reorganizing" +"reorganizable" = "reorganizable" +"reorganization" = "reorganization" +"reorganizations" = "reorganizations" +"reorganize" = "reorganize" +"reorganized" = "reorganized" +"reorganizer" = "reorganizer" +"reorganizers" = "reorganizers" +"reorganizes" = "reorganizes" +"reorganizing" = "reorganizing" +"reserialisable" = "reserializable" +"reserialisation" = "reserialization" +"reserialisations" = "reserializations" +"reserialise" = "reserialize" +"reserialised" = "reserialized" +"reserialiser" = "reserializer" +"reserialisers" = "reserializers" +"reserialises" = "reserializes" +"reserialising" = "reserializing" +"reserializable" = "reserializable" +"reserialization" = "reserialization" +"reserializations" = "reserializations" +"reserialize" = "reserialize" +"reserialized" = "reserialized" +"reserializer" = "reserializer" +"reserializers" = "reserializers" +"reserializes" = "reserializes" +"reserializing" = "reserializing" +"resynchronisable" = "resynchronizable" +"resynchronisation" = "resynchronization" +"resynchronisations" = "resynchronizations" +"resynchronise" = "resynchronize" +"resynchronised" = "resynchronized" +"resynchroniser" = "resynchronizer" +"resynchronisers" = "resynchronizers" +"resynchronises" = "resynchronizes" +"resynchronising" = "resynchronizing" +"resynchronizable" = "resynchronizable" +"resynchronization" = "resynchronization" +"resynchronizations" = "resynchronizations" +"resynchronize" = "resynchronize" +"resynchronized" = "resynchronized" +"resynchronizer" = "resynchronizer" +"resynchronizers" = "resynchronizers" +"resynchronizes" = "resynchronizes" +"resynchronizing" = "resynchronizing" +"retokenisable" = "retokenizable" +"retokenisation" = "retokenization" +"retokenisations" = "retokenizations" +"retokenise" = "retokenize" +"retokenised" = "retokenized" +"retokeniser" = "retokenizer" +"retokenisers" = "retokenizers" +"retokenises" = "retokenizes" +"retokenising" = "retokenizing" +"retokenizable" = "retokenizable" +"retokenization" = "retokenization" +"retokenizations" = "retokenizations" +"retokenize" = "retokenize" +"retokenized" = "retokenized" +"retokenizer" = "retokenizer" +"retokenizers" = "retokenizers" +"retokenizes" = "retokenizes" +"retokenizing" = "retokenizing" +"romanticisable" = "romanticizable" +"romanticisation" = "romanticization" +"romanticisations" = "romanticizations" +"romanticise" = "romanticize" +"romanticised" = "romanticized" +"romanticiser" = "romanticizer" +"romanticisers" = "romanticizers" +"romanticises" = "romanticizes" +"romanticising" = "romanticizing" +"romanticizable" = "romanticizable" +"romanticization" = "romanticization" +"romanticizations" = "romanticizations" +"romanticize" = "romanticize" +"romanticized" = "romanticized" +"romanticizer" = "romanticizer" +"romanticizers" = "romanticizers" +"romanticizes" = "romanticizes" +"romanticizing" = "romanticizing" +"sanitisable" = "sanitizable" +"sanitisation" = "sanitization" +"sanitisations" = "sanitizations" +"sanitise" = "sanitize" +"sanitised" = "sanitized" +"sanitiser" = "sanitizer" +"sanitisers" = "sanitizers" +"sanitises" = "sanitizes" +"sanitising" = "sanitizing" +"sanitizable" = "sanitizable" +"sanitization" = "sanitization" +"sanitizations" = "sanitizations" +"sanitize" = "sanitize" +"sanitized" = "sanitized" +"sanitizer" = "sanitizer" +"sanitizers" = "sanitizers" +"sanitizes" = "sanitizes" +"sanitizing" = "sanitizing" +"scrutinisable" = "scrutinizable" +"scrutinisation" = "scrutinization" +"scrutinisations" = "scrutinizations" +"scrutinise" = "scrutinize" +"scrutinised" = "scrutinized" +"scrutiniser" = "scrutinizer" +"scrutinisers" = "scrutinizers" +"scrutinises" = "scrutinizes" +"scrutinising" = "scrutinizing" +"scrutinizable" = "scrutinizable" +"scrutinization" = "scrutinization" +"scrutinizations" = "scrutinizations" +"scrutinize" = "scrutinize" +"scrutinized" = "scrutinized" +"scrutinizer" = "scrutinizer" +"scrutinizers" = "scrutinizers" +"scrutinizes" = "scrutinizes" +"scrutinizing" = "scrutinizing" +"serialisable" = "serializable" +"serialisation" = "serialization" +"serialisations" = "serializations" +"serialise" = "serialize" +"serialised" = "serialized" +"serialiser" = "serializer" +"serialisers" = "serializers" +"serialises" = "serializes" +"serialising" = "serializing" +"serializable" = "serializable" +"serialization" = "serialization" +"serializations" = "serializations" +"serialize" = "serialize" +"serialized" = "serialized" +"serializer" = "serializer" +"serializers" = "serializers" +"serializes" = "serializes" +"serializing" = "serializing" +"sexualisable" = "sexualizable" +"sexualisation" = "sexualization" +"sexualisations" = "sexualizations" +"sexualise" = "sexualize" +"sexualised" = "sexualized" +"sexualiser" = "sexualizer" +"sexualisers" = "sexualizers" +"sexualises" = "sexualizes" +"sexualising" = "sexualizing" +"sexualizable" = "sexualizable" +"sexualization" = "sexualization" +"sexualizations" = "sexualizations" +"sexualize" = "sexualize" +"sexualized" = "sexualized" +"sexualizer" = "sexualizer" +"sexualizers" = "sexualizers" +"sexualizes" = "sexualizes" +"sexualizing" = "sexualizing" +"singularisable" = "singularizable" +"singularisation" = "singularization" +"singularisations" = "singularizations" +"singularise" = "singularize" +"singularised" = "singularized" +"singulariser" = "singularizer" +"singularisers" = "singularizers" +"singularises" = "singularizes" +"singularising" = "singularizing" +"singularizable" = "singularizable" +"singularization" = "singularization" +"singularizations" = "singularizations" +"singularize" = "singularize" +"singularized" = "singularized" +"singularizer" = "singularizer" +"singularizers" = "singularizers" +"singularizes" = "singularizes" +"singularizing" = "singularizing" +"socialisable" = "socializable" +"socialisation" = "socialization" +"socialisations" = "socializations" +"socialise" = "socialize" +"socialised" = "socialized" +"socialiser" = "socializer" +"socialisers" = "socializers" +"socialises" = "socializes" +"socialising" = "socializing" +"socializable" = "socializable" +"socialization" = "socialization" +"socializations" = "socializations" +"socialize" = "socialize" +"socialized" = "socialized" +"socializer" = "socializer" +"socializers" = "socializers" +"socializes" = "socializes" +"socializing" = "socializing" +"specialisable" = "specializable" +"specialisation" = "specialization" +"specialisations" = "specializations" +"specialise" = "specialize" +"specialised" = "specialized" +"specialiser" = "specializer" +"specialisers" = "specializers" +"specialises" = "specializes" +"specialising" = "specializing" +"specializable" = "specializable" +"specialization" = "specialization" +"specializations" = "specializations" +"specialize" = "specialize" +"specialized" = "specialized" +"specializer" = "specializer" +"specializers" = "specializers" +"specializes" = "specializes" +"specializing" = "specializing" +"stabilisable" = "stabilizable" +"stabilisation" = "stabilization" +"stabilisations" = "stabilizations" +"stabilise" = "stabilize" +"stabilised" = "stabilized" +"stabiliser" = "stabilizer" +"stabilisers" = "stabilizers" +"stabilises" = "stabilizes" +"stabilising" = "stabilizing" +"stabilizable" = "stabilizable" +"stabilization" = "stabilization" +"stabilizations" = "stabilizations" +"stabilize" = "stabilize" +"stabilized" = "stabilized" +"stabilizer" = "stabilizer" +"stabilizers" = "stabilizers" +"stabilizes" = "stabilizes" +"stabilizing" = "stabilizing" +"standardisable" = "standardizable" +"standardisation" = "standardization" +"standardisations" = "standardizations" +"standardise" = "standardize" +"standardised" = "standardized" +"standardiser" = "standardizer" +"standardisers" = "standardizers" +"standardises" = "standardizes" +"standardising" = "standardizing" +"standardizable" = "standardizable" +"standardization" = "standardization" +"standardizations" = "standardizations" +"standardize" = "standardize" +"standardized" = "standardized" +"standardizer" = "standardizer" +"standardizers" = "standardizers" +"standardizes" = "standardizes" +"standardizing" = "standardizing" +"stylisable" = "stylizable" +"stylisation" = "stylization" +"stylisations" = "stylizations" +"stylise" = "stylize" +"stylised" = "stylized" +"styliser" = "stylizer" +"stylisers" = "stylizers" +"stylises" = "stylizes" +"stylising" = "stylizing" +"stylizable" = "stylizable" +"stylization" = "stylization" +"stylizations" = "stylizations" +"stylize" = "stylize" +"stylized" = "stylized" +"stylizer" = "stylizer" +"stylizers" = "stylizers" +"stylizes" = "stylizes" +"stylizing" = "stylizing" +"subsidisable" = "subsidizable" +"subsidisation" = "subsidization" +"subsidisations" = "subsidizations" +"subsidise" = "subsidize" +"subsidised" = "subsidized" +"subsidiser" = "subsidizer" +"subsidisers" = "subsidizers" +"subsidises" = "subsidizes" +"subsidising" = "subsidizing" +"subsidizable" = "subsidizable" +"subsidization" = "subsidization" +"subsidizations" = "subsidizations" +"subsidize" = "subsidize" +"subsidized" = "subsidized" +"subsidizer" = "subsidizer" +"subsidizers" = "subsidizers" +"subsidizes" = "subsidizes" +"subsidizing" = "subsidizing" +"summarisable" = "summarizable" +"summarisation" = "summarization" +"summarisations" = "summarizations" +"summarise" = "summarize" +"summarised" = "summarized" +"summariser" = "summarizer" +"summarisers" = "summarizers" +"summarises" = "summarizes" +"summarising" = "summarizing" +"summarizable" = "summarizable" +"summarization" = "summarization" +"summarizations" = "summarizations" +"summarize" = "summarize" +"summarized" = "summarized" +"summarizer" = "summarizer" +"summarizers" = "summarizers" +"summarizes" = "summarizes" +"summarizing" = "summarizing" +"symbolisable" = "symbolizable" +"symbolisation" = "symbolization" +"symbolisations" = "symbolizations" +"symbolise" = "symbolize" +"symbolised" = "symbolized" +"symboliser" = "symbolizer" +"symbolisers" = "symbolizers" +"symbolises" = "symbolizes" +"symbolising" = "symbolizing" +"symbolizable" = "symbolizable" +"symbolization" = "symbolization" +"symbolizations" = "symbolizations" +"symbolize" = "symbolize" +"symbolized" = "symbolized" +"symbolizer" = "symbolizer" +"symbolizers" = "symbolizers" +"symbolizes" = "symbolizes" +"symbolizing" = "symbolizing" +"synchronisable" = "synchronizable" +"synchronisation" = "synchronization" +"synchronisations" = "synchronizations" +"synchronise" = "synchronize" +"synchronised" = "synchronized" +"synchroniser" = "synchronizer" +"synchronisers" = "synchronizers" +"synchronises" = "synchronizes" +"synchronising" = "synchronizing" +"synchronizable" = "synchronizable" +"synchronization" = "synchronization" +"synchronizations" = "synchronizations" +"synchronize" = "synchronize" +"synchronized" = "synchronized" +"synchronizer" = "synchronizer" +"synchronizers" = "synchronizers" +"synchronizes" = "synchronizes" +"synchronizing" = "synchronizing" +"synthesisable" = "synthesizable" +"synthesisation" = "synthesization" +"synthesisations" = "synthesizations" +"synthesise" = "synthesize" +"synthesised" = "synthesized" +"synthesiser" = "synthesizer" +"synthesisers" = "synthesizers" +"synthesises" = "synthesizes" +"synthesising" = "synthesizing" +"synthesizable" = "synthesizable" +"synthesization" = "synthesization" +"synthesizations" = "synthesizations" +"synthesize" = "synthesize" +"synthesized" = "synthesized" +"synthesizer" = "synthesizer" +"synthesizers" = "synthesizers" +"synthesizes" = "synthesizes" +"synthesizing" = "synthesizing" +"systematisable" = "systematizable" +"systematisation" = "systematization" +"systematisations" = "systematizations" +"systematise" = "systematize" +"systematised" = "systematized" +"systematiser" = "systematizer" +"systematisers" = "systematizers" +"systematises" = "systematizes" +"systematising" = "systematizing" +"systematizable" = "systematizable" +"systematization" = "systematization" +"systematizations" = "systematizations" +"systematize" = "systematize" +"systematized" = "systematized" +"systematizer" = "systematizer" +"systematizers" = "systematizers" +"systematizes" = "systematizes" +"systematizing" = "systematizing" +"systemisable" = "systemizable" +"systemisation" = "systemization" +"systemisations" = "systemizations" +"systemise" = "systemize" +"systemised" = "systemized" +"systemiser" = "systemizer" +"systemisers" = "systemizers" +"systemises" = "systemizes" +"systemising" = "systemizing" +"systemizable" = "systemizable" +"systemization" = "systemization" +"systemizations" = "systemizations" +"systemize" = "systemize" +"systemized" = "systemized" +"systemizer" = "systemizer" +"systemizers" = "systemizers" +"systemizes" = "systemizes" +"systemizing" = "systemizing" +"templatisable" = "templatizable" +"templatisation" = "templatization" +"templatisations" = "templatizations" +"templatise" = "templatize" +"templatised" = "templatized" +"templatiser" = "templatizer" +"templatisers" = "templatizers" +"templatises" = "templatizes" +"templatising" = "templatizing" +"templatizable" = "templatizable" +"templatization" = "templatization" +"templatizations" = "templatizations" +"templatize" = "templatize" +"templatized" = "templatized" +"templatizer" = "templatizer" +"templatizers" = "templatizers" +"templatizes" = "templatizes" +"templatizing" = "templatizing" +"terminalisable" = "terminalizable" +"terminalisation" = "terminalization" +"terminalisations" = "terminalizations" +"terminalise" = "terminalize" +"terminalised" = "terminalized" +"terminaliser" = "terminalizer" +"terminalisers" = "terminalizers" +"terminalises" = "terminalizes" +"terminalising" = "terminalizing" +"terminalizable" = "terminalizable" +"terminalization" = "terminalization" +"terminalizations" = "terminalizations" +"terminalize" = "terminalize" +"terminalized" = "terminalized" +"terminalizer" = "terminalizer" +"terminalizers" = "terminalizers" +"terminalizes" = "terminalizes" +"terminalizing" = "terminalizing" +"theorisable" = "theorizable" +"theorisation" = "theorization" +"theorisations" = "theorizations" +"theorise" = "theorize" +"theorised" = "theorized" +"theoriser" = "theorizer" +"theorisers" = "theorizers" +"theorises" = "theorizes" +"theorising" = "theorizing" +"theorizable" = "theorizable" +"theorization" = "theorization" +"theorizations" = "theorizations" +"theorize" = "theorize" +"theorized" = "theorized" +"theorizer" = "theorizer" +"theorizers" = "theorizers" +"theorizes" = "theorizes" +"theorizing" = "theorizing" +"tokenisable" = "tokenizable" +"tokenisation" = "tokenization" +"tokenisations" = "tokenizations" +"tokenise" = "tokenize" +"tokenised" = "tokenized" +"tokeniser" = "tokenizer" +"tokenisers" = "tokenizers" +"tokenises" = "tokenizes" +"tokenising" = "tokenizing" +"tokenizable" = "tokenizable" +"tokenization" = "tokenization" +"tokenizations" = "tokenizations" +"tokenize" = "tokenize" +"tokenized" = "tokenized" +"tokenizer" = "tokenizer" +"tokenizers" = "tokenizers" +"tokenizes" = "tokenizes" +"tokenizing" = "tokenizing" +"trivialisable" = "trivializable" +"trivialisation" = "trivialization" +"trivialisations" = "trivializations" +"trivialise" = "trivialize" +"trivialised" = "trivialized" +"trivialiser" = "trivializer" +"trivialisers" = "trivializers" +"trivialises" = "trivializes" +"trivialising" = "trivializing" +"trivializable" = "trivializable" +"trivialization" = "trivialization" +"trivializations" = "trivializations" +"trivialize" = "trivialize" +"trivialized" = "trivialized" +"trivializer" = "trivializer" +"trivializers" = "trivializers" +"trivializes" = "trivializes" +"trivializing" = "trivializing" +"unauthorisable" = "unauthorizable" +"unauthorisation" = "unauthorization" +"unauthorisations" = "unauthorizations" +"unauthorise" = "unauthorize" +"unauthorised" = "unauthorized" +"unauthoriser" = "unauthorizer" +"unauthorisers" = "unauthorizers" +"unauthorises" = "unauthorizes" +"unauthorising" = "unauthorizing" +"unauthorizable" = "unauthorizable" +"unauthorization" = "unauthorization" +"unauthorizations" = "unauthorizations" +"unauthorize" = "unauthorize" +"unauthorized" = "unauthorized" +"unauthorizer" = "unauthorizer" +"unauthorizers" = "unauthorizers" +"unauthorizes" = "unauthorizes" +"unauthorizing" = "unauthorizing" +"uncategorisable" = "uncategorizable" +"uncategorisation" = "uncategorization" +"uncategorisations" = "uncategorizations" +"uncategorise" = "uncategorize" +"uncategorised" = "uncategorized" +"uncategoriser" = "uncategorizer" +"uncategorisers" = "uncategorizers" +"uncategorises" = "uncategorizes" +"uncategorising" = "uncategorizing" +"uncategorizable" = "uncategorizable" +"uncategorization" = "uncategorization" +"uncategorizations" = "uncategorizations" +"uncategorize" = "uncategorize" +"uncategorized" = "uncategorized" +"uncategorizer" = "uncategorizer" +"uncategorizers" = "uncategorizers" +"uncategorizes" = "uncategorizes" +"uncategorizing" = "uncategorizing" +"uninitialisable" = "uninitializable" +"uninitialisation" = "uninitialization" +"uninitialisations" = "uninitializations" +"uninitialise" = "uninitialize" +"uninitialised" = "uninitialized" +"uninitialiser" = "uninitializer" +"uninitialisers" = "uninitializers" +"uninitialises" = "uninitializes" +"uninitialising" = "uninitializing" +"uninitializable" = "uninitializable" +"uninitialization" = "uninitialization" +"uninitializations" = "uninitializations" +"uninitialize" = "uninitialize" +"uninitialized" = "uninitialized" +"uninitializer" = "uninitializer" +"uninitializers" = "uninitializers" +"uninitializes" = "uninitializes" +"uninitializing" = "uninitializing" +"unlocalisable" = "unlocalizable" +"unlocalisation" = "unlocalization" +"unlocalisations" = "unlocalizations" +"unlocalise" = "unlocalize" +"unlocalised" = "unlocalized" +"unlocaliser" = "unlocalizer" +"unlocalisers" = "unlocalizers" +"unlocalises" = "unlocalizes" +"unlocalising" = "unlocalizing" +"unlocalizable" = "unlocalizable" +"unlocalization" = "unlocalization" +"unlocalizations" = "unlocalizations" +"unlocalize" = "unlocalize" +"unlocalized" = "unlocalized" +"unlocalizer" = "unlocalizer" +"unlocalizers" = "unlocalizers" +"unlocalizes" = "unlocalizes" +"unlocalizing" = "unlocalizing" +"unoptimisable" = "unoptimizable" +"unoptimisation" = "unoptimization" +"unoptimisations" = "unoptimizations" +"unoptimise" = "unoptimize" +"unoptimised" = "unoptimized" +"unoptimiser" = "unoptimizer" +"unoptimisers" = "unoptimizers" +"unoptimises" = "unoptimizes" +"unoptimising" = "unoptimizing" +"unoptimizable" = "unoptimizable" +"unoptimization" = "unoptimization" +"unoptimizations" = "unoptimizations" +"unoptimize" = "unoptimize" +"unoptimized" = "unoptimized" +"unoptimizer" = "unoptimizer" +"unoptimizers" = "unoptimizers" +"unoptimizes" = "unoptimizes" +"unoptimizing" = "unoptimizing" +"unparameterisable" = "unparameterizable" +"unparameterisation" = "unparameterization" +"unparameterisations" = "unparameterizations" +"unparameterise" = "unparameterize" +"unparameterised" = "unparameterized" +"unparameteriser" = "unparameterizer" +"unparameterisers" = "unparameterizers" +"unparameterises" = "unparameterizes" +"unparameterising" = "unparameterizing" +"unparameterizable" = "unparameterizable" +"unparameterization" = "unparameterization" +"unparameterizations" = "unparameterizations" +"unparameterize" = "unparameterize" +"unparameterized" = "unparameterized" +"unparameterizer" = "unparameterizer" +"unparameterizers" = "unparameterizers" +"unparameterizes" = "unparameterizes" +"unparameterizing" = "unparameterizing" +"unrecognisable" = "unrecognizable" +"unrecognisation" = "unrecognization" +"unrecognisations" = "unrecognizations" +"unrecognise" = "unrecognize" +"unrecognised" = "unrecognized" +"unrecogniser" = "unrecognizer" +"unrecognisers" = "unrecognizers" +"unrecognises" = "unrecognizes" +"unrecognising" = "unrecognizing" +"unrecognizable" = "unrecognizable" +"unrecognization" = "unrecognization" +"unrecognizations" = "unrecognizations" +"unrecognize" = "unrecognize" +"unrecognized" = "unrecognized" +"unrecognizer" = "unrecognizer" +"unrecognizers" = "unrecognizers" +"unrecognizes" = "unrecognizes" +"unrecognizing" = "unrecognizing" +"unsynchronisable" = "unsynchronizable" +"unsynchronisation" = "unsynchronization" +"unsynchronisations" = "unsynchronizations" +"unsynchronise" = "unsynchronize" +"unsynchronised" = "unsynchronized" +"unsynchroniser" = "unsynchronizer" +"unsynchronisers" = "unsynchronizers" +"unsynchronises" = "unsynchronizes" +"unsynchronising" = "unsynchronizing" +"unsynchronizable" = "unsynchronizable" +"unsynchronization" = "unsynchronization" +"unsynchronizations" = "unsynchronizations" +"unsynchronize" = "unsynchronize" +"unsynchronized" = "unsynchronized" +"unsynchronizer" = "unsynchronizer" +"unsynchronizers" = "unsynchronizers" +"unsynchronizes" = "unsynchronizes" +"unsynchronizing" = "unsynchronizing" +"utilisable" = "utilizable" +"utilisation" = "utilization" +"utilisations" = "utilizations" +"utilise" = "utilize" +"utilised" = "utilized" +"utiliser" = "utilizer" +"utilisers" = "utilizers" +"utilises" = "utilizes" +"utilising" = "utilizing" +"utilizable" = "utilizable" +"utilization" = "utilization" +"utilizations" = "utilizations" +"utilize" = "utilize" +"utilized" = "utilized" +"utilizer" = "utilizer" +"utilizers" = "utilizers" +"utilizes" = "utilizes" +"utilizing" = "utilizing" +"vectorisable" = "vectorizable" +"vectorisation" = "vectorization" +"vectorisations" = "vectorizations" +"vectorise" = "vectorize" +"vectorised" = "vectorized" +"vectoriser" = "vectorizer" +"vectorisers" = "vectorizers" +"vectorises" = "vectorizes" +"vectorising" = "vectorizing" +"vectorizable" = "vectorizable" +"vectorization" = "vectorization" +"vectorizations" = "vectorizations" +"vectorize" = "vectorize" +"vectorized" = "vectorized" +"vectorizer" = "vectorizer" +"vectorizers" = "vectorizers" +"vectorizes" = "vectorizes" +"vectorizing" = "vectorizing" +"virtualisable" = "virtualizable" +"virtualisation" = "virtualization" +"virtualisations" = "virtualizations" +"virtualise" = "virtualize" +"virtualised" = "virtualized" +"virtualiser" = "virtualizer" +"virtualisers" = "virtualizers" +"virtualises" = "virtualizes" +"virtualising" = "virtualizing" +"virtualizable" = "virtualizable" +"virtualization" = "virtualization" +"virtualizations" = "virtualizations" +"virtualize" = "virtualize" +"virtualized" = "virtualized" +"virtualizer" = "virtualizer" +"virtualizers" = "virtualizers" +"virtualizes" = "virtualizes" +"virtualizing" = "virtualizing" +"visualisable" = "visualizable" +"visualisation" = "visualization" +"visualisations" = "visualizations" +"visualise" = "visualize" +"visualised" = "visualized" +"visualiser" = "visualizer" +"visualisers" = "visualizers" +"visualises" = "visualizes" +"visualising" = "visualizing" +"visualizable" = "visualizable" +"visualization" = "visualization" +"visualizations" = "visualizations" +"visualize" = "visualize" +"visualized" = "visualized" +"visualizer" = "visualizer" +"visualizers" = "visualizers" +"visualizes" = "visualizes" +"visualizing" = "visualizing" +"weaponisable" = "weaponizable" +"weaponisation" = "weaponization" +"weaponisations" = "weaponizations" +"weaponise" = "weaponize" +"weaponised" = "weaponized" +"weaponiser" = "weaponizer" +"weaponisers" = "weaponizers" +"weaponises" = "weaponizes" +"weaponising" = "weaponizing" +"weaponizable" = "weaponizable" +"weaponization" = "weaponization" +"weaponizations" = "weaponizations" +"weaponize" = "weaponize" +"weaponized" = "weaponized" +"weaponizer" = "weaponizer" +"weaponizers" = "weaponizers" +"weaponizes" = "weaponizes" +"weaponizing" = "weaponizing" +"yse" = "yse" +"zeroisable" = "zeroizable" +"zeroisation" = "zeroization" +"zeroisations" = "zeroizations" +"zeroise" = "zeroize" +"zeroised" = "zeroized" +"zeroiser" = "zeroizer" +"zeroisers" = "zeroizers" +"zeroises" = "zeroizes" +"zeroising" = "zeroizing" +"zeroizable" = "zeroizable" +"zeroization" = "zeroization" +"zeroizations" = "zeroizations" +"zeroize" = "zeroize" +"zeroized" = "zeroized" +"zeroizer" = "zeroizer" +"zeroizers" = "zeroizers" +"zeroizes" = "zeroizes" +"zeroizing" = "zeroizing" diff --git a/tests/__snapshots__/test_template.ambr b/tests/__snapshots__/test_template.ambr index eee44c2..501e825 100644 --- a/tests/__snapshots__/test_template.ambr +++ b/tests/__snapshots__/test_template.ambr @@ -54,7 +54,8 @@ lint-python Run Python linters typecheck Run typechecking audit Audit dependencies for known vulnerabilities - markdownlint Lint Markdown files + markdownlint Lint Markdown files and spelling + spelling Enforce en-GB-oxendict spelling nixie Validate Mermaid diagrams test Run tests help Show available targets diff --git a/tests/helpers/agents_contracts.py b/tests/helpers/agents_contracts.py index b1e321a..afdebe5 100644 --- a/tests/helpers/agents_contracts.py +++ b/tests/helpers/agents_contracts.py @@ -64,6 +64,7 @@ def _assert_agents_make_targets_mirror_makefile( "lint", "markdownlint", "nixie", + "spelling", "test", "typecheck", } @@ -110,6 +111,11 @@ def _assert_documented_command_flags( ("AGENTS.md", "pip-audit"), ("Makefile", "pip-audit"), ], + "spelling": [ + ("AGENTS.md", "make spelling"), + ("Makefile", "generate_typos_config.py"), + ("Makefile", "--config typos.toml --force-exclude"), + ], "test": [ ("AGENTS.md", "pytest -v -n $(PYTEST_XDIST_WORKERS)"), ("Makefile", "pytest -v -n auto"), diff --git a/tests/helpers/ci_contracts.py b/tests/helpers/ci_contracts.py index 3511bb7..47981f0 100644 --- a/tests/helpers/ci_contracts.py +++ b/tests/helpers/ci_contracts.py @@ -128,6 +128,9 @@ def _assert_ci_workflow_contracts( assert "make typecheck" in ci_workflow, ( "expected generated CI workflow to run the typecheck gate" ) + assert "make spelling" in ci_workflow, ( + "expected generated CI workflow to run the spelling gate" + ) assert "make audit" in ci_workflow, ( "expected generated CI workflow to run the dependency audit gate" ) diff --git a/tests/helpers/makefile_contracts.py b/tests/helpers/makefile_contracts.py index 8157f0f..46e26f9 100644 --- a/tests/helpers/makefile_contracts.py +++ b/tests/helpers/makefile_contracts.py @@ -43,6 +43,14 @@ def assert_common_make_targets(makefile: str) -> None: assert "lint-python: build" in makefile, "Makefile should expose lint-python" assert "lint: lint-python" in makefile, "lint should delegate to lint-python" assert "audit: build" in makefile, "Makefile should expose audit" + assert "spelling:" in makefile, "Makefile should expose spelling" + assert "TYPOS_VERSION ?= 1.48.0" in makefile, "Makefile should pin typos" + assert "scripts/generate_typos_config.py" in makefile, ( + "spelling should generate configuration" + ) + assert "--config typos.toml --force-exclude" in makefile, ( + "spelling should apply generated configuration and exclusions" + ) assert ".uv-cache .uv-tools" in makefile, "clean should remove uv state dirs" @@ -108,6 +116,9 @@ def _assert_makefile_contracts(*, makefile: str, use_rust: bool) -> None: assert "$(UV_ENV) $(UV) run interrogate --fail-under 100" in makefile, ( "expected generated lint target to enforce docstring coverage" ) + assert "+$(MAKE) spelling" in makefile, ( + "expected generated aggregate gate to serialize spelling last" + ) if use_rust: assert "TEST_CMD :=" in makefile, ( "expected Rust variant to select nextest or cargo test" diff --git a/tests/test_helpers.py b/tests/test_helpers.py index e9cca5c..90e3f17 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -305,6 +305,10 @@ def test_common_make_targets_reports_missing_contracts() -> None: "lint-python: build\n" "lint: lint-python\n" "audit: build\n" + "TYPOS_VERSION ?= 1.48.0\n" + "spelling:\n" + "\tuv run scripts/generate_typos_config.py\n" + "\tuv tool run typos --config typos.toml --force-exclude\n" "clean:\n" "\trm -rf .uv-cache .uv-tools\n" ) @@ -441,7 +445,7 @@ def test_parent_makefile_test_target_uses_requisite_pytest_command() -> None: """ makefile = (REPO_ROOT / "Makefile").read_text(encoding="utf-8") - assert ".PHONY: help check-fmt lint test typecheck" in makefile, ( + assert ".PHONY: help check-fmt lint spelling test typecheck" in makefile, ( "expected parent Makefile to mark documented gate targets as phony" ) assert "check-fmt: ## Verify template test formatting" in makefile, ( @@ -463,7 +467,7 @@ def test_parent_makefile_test_target_uses_requisite_pytest_command() -> None: "expected parent Makefile to expose a documented typecheck target" ) assert ( - "$(UV) --with pytest --with pytest-copier --with pyyaml --with syrupy " + "$(UV) --with hypothesis --with pytest --with pytest-copier --with pyyaml --with syrupy " "--with make-parser ty check tests/" in makefile ), "expected parent Makefile typecheck target to run ty with test dependencies" assert "test: ## Run template tests" in makefile, ( @@ -482,11 +486,11 @@ def test_parent_makefile_test_target_uses_requisite_pytest_command() -> None: "expected parent Makefile to map WITH_ACT to act validation" ) assert ( - "$(ACT_TEST_ENV) $(UV) --with pytest-copier --with pyyaml --with syrupy " + "$(ACT_TEST_ENV) $(UV) --with hypothesis --with pytest-copier --with pyyaml --with syrupy " "--with make-parser pytest tests/" in makefile ), ( "expected parent Makefile test target to run pytest through $(UV) with " - "pytest-copier, pyyaml, syrupy, make-parser, and act environment wiring" + "Hypothesis, pytest-copier, pyyaml, syrupy, make-parser, and act environment wiring" ) diff --git a/tests/test_parent_ci.py b/tests/test_parent_ci.py index 19aaf2c..f3629bb 100644 --- a/tests/test_parent_ci.py +++ b/tests/test_parent_ci.py @@ -45,6 +45,9 @@ def test_parent_ci_splits_application_and_act_validation_tests() -> None: assert "make test\n" in ci_workflow, ( "expected parent CI to run the normal parent test gate" ) + assert "make spelling\n" in ci_workflow, ( + "expected parent CI to run the spelling gate" + ) assert "uv tool install mdformat-all" not in ci_workflow, ( "expected parent CI not to install mdformat-all through uv" ) diff --git a/tests/test_template.py b/tests/test_template.py index a266f11..d8a6940 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -80,7 +80,16 @@ def test_python_only_help_output_snapshot( ) help_output = project.run("make help") - for target in ["build", "check-fmt", "lint", "typecheck", "audit", "test", "help"]: + for target in [ + "build", + "check-fmt", + "lint", + "typecheck", + "audit", + "spelling", + "test", + "help", + ]: assert f" {target}" in help_output, ( f"expected generated help output to list the {target!r} target" ) diff --git a/tests/test_typos_rollout.py b/tests/test_typos_rollout.py new file mode 100644 index 0000000..6021557 --- /dev/null +++ b/tests/test_typos_rollout.py @@ -0,0 +1,245 @@ +"""Tests for shared-base ``typos.toml`` generation and consumption.""" + +from __future__ import annotations + +import importlib.util +import json +import os +import pathlib +import re +import shutil +import string +import subprocess # noqa: S404 - runs the pinned, trusted typos binary via uv. +import sys +import tomllib +import typing as typ + +import pytest +from hypothesis import given +from hypothesis import strategies as st + +if typ.TYPE_CHECKING: + import types + +REPOSITORY_ROOT = pathlib.Path(__file__).resolve().parents[1] +SCRIPTS_ROOT = REPOSITORY_ROOT / "scripts" +SCRIPT_PATH = SCRIPTS_ROOT / "generate_typos_config.py" +COMMITTED_CONFIG = REPOSITORY_ROOT / "typos.toml" + + +@pytest.fixture(name="generator", scope="module") +def generator_fixture() -> types.ModuleType: + """Load the standalone generator with its neighbouring module visible.""" + sys.path.insert(0, str(SCRIPTS_ROOT)) + try: + spec = importlib.util.spec_from_file_location( + "generate_typos_config", + SCRIPT_PATH, + ) + assert spec is not None, "could not create generator module specification" + assert spec.loader is not None, "generator module specification has no loader" + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + finally: + sys.path.remove(str(SCRIPTS_ROOT)) + return module + + +def dictionary_text(*, stem: str = "organ", accepted: str = "oxendict") -> str: + """Return a minimal valid shared or local dictionary document.""" + return ( + "schema = 1\n\n[oxford]\n" + f'stems = ["{stem}"]\n\n' + f'[words]\naccepted = ["{accepted}"]\n\n' + "[words.corrections]\n\n[patterns]\nignore = []\n\n" + '[files]\nexclude = [".git"]\n' + ) + + +def prepare_repository( + tmp_path: pathlib.Path, + *, + base_stem: str = "organ", + local_stem: str = "custom", +) -> tuple[pathlib.Path, pathlib.Path]: + """Create a repository root and local shared source for generation tests.""" + repository = tmp_path / "repository" + repository.mkdir() + source = tmp_path / "shared.toml" + source.write_text(dictionary_text(stem=base_stem), encoding="utf-8") + (repository / "typos.local.toml").write_text( + dictionary_text(stem=local_stem, accepted="localword"), + encoding="utf-8", + ) + return repository, source + + +def test_main_refreshes_base_and_merges_local_overlay( + generator: types.ModuleType, + tmp_path: pathlib.Path, +) -> None: + """Generation starts from the shared base and retains narrow local policy.""" + repository, source = prepare_repository(tmp_path) + + result = generator.main(repository=repository, source=source) + rendered = (repository / "typos.toml").read_text(encoding="utf-8") + parsed = tomllib.loads(rendered) + words = parsed["default"]["extend-words"] + + assert result.status == "refreshed" + assert words["organise"] == "organize" + assert words["customise"] == "customize" + assert words["localword"] == "localword" + + +@given(stem=st.text(alphabet=string.ascii_lowercase, min_size=1, max_size=16)) +def test_oxford_mapping_property_covers_every_suffix_pair( + generator: types.ModuleType, + stem: str, +) -> None: + """Every safe stem expands to correction and identity entries.""" + mappings = generator.rollout.generate_word_mappings( + generator.rollout.Dictionary(stems=(stem,)) + ) + + for plain_british, oxford in generator.rollout.SUFFIX_PAIRS: + assert mappings[f"{stem}{plain_british}"] == f"{stem}{oxford}" + assert mappings[f"{stem}{oxford}"] == f"{stem}{oxford}" + + +def test_main_does_not_replace_newer_valid_local_cache( + generator: types.ModuleType, + tmp_path: pathlib.Path, +) -> None: + """An older shared copy cannot overwrite a newer untracked local cache.""" + repository, source = prepare_repository(tmp_path) + generator.main(repository=repository, source=source) + cache = repository / ".typos-oxendict-base.toml" + cache.write_text(dictionary_text(stem="newer"), encoding="utf-8") + os.utime(source, ns=(1_000_000_000, 1_000_000_000)) + os.utime(cache, ns=(2_000_000_000, 2_000_000_000)) + + result = generator.main(repository=repository, source=source) + + assert result.status == "current" + assert '"newerise" = "newerize"' in generator.render_config(repository) + + +def test_main_replaces_cache_from_different_authority( + generator: types.ModuleType, + tmp_path: pathlib.Path, +) -> None: + """Switching the explicit source replaces an unrelated newer cache.""" + repository, first_source = prepare_repository(tmp_path) + second_source = tmp_path / "second.toml" + second_source.write_text(dictionary_text(stem="second"), encoding="utf-8") + os.utime(first_source, ns=(3_000_000_000, 3_000_000_000)) + os.utime(second_source, ns=(1_000_000_000, 1_000_000_000)) + generator.main(repository=repository, source=first_source) + + result = generator.main(repository=repository, source=second_source) + + assert result.status == "refreshed" + assert '"secondise" = "secondize"' in generator.render_config(repository) + + +def test_offline_generation_requires_then_reuses_valid_cache( + generator: types.ModuleType, + tmp_path: pathlib.Path, +) -> None: + """Offline mode is safe after population and explicit before population.""" + repository, source = prepare_repository(tmp_path) + + with pytest.raises(FileNotFoundError, match="no cached shared dictionary"): + generator.main(repository=repository, source=source, offline=True) + + generator.main(repository=repository, source=source) + result = generator.main(repository=repository, source=source, offline=True) + + assert result.status == "offline-cache" + + +def test_rendered_config_is_deterministic_valid_toml( + generator: types.ModuleType, + tmp_path: pathlib.Path, +) -> None: + """Rendered output is stable, parseable and has one trailing newline.""" + repository, source = prepare_repository(tmp_path) + generator.main(repository=repository, source=source) + + first = generator.render_config(repository) + second = generator.render_config(repository) + + assert first == second + assert tomllib.loads(first)["default"]["locale"] == "en-gb" + assert first.endswith("\n") + assert not first.endswith("\n\n") + + +def test_committed_config_matches_current_shared_dictionary( + generator: types.ModuleType, + tmp_path: pathlib.Path, +) -> None: + """The committed generated file has not drifted from shared and local data.""" + output = tmp_path / "typos.toml" + + generator.main(output) + + assert COMMITTED_CONFIG.read_text(encoding="utf-8") == output.read_text( + encoding="utf-8" + ) + tomllib.loads(output.read_text(encoding="utf-8")) + + +def _pinned_typos_version() -> str: + """Read the Makefile's single source of truth for the typos version.""" + makefile = (REPOSITORY_ROOT / "Makefile").read_text(encoding="utf-8") + match = re.search(r"^TYPOS_VERSION\s*\?=\s*(\S+)", makefile, re.MULTILINE) + assert match is not None, "TYPOS_VERSION not found in Makefile" + return match.group(1) + + +@pytest.mark.slow +def test_generated_config_loads_in_pinned_typos( + generator: types.ModuleType, + tmp_path: pathlib.Path, +) -> None: + """The real pinned binary enforces Oxford and British sample spellings.""" + uv_executable = shutil.which("uv") + if uv_executable is None: + pytest.skip("uv is unavailable to run the pinned typos binary") + repository, source = prepare_repository(tmp_path) + config = repository / "typos.toml" + generator.main(repository=repository, source=source) + sample = repository / "sample.md" + sample.write_text( + "The team will organise color output.\n", + encoding="utf-8", + ) + + result = subprocess.run( # noqa: S603 - argv contains trusted paths and literals. + [ + uv_executable, + "tool", + "run", + f"typos@{_pinned_typos_version()}", + "--config", + str(config), + "--format", + "json", + str(sample), + ], + capture_output=True, + text=True, + timeout=90, + check=False, + ) + corrections = { + entry["typo"]: entry.get("corrections", []) + for line in result.stdout.splitlines() + for entry in (json.loads(line),) + if entry.get("type") == "typo" + } + + assert corrections.get("organise") == ["organize"] + assert corrections.get("color") == ["colour"] diff --git a/typos.local.toml b/typos.local.toml new file mode 100644 index 0000000..5e01e97 --- /dev/null +++ b/typos.local.toml @@ -0,0 +1,22 @@ +# Repository-specific identifiers, quotations and deliberate fixtures. + +schema = 1 + +[oxford] +stems = [] + +[words] +accepted = [] + +[words.corrections] + +[patterns] +ignore = [ + 'Center \| Microsoft Learn', +] + +[files] +exclude = [ + "docs/configuring-a-copier-template.md", + "docs/creating-a-copier-template.md", +] diff --git a/typos.toml b/typos.toml new file mode 100644 index 0000000..81e512c --- /dev/null +++ b/typos.toml @@ -0,0 +1,2633 @@ +# Generated from the shared en-GB-oxendict dictionary. +# Regenerate with scripts/generate_typos_config.py; do not edit by hand. + +[files] +extend-exclude = [ + ".git", + ".hypothesis", + ".pytest_cache", + ".tox", + ".typos-oxendict-base.json", + ".typos-oxendict-base.toml", + ".uv-cache", + ".uv-tools", + ".venv", + "Cargo.lock", + "bun.lock", + "data/typos-oxendict-base.toml", + "dist", + "docs/configuring-a-copier-template.md", + "docs/creating-a-copier-template.md", + "node_modules", + "package-lock.json", + "pnpm-lock.yaml", + "target", + "typos.local.toml", + "typos.toml", + "uv.lock", + "yarn.lock", +] + +[default] +locale = "en-gb" +extend-ignore-re = [ + "(?s)```.*?```", + "Center \\| Microsoft Learn", + "`[^`\\n]+`", +] + +[default.extend-words] +"absolutisable" = "absolutizable" +"absolutisation" = "absolutization" +"absolutisations" = "absolutizations" +"absolutise" = "absolutize" +"absolutised" = "absolutized" +"absolutiser" = "absolutizer" +"absolutisers" = "absolutizers" +"absolutises" = "absolutizes" +"absolutising" = "absolutizing" +"absolutizable" = "absolutizable" +"absolutization" = "absolutization" +"absolutizations" = "absolutizations" +"absolutize" = "absolutize" +"absolutized" = "absolutized" +"absolutizer" = "absolutizer" +"absolutizers" = "absolutizers" +"absolutizes" = "absolutizes" +"absolutizing" = "absolutizing" +"actualisable" = "actualizable" +"actualisation" = "actualization" +"actualisations" = "actualizations" +"actualise" = "actualize" +"actualised" = "actualized" +"actualiser" = "actualizer" +"actualisers" = "actualizers" +"actualises" = "actualizes" +"actualising" = "actualizing" +"actualizable" = "actualizable" +"actualization" = "actualization" +"actualizations" = "actualizations" +"actualize" = "actualize" +"actualized" = "actualized" +"actualizer" = "actualizer" +"actualizers" = "actualizers" +"actualizes" = "actualizes" +"actualizing" = "actualizing" +"alphabetisable" = "alphabetizable" +"alphabetisation" = "alphabetization" +"alphabetisations" = "alphabetizations" +"alphabetise" = "alphabetize" +"alphabetised" = "alphabetized" +"alphabetiser" = "alphabetizer" +"alphabetisers" = "alphabetizers" +"alphabetises" = "alphabetizes" +"alphabetising" = "alphabetizing" +"alphabetizable" = "alphabetizable" +"alphabetization" = "alphabetization" +"alphabetizations" = "alphabetizations" +"alphabetize" = "alphabetize" +"alphabetized" = "alphabetized" +"alphabetizer" = "alphabetizer" +"alphabetizers" = "alphabetizers" +"alphabetizes" = "alphabetizes" +"alphabetizing" = "alphabetizing" +"amortisable" = "amortizable" +"amortisation" = "amortization" +"amortisations" = "amortizations" +"amortise" = "amortize" +"amortised" = "amortized" +"amortiser" = "amortizer" +"amortisers" = "amortizers" +"amortises" = "amortizes" +"amortising" = "amortizing" +"amortizable" = "amortizable" +"amortization" = "amortization" +"amortizations" = "amortizations" +"amortize" = "amortize" +"amortized" = "amortized" +"amortizer" = "amortizer" +"amortizers" = "amortizers" +"amortizes" = "amortizes" +"amortizing" = "amortizing" +"anonymisable" = "anonymizable" +"anonymisation" = "anonymization" +"anonymisations" = "anonymizations" +"anonymise" = "anonymize" +"anonymised" = "anonymized" +"anonymiser" = "anonymizer" +"anonymisers" = "anonymizers" +"anonymises" = "anonymizes" +"anonymising" = "anonymizing" +"anonymizable" = "anonymizable" +"anonymization" = "anonymization" +"anonymizations" = "anonymizations" +"anonymize" = "anonymize" +"anonymized" = "anonymized" +"anonymizer" = "anonymizer" +"anonymizers" = "anonymizers" +"anonymizes" = "anonymizes" +"anonymizing" = "anonymizing" +"apologisable" = "apologizable" +"apologisation" = "apologization" +"apologisations" = "apologizations" +"apologise" = "apologize" +"apologised" = "apologized" +"apologiser" = "apologizer" +"apologisers" = "apologizers" +"apologises" = "apologizes" +"apologising" = "apologizing" +"apologizable" = "apologizable" +"apologization" = "apologization" +"apologizations" = "apologizations" +"apologize" = "apologize" +"apologized" = "apologized" +"apologizer" = "apologizer" +"apologizers" = "apologizers" +"apologizes" = "apologizes" +"apologizing" = "apologizing" +"atomisable" = "atomizable" +"atomisation" = "atomization" +"atomisations" = "atomizations" +"atomise" = "atomize" +"atomised" = "atomized" +"atomiser" = "atomizer" +"atomisers" = "atomizers" +"atomises" = "atomizes" +"atomising" = "atomizing" +"atomizable" = "atomizable" +"atomization" = "atomization" +"atomizations" = "atomizations" +"atomize" = "atomize" +"atomized" = "atomized" +"atomizer" = "atomizer" +"atomizers" = "atomizers" +"atomizes" = "atomizes" +"atomizing" = "atomizing" +"authorisable" = "authorizable" +"authorisation" = "authorization" +"authorisations" = "authorizations" +"authorise" = "authorize" +"authorised" = "authorized" +"authoriser" = "authorizer" +"authorisers" = "authorizers" +"authorises" = "authorizes" +"authorising" = "authorizing" +"authorizable" = "authorizable" +"authorization" = "authorization" +"authorizations" = "authorizations" +"authorize" = "authorize" +"authorized" = "authorized" +"authorizer" = "authorizer" +"authorizers" = "authorizers" +"authorizes" = "authorizes" +"authorizing" = "authorizing" +"canonicalisable" = "canonicalizable" +"canonicalisation" = "canonicalization" +"canonicalisations" = "canonicalizations" +"canonicalise" = "canonicalize" +"canonicalised" = "canonicalized" +"canonicaliser" = "canonicalizer" +"canonicalisers" = "canonicalizers" +"canonicalises" = "canonicalizes" +"canonicalising" = "canonicalizing" +"canonicalizable" = "canonicalizable" +"canonicalization" = "canonicalization" +"canonicalizations" = "canonicalizations" +"canonicalize" = "canonicalize" +"canonicalized" = "canonicalized" +"canonicalizer" = "canonicalizer" +"canonicalizers" = "canonicalizers" +"canonicalizes" = "canonicalizes" +"canonicalizing" = "canonicalizing" +"capitalisable" = "capitalizable" +"capitalisation" = "capitalization" +"capitalisations" = "capitalizations" +"capitalise" = "capitalize" +"capitalised" = "capitalized" +"capitaliser" = "capitalizer" +"capitalisers" = "capitalizers" +"capitalises" = "capitalizes" +"capitalising" = "capitalizing" +"capitalizable" = "capitalizable" +"capitalization" = "capitalization" +"capitalizations" = "capitalizations" +"capitalize" = "capitalize" +"capitalized" = "capitalized" +"capitalizer" = "capitalizer" +"capitalizers" = "capitalizers" +"capitalizes" = "capitalizes" +"capitalizing" = "capitalizing" +"categorisable" = "categorizable" +"categorisation" = "categorization" +"categorisations" = "categorizations" +"categorise" = "categorize" +"categorised" = "categorized" +"categoriser" = "categorizer" +"categorisers" = "categorizers" +"categorises" = "categorizes" +"categorising" = "categorizing" +"categorizable" = "categorizable" +"categorization" = "categorization" +"categorizations" = "categorizations" +"categorize" = "categorize" +"categorized" = "categorized" +"categorizer" = "categorizer" +"categorizers" = "categorizers" +"categorizes" = "categorizes" +"categorizing" = "categorizing" +"centralisable" = "centralizable" +"centralisation" = "centralization" +"centralisations" = "centralizations" +"centralise" = "centralize" +"centralised" = "centralized" +"centraliser" = "centralizer" +"centralisers" = "centralizers" +"centralises" = "centralizes" +"centralising" = "centralizing" +"centralizable" = "centralizable" +"centralization" = "centralization" +"centralizations" = "centralizations" +"centralize" = "centralize" +"centralized" = "centralized" +"centralizer" = "centralizer" +"centralizers" = "centralizers" +"centralizes" = "centralizes" +"centralizing" = "centralizing" +"characterisable" = "characterizable" +"characterisation" = "characterization" +"characterisations" = "characterizations" +"characterise" = "characterize" +"characterised" = "characterized" +"characteriser" = "characterizer" +"characterisers" = "characterizers" +"characterises" = "characterizes" +"characterising" = "characterizing" +"characterizable" = "characterizable" +"characterization" = "characterization" +"characterizations" = "characterizations" +"characterize" = "characterize" +"characterized" = "characterized" +"characterizer" = "characterizer" +"characterizers" = "characterizers" +"characterizes" = "characterizes" +"characterizing" = "characterizing" +"civilisable" = "civilizable" +"civilisation" = "civilization" +"civilisations" = "civilizations" +"civilise" = "civilize" +"civilised" = "civilized" +"civiliser" = "civilizer" +"civilisers" = "civilizers" +"civilises" = "civilizes" +"civilising" = "civilizing" +"civilizable" = "civilizable" +"civilization" = "civilization" +"civilizations" = "civilizations" +"civilize" = "civilize" +"civilized" = "civilized" +"civilizer" = "civilizer" +"civilizers" = "civilizers" +"civilizes" = "civilizes" +"civilizing" = "civilizing" +"colonisable" = "colonizable" +"colonisation" = "colonization" +"colonisations" = "colonizations" +"colonise" = "colonize" +"colonised" = "colonized" +"coloniser" = "colonizer" +"colonisers" = "colonizers" +"colonises" = "colonizes" +"colonising" = "colonizing" +"colonizable" = "colonizable" +"colonization" = "colonization" +"colonizations" = "colonizations" +"colonize" = "colonize" +"colonized" = "colonized" +"colonizer" = "colonizer" +"colonizers" = "colonizers" +"colonizes" = "colonizes" +"colonizing" = "colonizing" +"colourisable" = "colourizable" +"colourisation" = "colourization" +"colourisations" = "colourizations" +"colourise" = "colourize" +"colourised" = "colourized" +"colouriser" = "colourizer" +"colourisers" = "colourizers" +"colourises" = "colourizes" +"colourising" = "colourizing" +"colourizable" = "colourizable" +"colourization" = "colourization" +"colourizations" = "colourizations" +"colourize" = "colourize" +"colourized" = "colourized" +"colourizer" = "colourizer" +"colourizers" = "colourizers" +"colourizes" = "colourizes" +"colourizing" = "colourizing" +"commonisable" = "commonizable" +"commonisation" = "commonization" +"commonisations" = "commonizations" +"commonise" = "commonize" +"commonised" = "commonized" +"commoniser" = "commonizer" +"commonisers" = "commonizers" +"commonises" = "commonizes" +"commonising" = "commonizing" +"commonizable" = "commonizable" +"commonization" = "commonization" +"commonizations" = "commonizations" +"commonize" = "commonize" +"commonized" = "commonized" +"commonizer" = "commonizer" +"commonizers" = "commonizers" +"commonizes" = "commonizes" +"commonizing" = "commonizing" +"conceptualisable" = "conceptualizable" +"conceptualisation" = "conceptualization" +"conceptualisations" = "conceptualizations" +"conceptualise" = "conceptualize" +"conceptualised" = "conceptualized" +"conceptualiser" = "conceptualizer" +"conceptualisers" = "conceptualizers" +"conceptualises" = "conceptualizes" +"conceptualising" = "conceptualizing" +"conceptualizable" = "conceptualizable" +"conceptualization" = "conceptualization" +"conceptualizations" = "conceptualizations" +"conceptualize" = "conceptualize" +"conceptualized" = "conceptualized" +"conceptualizer" = "conceptualizer" +"conceptualizers" = "conceptualizers" +"conceptualizes" = "conceptualizes" +"conceptualizing" = "conceptualizing" +"concretisable" = "concretizable" +"concretisation" = "concretization" +"concretisations" = "concretizations" +"concretise" = "concretize" +"concretised" = "concretized" +"concretiser" = "concretizer" +"concretisers" = "concretizers" +"concretises" = "concretizes" +"concretising" = "concretizing" +"concretizable" = "concretizable" +"concretization" = "concretization" +"concretizations" = "concretizations" +"concretize" = "concretize" +"concretized" = "concretized" +"concretizer" = "concretizer" +"concretizers" = "concretizers" +"concretizes" = "concretizes" +"concretizing" = "concretizing" +"containerisable" = "containerizable" +"containerisation" = "containerization" +"containerisations" = "containerizations" +"containerise" = "containerize" +"containerised" = "containerized" +"containeriser" = "containerizer" +"containerisers" = "containerizers" +"containerises" = "containerizes" +"containerising" = "containerizing" +"containerizable" = "containerizable" +"containerization" = "containerization" +"containerizations" = "containerizations" +"containerize" = "containerize" +"containerized" = "containerized" +"containerizer" = "containerizer" +"containerizers" = "containerizers" +"containerizes" = "containerizes" +"containerizing" = "containerizing" +"contextualisable" = "contextualizable" +"contextualisation" = "contextualization" +"contextualisations" = "contextualizations" +"contextualise" = "contextualize" +"contextualised" = "contextualized" +"contextualiser" = "contextualizer" +"contextualisers" = "contextualizers" +"contextualises" = "contextualizes" +"contextualising" = "contextualizing" +"contextualizable" = "contextualizable" +"contextualization" = "contextualization" +"contextualizations" = "contextualizations" +"contextualize" = "contextualize" +"contextualized" = "contextualized" +"contextualizer" = "contextualizer" +"contextualizers" = "contextualizers" +"contextualizes" = "contextualizes" +"contextualizing" = "contextualizing" +"criticisable" = "criticizable" +"criticisation" = "criticization" +"criticisations" = "criticizations" +"criticise" = "criticize" +"criticised" = "criticized" +"criticiser" = "criticizer" +"criticisers" = "criticizers" +"criticises" = "criticizes" +"criticising" = "criticizing" +"criticizable" = "criticizable" +"criticization" = "criticization" +"criticizations" = "criticizations" +"criticize" = "criticize" +"criticized" = "criticized" +"criticizer" = "criticizer" +"criticizers" = "criticizers" +"criticizes" = "criticizes" +"criticizing" = "criticizing" +"crystallisable" = "crystallizable" +"crystallisation" = "crystallization" +"crystallisations" = "crystallizations" +"crystallise" = "crystallize" +"crystallised" = "crystallized" +"crystalliser" = "crystallizer" +"crystallisers" = "crystallizers" +"crystallises" = "crystallizes" +"crystallising" = "crystallizing" +"crystallizable" = "crystallizable" +"crystallization" = "crystallization" +"crystallizations" = "crystallizations" +"crystallize" = "crystallize" +"crystallized" = "crystallized" +"crystallizer" = "crystallizer" +"crystallizers" = "crystallizers" +"crystallizes" = "crystallizes" +"crystallizing" = "crystallizing" +"customisable" = "customizable" +"customisation" = "customization" +"customisations" = "customizations" +"customise" = "customize" +"customised" = "customized" +"customiser" = "customizer" +"customisers" = "customizers" +"customises" = "customizes" +"customising" = "customizing" +"customizable" = "customizable" +"customization" = "customization" +"customizations" = "customizations" +"customize" = "customize" +"customized" = "customized" +"customizer" = "customizer" +"customizers" = "customizers" +"customizes" = "customizes" +"customizing" = "customizing" +"daemonisable" = "daemonizable" +"daemonisation" = "daemonization" +"daemonisations" = "daemonizations" +"daemonise" = "daemonize" +"daemonised" = "daemonized" +"daemoniser" = "daemonizer" +"daemonisers" = "daemonizers" +"daemonises" = "daemonizes" +"daemonising" = "daemonizing" +"daemonizable" = "daemonizable" +"daemonization" = "daemonization" +"daemonizations" = "daemonizations" +"daemonize" = "daemonize" +"daemonized" = "daemonized" +"daemonizer" = "daemonizer" +"daemonizers" = "daemonizers" +"daemonizes" = "daemonizes" +"daemonizing" = "daemonizing" +"decentralisable" = "decentralizable" +"decentralisation" = "decentralization" +"decentralisations" = "decentralizations" +"decentralise" = "decentralize" +"decentralised" = "decentralized" +"decentraliser" = "decentralizer" +"decentralisers" = "decentralizers" +"decentralises" = "decentralizes" +"decentralising" = "decentralizing" +"decentralizable" = "decentralizable" +"decentralization" = "decentralization" +"decentralizations" = "decentralizations" +"decentralize" = "decentralize" +"decentralized" = "decentralized" +"decentralizer" = "decentralizer" +"decentralizers" = "decentralizers" +"decentralizes" = "decentralizes" +"decentralizing" = "decentralizing" +"denormalisable" = "denormalizable" +"denormalisation" = "denormalization" +"denormalisations" = "denormalizations" +"denormalise" = "denormalize" +"denormalised" = "denormalized" +"denormaliser" = "denormalizer" +"denormalisers" = "denormalizers" +"denormalises" = "denormalizes" +"denormalising" = "denormalizing" +"denormalizable" = "denormalizable" +"denormalization" = "denormalization" +"denormalizations" = "denormalizations" +"denormalize" = "denormalize" +"denormalized" = "denormalized" +"denormalizer" = "denormalizer" +"denormalizers" = "denormalizers" +"denormalizes" = "denormalizes" +"denormalizing" = "denormalizing" +"derandomisable" = "derandomizable" +"derandomisation" = "derandomization" +"derandomisations" = "derandomizations" +"derandomise" = "derandomize" +"derandomised" = "derandomized" +"derandomiser" = "derandomizer" +"derandomisers" = "derandomizers" +"derandomises" = "derandomizes" +"derandomising" = "derandomizing" +"derandomizable" = "derandomizable" +"derandomization" = "derandomization" +"derandomizations" = "derandomizations" +"derandomize" = "derandomize" +"derandomized" = "derandomized" +"derandomizer" = "derandomizer" +"derandomizers" = "derandomizers" +"derandomizes" = "derandomizes" +"derandomizing" = "derandomizing" +"deserialisable" = "deserializable" +"deserialisation" = "deserialization" +"deserialisations" = "deserializations" +"deserialise" = "deserialize" +"deserialised" = "deserialized" +"deserialiser" = "deserializer" +"deserialisers" = "deserializers" +"deserialises" = "deserializes" +"deserialising" = "deserializing" +"deserializable" = "deserializable" +"deserialization" = "deserialization" +"deserializations" = "deserializations" +"deserialize" = "deserialize" +"deserialized" = "deserialized" +"deserializer" = "deserializer" +"deserializers" = "deserializers" +"deserializes" = "deserializes" +"deserializing" = "deserializing" +"destabilisable" = "destabilizable" +"destabilisation" = "destabilization" +"destabilisations" = "destabilizations" +"destabilise" = "destabilize" +"destabilised" = "destabilized" +"destabiliser" = "destabilizer" +"destabilisers" = "destabilizers" +"destabilises" = "destabilizes" +"destabilising" = "destabilizing" +"destabilizable" = "destabilizable" +"destabilization" = "destabilization" +"destabilizations" = "destabilizations" +"destabilize" = "destabilize" +"destabilized" = "destabilized" +"destabilizer" = "destabilizer" +"destabilizers" = "destabilizers" +"destabilizes" = "destabilizes" +"destabilizing" = "destabilizing" +"desynchronisable" = "desynchronizable" +"desynchronisation" = "desynchronization" +"desynchronisations" = "desynchronizations" +"desynchronise" = "desynchronize" +"desynchronised" = "desynchronized" +"desynchroniser" = "desynchronizer" +"desynchronisers" = "desynchronizers" +"desynchronises" = "desynchronizes" +"desynchronising" = "desynchronizing" +"desynchronizable" = "desynchronizable" +"desynchronization" = "desynchronization" +"desynchronizations" = "desynchronizations" +"desynchronize" = "desynchronize" +"desynchronized" = "desynchronized" +"desynchronizer" = "desynchronizer" +"desynchronizers" = "desynchronizers" +"desynchronizes" = "desynchronizes" +"desynchronizing" = "desynchronizing" +"dockerisable" = "dockerizable" +"dockerisation" = "dockerization" +"dockerisations" = "dockerizations" +"dockerise" = "dockerize" +"dockerised" = "dockerized" +"dockeriser" = "dockerizer" +"dockerisers" = "dockerizers" +"dockerises" = "dockerizes" +"dockerising" = "dockerizing" +"dockerizable" = "dockerizable" +"dockerization" = "dockerization" +"dockerizations" = "dockerizations" +"dockerize" = "dockerize" +"dockerized" = "dockerized" +"dockerizer" = "dockerizer" +"dockerizers" = "dockerizers" +"dockerizes" = "dockerizes" +"dockerizing" = "dockerizing" +"dramatisable" = "dramatizable" +"dramatisation" = "dramatization" +"dramatisations" = "dramatizations" +"dramatise" = "dramatize" +"dramatised" = "dramatized" +"dramatiser" = "dramatizer" +"dramatisers" = "dramatizers" +"dramatises" = "dramatizes" +"dramatising" = "dramatizing" +"dramatizable" = "dramatizable" +"dramatization" = "dramatization" +"dramatizations" = "dramatizations" +"dramatize" = "dramatize" +"dramatized" = "dramatized" +"dramatizer" = "dramatizer" +"dramatizers" = "dramatizers" +"dramatizes" = "dramatizes" +"dramatizing" = "dramatizing" +"emphasisable" = "emphasizable" +"emphasisation" = "emphasization" +"emphasisations" = "emphasizations" +"emphasise" = "emphasize" +"emphasised" = "emphasized" +"emphasiser" = "emphasizer" +"emphasisers" = "emphasizers" +"emphasises" = "emphasizes" +"emphasising" = "emphasizing" +"emphasizable" = "emphasizable" +"emphasization" = "emphasization" +"emphasizations" = "emphasizations" +"emphasize" = "emphasize" +"emphasized" = "emphasized" +"emphasizer" = "emphasizer" +"emphasizers" = "emphasizers" +"emphasizes" = "emphasizes" +"emphasizing" = "emphasizing" +"energisable" = "energizable" +"energisation" = "energization" +"energisations" = "energizations" +"energise" = "energize" +"energised" = "energized" +"energiser" = "energizer" +"energisers" = "energizers" +"energises" = "energizes" +"energising" = "energizing" +"energizable" = "energizable" +"energization" = "energization" +"energizations" = "energizations" +"energize" = "energize" +"energized" = "energized" +"energizer" = "energizer" +"energizers" = "energizers" +"energizes" = "energizes" +"energizing" = "energizing" +"equalisable" = "equalizable" +"equalisation" = "equalization" +"equalisations" = "equalizations" +"equalise" = "equalize" +"equalised" = "equalized" +"equaliser" = "equalizer" +"equalisers" = "equalizers" +"equalises" = "equalizes" +"equalising" = "equalizing" +"equalizable" = "equalizable" +"equalization" = "equalization" +"equalizations" = "equalizations" +"equalize" = "equalize" +"equalized" = "equalized" +"equalizer" = "equalizer" +"equalizers" = "equalizers" +"equalizes" = "equalizes" +"equalizing" = "equalizing" +"externalisable" = "externalizable" +"externalisation" = "externalization" +"externalisations" = "externalizations" +"externalise" = "externalize" +"externalised" = "externalized" +"externaliser" = "externalizer" +"externalisers" = "externalizers" +"externalises" = "externalizes" +"externalising" = "externalizing" +"externalizable" = "externalizable" +"externalization" = "externalization" +"externalizations" = "externalizations" +"externalize" = "externalize" +"externalized" = "externalized" +"externalizer" = "externalizer" +"externalizers" = "externalizers" +"externalizes" = "externalizes" +"externalizing" = "externalizing" +"factorisable" = "factorizable" +"factorisation" = "factorization" +"factorisations" = "factorizations" +"factorise" = "factorize" +"factorised" = "factorized" +"factoriser" = "factorizer" +"factorisers" = "factorizers" +"factorises" = "factorizes" +"factorising" = "factorizing" +"factorizable" = "factorizable" +"factorization" = "factorization" +"factorizations" = "factorizations" +"factorize" = "factorize" +"factorized" = "factorized" +"factorizer" = "factorizer" +"factorizers" = "factorizers" +"factorizes" = "factorizes" +"factorizing" = "factorizing" +"familiarisable" = "familiarizable" +"familiarisation" = "familiarization" +"familiarisations" = "familiarizations" +"familiarise" = "familiarize" +"familiarised" = "familiarized" +"familiariser" = "familiarizer" +"familiarisers" = "familiarizers" +"familiarises" = "familiarizes" +"familiarising" = "familiarizing" +"familiarizable" = "familiarizable" +"familiarization" = "familiarization" +"familiarizations" = "familiarizations" +"familiarize" = "familiarize" +"familiarized" = "familiarized" +"familiarizer" = "familiarizer" +"familiarizers" = "familiarizers" +"familiarizes" = "familiarizes" +"familiarizing" = "familiarizing" +"finalisable" = "finalizable" +"finalisation" = "finalization" +"finalisations" = "finalizations" +"finalise" = "finalize" +"finalised" = "finalized" +"finaliser" = "finalizer" +"finalisers" = "finalizers" +"finalises" = "finalizes" +"finalising" = "finalizing" +"finalizable" = "finalizable" +"finalization" = "finalization" +"finalizations" = "finalizations" +"finalize" = "finalize" +"finalized" = "finalized" +"finalizer" = "finalizer" +"finalizers" = "finalizers" +"finalizes" = "finalizes" +"finalizing" = "finalizing" +"formalisable" = "formalizable" +"formalisation" = "formalization" +"formalisations" = "formalizations" +"formalise" = "formalize" +"formalised" = "formalized" +"formaliser" = "formalizer" +"formalisers" = "formalizers" +"formalises" = "formalizes" +"formalising" = "formalizing" +"formalizable" = "formalizable" +"formalization" = "formalization" +"formalizations" = "formalizations" +"formalize" = "formalize" +"formalized" = "formalized" +"formalizer" = "formalizer" +"formalizers" = "formalizers" +"formalizes" = "formalizes" +"formalizing" = "formalizing" +"fossilisable" = "fossilizable" +"fossilisation" = "fossilization" +"fossilisations" = "fossilizations" +"fossilise" = "fossilize" +"fossilised" = "fossilized" +"fossiliser" = "fossilizer" +"fossilisers" = "fossilizers" +"fossilises" = "fossilizes" +"fossilising" = "fossilizing" +"fossilizable" = "fossilizable" +"fossilization" = "fossilization" +"fossilizations" = "fossilizations" +"fossilize" = "fossilize" +"fossilized" = "fossilized" +"fossilizer" = "fossilizer" +"fossilizers" = "fossilizers" +"fossilizes" = "fossilizes" +"fossilizing" = "fossilizing" +"generalisable" = "generalizable" +"generalisation" = "generalization" +"generalisations" = "generalizations" +"generalise" = "generalize" +"generalised" = "generalized" +"generaliser" = "generalizer" +"generalisers" = "generalizers" +"generalises" = "generalizes" +"generalising" = "generalizing" +"generalizable" = "generalizable" +"generalization" = "generalization" +"generalizations" = "generalizations" +"generalize" = "generalize" +"generalized" = "generalized" +"generalizer" = "generalizer" +"generalizers" = "generalizers" +"generalizes" = "generalizes" +"generalizing" = "generalizing" +"globalisable" = "globalizable" +"globalisation" = "globalization" +"globalisations" = "globalizations" +"globalise" = "globalize" +"globalised" = "globalized" +"globaliser" = "globalizer" +"globalisers" = "globalizers" +"globalises" = "globalizes" +"globalising" = "globalizing" +"globalizable" = "globalizable" +"globalization" = "globalization" +"globalizations" = "globalizations" +"globalize" = "globalize" +"globalized" = "globalized" +"globalizer" = "globalizer" +"globalizers" = "globalizers" +"globalizes" = "globalizes" +"globalizing" = "globalizing" +"harmonisable" = "harmonizable" +"harmonisation" = "harmonization" +"harmonisations" = "harmonizations" +"harmonise" = "harmonize" +"harmonised" = "harmonized" +"harmoniser" = "harmonizer" +"harmonisers" = "harmonizers" +"harmonises" = "harmonizes" +"harmonising" = "harmonizing" +"harmonizable" = "harmonizable" +"harmonization" = "harmonization" +"harmonizations" = "harmonizations" +"harmonize" = "harmonize" +"harmonized" = "harmonized" +"harmonizer" = "harmonizer" +"harmonizers" = "harmonizers" +"harmonizes" = "harmonizes" +"harmonizing" = "harmonizing" +"homogenisable" = "homogenizable" +"homogenisation" = "homogenization" +"homogenisations" = "homogenizations" +"homogenise" = "homogenize" +"homogenised" = "homogenized" +"homogeniser" = "homogenizer" +"homogenisers" = "homogenizers" +"homogenises" = "homogenizes" +"homogenising" = "homogenizing" +"homogenizable" = "homogenizable" +"homogenization" = "homogenization" +"homogenizations" = "homogenizations" +"homogenize" = "homogenize" +"homogenized" = "homogenized" +"homogenizer" = "homogenizer" +"homogenizers" = "homogenizers" +"homogenizes" = "homogenizes" +"homogenizing" = "homogenizing" +"humanisable" = "humanizable" +"humanisation" = "humanization" +"humanisations" = "humanizations" +"humanise" = "humanize" +"humanised" = "humanized" +"humaniser" = "humanizer" +"humanisers" = "humanizers" +"humanises" = "humanizes" +"humanising" = "humanizing" +"humanizable" = "humanizable" +"humanization" = "humanization" +"humanizations" = "humanizations" +"humanize" = "humanize" +"humanized" = "humanized" +"humanizer" = "humanizer" +"humanizers" = "humanizers" +"humanizes" = "humanizes" +"humanizing" = "humanizing" +"hypothesisable" = "hypothesizable" +"hypothesisation" = "hypothesization" +"hypothesisations" = "hypothesizations" +"hypothesise" = "hypothesize" +"hypothesised" = "hypothesized" +"hypothesiser" = "hypothesizer" +"hypothesisers" = "hypothesizers" +"hypothesises" = "hypothesizes" +"hypothesising" = "hypothesizing" +"hypothesizable" = "hypothesizable" +"hypothesization" = "hypothesization" +"hypothesizations" = "hypothesizations" +"hypothesize" = "hypothesize" +"hypothesized" = "hypothesized" +"hypothesizer" = "hypothesizer" +"hypothesizers" = "hypothesizers" +"hypothesizes" = "hypothesizes" +"hypothesizing" = "hypothesizing" +"idealisable" = "idealizable" +"idealisation" = "idealization" +"idealisations" = "idealizations" +"idealise" = "idealize" +"idealised" = "idealized" +"idealiser" = "idealizer" +"idealisers" = "idealizers" +"idealises" = "idealizes" +"idealising" = "idealizing" +"idealizable" = "idealizable" +"idealization" = "idealization" +"idealizations" = "idealizations" +"idealize" = "idealize" +"idealized" = "idealized" +"idealizer" = "idealizer" +"idealizers" = "idealizers" +"idealizes" = "idealizes" +"idealizing" = "idealizing" +"industrialisable" = "industrializable" +"industrialisation" = "industrialization" +"industrialisations" = "industrializations" +"industrialise" = "industrialize" +"industrialised" = "industrialized" +"industrialiser" = "industrializer" +"industrialisers" = "industrializers" +"industrialises" = "industrializes" +"industrialising" = "industrializing" +"industrializable" = "industrializable" +"industrialization" = "industrialization" +"industrializations" = "industrializations" +"industrialize" = "industrialize" +"industrialized" = "industrialized" +"industrializer" = "industrializer" +"industrializers" = "industrializers" +"industrializes" = "industrializes" +"industrializing" = "industrializing" +"initialisable" = "initializable" +"initialisation" = "initialization" +"initialisations" = "initializations" +"initialise" = "initialize" +"initialised" = "initialized" +"initialiser" = "initializer" +"initialisers" = "initializers" +"initialises" = "initializes" +"initialising" = "initializing" +"initializable" = "initializable" +"initialization" = "initialization" +"initializations" = "initializations" +"initialize" = "initialize" +"initialized" = "initialized" +"initializer" = "initializer" +"initializers" = "initializers" +"initializes" = "initializes" +"initializing" = "initializing" +"institutionalisable" = "institutionalizable" +"institutionalisation" = "institutionalization" +"institutionalisations" = "institutionalizations" +"institutionalise" = "institutionalize" +"institutionalised" = "institutionalized" +"institutionaliser" = "institutionalizer" +"institutionalisers" = "institutionalizers" +"institutionalises" = "institutionalizes" +"institutionalising" = "institutionalizing" +"institutionalizable" = "institutionalizable" +"institutionalization" = "institutionalization" +"institutionalizations" = "institutionalizations" +"institutionalize" = "institutionalize" +"institutionalized" = "institutionalized" +"institutionalizer" = "institutionalizer" +"institutionalizers" = "institutionalizers" +"institutionalizes" = "institutionalizes" +"institutionalizing" = "institutionalizing" +"internalisable" = "internalizable" +"internalisation" = "internalization" +"internalisations" = "internalizations" +"internalise" = "internalize" +"internalised" = "internalized" +"internaliser" = "internalizer" +"internalisers" = "internalizers" +"internalises" = "internalizes" +"internalising" = "internalizing" +"internalizable" = "internalizable" +"internalization" = "internalization" +"internalizations" = "internalizations" +"internalize" = "internalize" +"internalized" = "internalized" +"internalizer" = "internalizer" +"internalizers" = "internalizers" +"internalizes" = "internalizes" +"internalizing" = "internalizing" +"internationalisable" = "internationalizable" +"internationalisation" = "internationalization" +"internationalisations" = "internationalizations" +"internationalise" = "internationalize" +"internationalised" = "internationalized" +"internationaliser" = "internationalizer" +"internationalisers" = "internationalizers" +"internationalises" = "internationalizes" +"internationalising" = "internationalizing" +"internationalizable" = "internationalizable" +"internationalization" = "internationalization" +"internationalizations" = "internationalizations" +"internationalize" = "internationalize" +"internationalized" = "internationalized" +"internationalizer" = "internationalizer" +"internationalizers" = "internationalizers" +"internationalizes" = "internationalizes" +"internationalizing" = "internationalizing" +"itemisable" = "itemizable" +"itemisation" = "itemization" +"itemisations" = "itemizations" +"itemise" = "itemize" +"itemised" = "itemized" +"itemiser" = "itemizer" +"itemisers" = "itemizers" +"itemises" = "itemizes" +"itemising" = "itemizing" +"itemizable" = "itemizable" +"itemization" = "itemization" +"itemizations" = "itemizations" +"itemize" = "itemize" +"itemized" = "itemized" +"itemizer" = "itemizer" +"itemizers" = "itemizers" +"itemizes" = "itemizes" +"itemizing" = "itemizing" +"jeopardisable" = "jeopardizable" +"jeopardisation" = "jeopardization" +"jeopardisations" = "jeopardizations" +"jeopardise" = "jeopardize" +"jeopardised" = "jeopardized" +"jeopardiser" = "jeopardizer" +"jeopardisers" = "jeopardizers" +"jeopardises" = "jeopardizes" +"jeopardising" = "jeopardizing" +"jeopardizable" = "jeopardizable" +"jeopardization" = "jeopardization" +"jeopardizations" = "jeopardizations" +"jeopardize" = "jeopardize" +"jeopardized" = "jeopardized" +"jeopardizer" = "jeopardizer" +"jeopardizers" = "jeopardizers" +"jeopardizes" = "jeopardizes" +"jeopardizing" = "jeopardizing" +"kernelisable" = "kernelizable" +"kernelisation" = "kernelization" +"kernelisations" = "kernelizations" +"kernelise" = "kernelize" +"kernelised" = "kernelized" +"kerneliser" = "kernelizer" +"kernelisers" = "kernelizers" +"kernelises" = "kernelizes" +"kernelising" = "kernelizing" +"kernelizable" = "kernelizable" +"kernelization" = "kernelization" +"kernelizations" = "kernelizations" +"kernelize" = "kernelize" +"kernelized" = "kernelized" +"kernelizer" = "kernelizer" +"kernelizers" = "kernelizers" +"kernelizes" = "kernelizes" +"kernelizing" = "kernelizing" +"legitimisable" = "legitimizable" +"legitimisation" = "legitimization" +"legitimisations" = "legitimizations" +"legitimise" = "legitimize" +"legitimised" = "legitimized" +"legitimiser" = "legitimizer" +"legitimisers" = "legitimizers" +"legitimises" = "legitimizes" +"legitimising" = "legitimizing" +"legitimizable" = "legitimizable" +"legitimization" = "legitimization" +"legitimizations" = "legitimizations" +"legitimize" = "legitimize" +"legitimized" = "legitimized" +"legitimizer" = "legitimizer" +"legitimizers" = "legitimizers" +"legitimizes" = "legitimizes" +"legitimizing" = "legitimizing" +"lemmatisable" = "lemmatizable" +"lemmatisation" = "lemmatization" +"lemmatisations" = "lemmatizations" +"lemmatise" = "lemmatize" +"lemmatised" = "lemmatized" +"lemmatiser" = "lemmatizer" +"lemmatisers" = "lemmatizers" +"lemmatises" = "lemmatizes" +"lemmatising" = "lemmatizing" +"lemmatizable" = "lemmatizable" +"lemmatization" = "lemmatization" +"lemmatizations" = "lemmatizations" +"lemmatize" = "lemmatize" +"lemmatized" = "lemmatized" +"lemmatizer" = "lemmatizer" +"lemmatizers" = "lemmatizers" +"lemmatizes" = "lemmatizes" +"lemmatizing" = "lemmatizing" +"linearisable" = "linearizable" +"linearisation" = "linearization" +"linearisations" = "linearizations" +"linearise" = "linearize" +"linearised" = "linearized" +"lineariser" = "linearizer" +"linearisers" = "linearizers" +"linearises" = "linearizes" +"linearising" = "linearizing" +"linearizable" = "linearizable" +"linearization" = "linearization" +"linearizations" = "linearizations" +"linearize" = "linearize" +"linearized" = "linearized" +"linearizer" = "linearizer" +"linearizers" = "linearizers" +"linearizes" = "linearizes" +"linearizing" = "linearizing" +"localisable" = "localizable" +"localisation" = "localization" +"localisations" = "localizations" +"localise" = "localize" +"localised" = "localized" +"localiser" = "localizer" +"localisers" = "localizers" +"localises" = "localizes" +"localising" = "localizing" +"localizable" = "localizable" +"localization" = "localization" +"localizations" = "localizations" +"localize" = "localize" +"localized" = "localized" +"localizer" = "localizer" +"localizers" = "localizers" +"localizes" = "localizes" +"localizing" = "localizing" +"materialisable" = "materializable" +"materialisation" = "materialization" +"materialisations" = "materializations" +"materialise" = "materialize" +"materialised" = "materialized" +"materialiser" = "materializer" +"materialisers" = "materializers" +"materialises" = "materializes" +"materialising" = "materializing" +"materializable" = "materializable" +"materialization" = "materialization" +"materializations" = "materializations" +"materialize" = "materialize" +"materialized" = "materialized" +"materializer" = "materializer" +"materializers" = "materializers" +"materializes" = "materializes" +"materializing" = "materializing" +"maximisable" = "maximizable" +"maximisation" = "maximization" +"maximisations" = "maximizations" +"maximise" = "maximize" +"maximised" = "maximized" +"maximiser" = "maximizer" +"maximisers" = "maximizers" +"maximises" = "maximizes" +"maximising" = "maximizing" +"maximizable" = "maximizable" +"maximization" = "maximization" +"maximizations" = "maximizations" +"maximize" = "maximize" +"maximized" = "maximized" +"maximizer" = "maximizer" +"maximizers" = "maximizers" +"maximizes" = "maximizes" +"maximizing" = "maximizing" +"mechanisable" = "mechanizable" +"mechanisation" = "mechanization" +"mechanisations" = "mechanizations" +"mechanise" = "mechanize" +"mechanised" = "mechanized" +"mechaniser" = "mechanizer" +"mechanisers" = "mechanizers" +"mechanises" = "mechanizes" +"mechanising" = "mechanizing" +"mechanizable" = "mechanizable" +"mechanization" = "mechanization" +"mechanizations" = "mechanizations" +"mechanize" = "mechanize" +"mechanized" = "mechanized" +"mechanizer" = "mechanizer" +"mechanizers" = "mechanizers" +"mechanizes" = "mechanizes" +"mechanizing" = "mechanizing" +"memoisable" = "memoizable" +"memoisation" = "memoization" +"memoisations" = "memoizations" +"memoise" = "memoize" +"memoised" = "memoized" +"memoiser" = "memoizer" +"memoisers" = "memoizers" +"memoises" = "memoizes" +"memoising" = "memoizing" +"memoizable" = "memoizable" +"memoization" = "memoization" +"memoizations" = "memoizations" +"memoize" = "memoize" +"memoized" = "memoized" +"memoizer" = "memoizer" +"memoizers" = "memoizers" +"memoizes" = "memoizes" +"memoizing" = "memoizing" +"memorisable" = "memorizable" +"memorisation" = "memorization" +"memorisations" = "memorizations" +"memorise" = "memorize" +"memorised" = "memorized" +"memoriser" = "memorizer" +"memorisers" = "memorizers" +"memorises" = "memorizes" +"memorising" = "memorizing" +"memorizable" = "memorizable" +"memorization" = "memorization" +"memorizations" = "memorizations" +"memorize" = "memorize" +"memorized" = "memorized" +"memorizer" = "memorizer" +"memorizers" = "memorizers" +"memorizes" = "memorizes" +"memorizing" = "memorizing" +"miniaturisable" = "miniaturizable" +"miniaturisation" = "miniaturization" +"miniaturisations" = "miniaturizations" +"miniaturise" = "miniaturize" +"miniaturised" = "miniaturized" +"miniaturiser" = "miniaturizer" +"miniaturisers" = "miniaturizers" +"miniaturises" = "miniaturizes" +"miniaturising" = "miniaturizing" +"miniaturizable" = "miniaturizable" +"miniaturization" = "miniaturization" +"miniaturizations" = "miniaturizations" +"miniaturize" = "miniaturize" +"miniaturized" = "miniaturized" +"miniaturizer" = "miniaturizer" +"miniaturizers" = "miniaturizers" +"miniaturizes" = "miniaturizes" +"miniaturizing" = "miniaturizing" +"minimisable" = "minimizable" +"minimisation" = "minimization" +"minimisations" = "minimizations" +"minimise" = "minimize" +"minimised" = "minimized" +"minimiser" = "minimizer" +"minimisers" = "minimizers" +"minimises" = "minimizes" +"minimising" = "minimizing" +"minimizable" = "minimizable" +"minimization" = "minimization" +"minimizations" = "minimizations" +"minimize" = "minimize" +"minimized" = "minimized" +"minimizer" = "minimizer" +"minimizers" = "minimizers" +"minimizes" = "minimizes" +"minimizing" = "minimizing" +"mobilisable" = "mobilizable" +"mobilisation" = "mobilization" +"mobilisations" = "mobilizations" +"mobilise" = "mobilize" +"mobilised" = "mobilized" +"mobiliser" = "mobilizer" +"mobilisers" = "mobilizers" +"mobilises" = "mobilizes" +"mobilising" = "mobilizing" +"mobilizable" = "mobilizable" +"mobilization" = "mobilization" +"mobilizations" = "mobilizations" +"mobilize" = "mobilize" +"mobilized" = "mobilized" +"mobilizer" = "mobilizer" +"mobilizers" = "mobilizers" +"mobilizes" = "mobilizes" +"mobilizing" = "mobilizing" +"modernisable" = "modernizable" +"modernisation" = "modernization" +"modernisations" = "modernizations" +"modernise" = "modernize" +"modernised" = "modernized" +"moderniser" = "modernizer" +"modernisers" = "modernizers" +"modernises" = "modernizes" +"modernising" = "modernizing" +"modernizable" = "modernizable" +"modernization" = "modernization" +"modernizations" = "modernizations" +"modernize" = "modernize" +"modernized" = "modernized" +"modernizer" = "modernizer" +"modernizers" = "modernizers" +"modernizes" = "modernizes" +"modernizing" = "modernizing" +"modularisable" = "modularizable" +"modularisation" = "modularization" +"modularisations" = "modularizations" +"modularise" = "modularize" +"modularised" = "modularized" +"modulariser" = "modularizer" +"modularisers" = "modularizers" +"modularises" = "modularizes" +"modularising" = "modularizing" +"modularizable" = "modularizable" +"modularization" = "modularization" +"modularizations" = "modularizations" +"modularize" = "modularize" +"modularized" = "modularized" +"modularizer" = "modularizer" +"modularizers" = "modularizers" +"modularizes" = "modularizes" +"modularizing" = "modularizing" +"monetisable" = "monetizable" +"monetisation" = "monetization" +"monetisations" = "monetizations" +"monetise" = "monetize" +"monetised" = "monetized" +"monetiser" = "monetizer" +"monetisers" = "monetizers" +"monetises" = "monetizes" +"monetising" = "monetizing" +"monetizable" = "monetizable" +"monetization" = "monetization" +"monetizations" = "monetizations" +"monetize" = "monetize" +"monetized" = "monetized" +"monetizer" = "monetizer" +"monetizers" = "monetizers" +"monetizes" = "monetizes" +"monetizing" = "monetizing" +"monomorphisable" = "monomorphizable" +"monomorphisation" = "monomorphization" +"monomorphisations" = "monomorphizations" +"monomorphise" = "monomorphize" +"monomorphised" = "monomorphized" +"monomorphiser" = "monomorphizer" +"monomorphisers" = "monomorphizers" +"monomorphises" = "monomorphizes" +"monomorphising" = "monomorphizing" +"monomorphizable" = "monomorphizable" +"monomorphization" = "monomorphization" +"monomorphizations" = "monomorphizations" +"monomorphize" = "monomorphize" +"monomorphized" = "monomorphized" +"monomorphizer" = "monomorphizer" +"monomorphizers" = "monomorphizers" +"monomorphizes" = "monomorphizes" +"monomorphizing" = "monomorphizing" +"monopolisable" = "monopolizable" +"monopolisation" = "monopolization" +"monopolisations" = "monopolizations" +"monopolise" = "monopolize" +"monopolised" = "monopolized" +"monopoliser" = "monopolizer" +"monopolisers" = "monopolizers" +"monopolises" = "monopolizes" +"monopolising" = "monopolizing" +"monopolizable" = "monopolizable" +"monopolization" = "monopolization" +"monopolizations" = "monopolizations" +"monopolize" = "monopolize" +"monopolized" = "monopolized" +"monopolizer" = "monopolizer" +"monopolizers" = "monopolizers" +"monopolizes" = "monopolizes" +"monopolizing" = "monopolizing" +"moralisable" = "moralizable" +"moralisation" = "moralization" +"moralisations" = "moralizations" +"moralise" = "moralize" +"moralised" = "moralized" +"moraliser" = "moralizer" +"moralisers" = "moralizers" +"moralises" = "moralizes" +"moralising" = "moralizing" +"moralizable" = "moralizable" +"moralization" = "moralization" +"moralizations" = "moralizations" +"moralize" = "moralize" +"moralized" = "moralized" +"moralizer" = "moralizer" +"moralizers" = "moralizers" +"moralizes" = "moralizes" +"moralizing" = "moralizing" +"neutralisable" = "neutralizable" +"neutralisation" = "neutralization" +"neutralisations" = "neutralizations" +"neutralise" = "neutralize" +"neutralised" = "neutralized" +"neutraliser" = "neutralizer" +"neutralisers" = "neutralizers" +"neutralises" = "neutralizes" +"neutralising" = "neutralizing" +"neutralizable" = "neutralizable" +"neutralization" = "neutralization" +"neutralizations" = "neutralizations" +"neutralize" = "neutralize" +"neutralized" = "neutralized" +"neutralizer" = "neutralizer" +"neutralizers" = "neutralizers" +"neutralizes" = "neutralizes" +"neutralizing" = "neutralizing" +"normalisable" = "normalizable" +"normalisation" = "normalization" +"normalisations" = "normalizations" +"normalise" = "normalize" +"normalised" = "normalized" +"normaliser" = "normalizer" +"normalisers" = "normalizers" +"normalises" = "normalizes" +"normalising" = "normalizing" +"normalizable" = "normalizable" +"normalization" = "normalization" +"normalizations" = "normalizations" +"normalize" = "normalize" +"normalized" = "normalized" +"normalizer" = "normalizer" +"normalizers" = "normalizers" +"normalizes" = "normalizes" +"normalizing" = "normalizing" +"notarisable" = "notarizable" +"notarisation" = "notarization" +"notarisations" = "notarizations" +"notarise" = "notarize" +"notarised" = "notarized" +"notariser" = "notarizer" +"notarisers" = "notarizers" +"notarises" = "notarizes" +"notarising" = "notarizing" +"notarizable" = "notarizable" +"notarization" = "notarization" +"notarizations" = "notarizations" +"notarize" = "notarize" +"notarized" = "notarized" +"notarizer" = "notarizer" +"notarizers" = "notarizers" +"notarizes" = "notarizes" +"notarizing" = "notarizing" +"operationalisable" = "operationalizable" +"operationalisation" = "operationalization" +"operationalisations" = "operationalizations" +"operationalise" = "operationalize" +"operationalised" = "operationalized" +"operationaliser" = "operationalizer" +"operationalisers" = "operationalizers" +"operationalises" = "operationalizes" +"operationalising" = "operationalizing" +"operationalizable" = "operationalizable" +"operationalization" = "operationalization" +"operationalizations" = "operationalizations" +"operationalize" = "operationalize" +"operationalized" = "operationalized" +"operationalizer" = "operationalizer" +"operationalizers" = "operationalizers" +"operationalizes" = "operationalizes" +"operationalizing" = "operationalizing" +"optimisable" = "optimizable" +"optimisation" = "optimization" +"optimisations" = "optimizations" +"optimise" = "optimize" +"optimised" = "optimized" +"optimiser" = "optimizer" +"optimisers" = "optimizers" +"optimises" = "optimizes" +"optimising" = "optimizing" +"optimizable" = "optimizable" +"optimization" = "optimization" +"optimizations" = "optimizations" +"optimize" = "optimize" +"optimized" = "optimized" +"optimizer" = "optimizer" +"optimizers" = "optimizers" +"optimizes" = "optimizes" +"optimizing" = "optimizing" +"ordinalisable" = "ordinalizable" +"ordinalisation" = "ordinalization" +"ordinalisations" = "ordinalizations" +"ordinalise" = "ordinalize" +"ordinalised" = "ordinalized" +"ordinaliser" = "ordinalizer" +"ordinalisers" = "ordinalizers" +"ordinalises" = "ordinalizes" +"ordinalising" = "ordinalizing" +"ordinalizable" = "ordinalizable" +"ordinalization" = "ordinalization" +"ordinalizations" = "ordinalizations" +"ordinalize" = "ordinalize" +"ordinalized" = "ordinalized" +"ordinalizer" = "ordinalizer" +"ordinalizers" = "ordinalizers" +"ordinalizes" = "ordinalizes" +"ordinalizing" = "ordinalizing" +"organisable" = "organizable" +"organisation" = "organization" +"organisations" = "organizations" +"organise" = "organize" +"organised" = "organized" +"organiser" = "organizer" +"organisers" = "organizers" +"organises" = "organizes" +"organising" = "organizing" +"organizable" = "organizable" +"organization" = "organization" +"organizations" = "organizations" +"organize" = "organize" +"organized" = "organized" +"organizer" = "organizer" +"organizers" = "organizers" +"organizes" = "organizes" +"organizing" = "organizing" +"oxendict" = "oxendict" +"palettisable" = "palettizable" +"palettisation" = "palettization" +"palettisations" = "palettizations" +"palettise" = "palettize" +"palettised" = "palettized" +"palettiser" = "palettizer" +"palettisers" = "palettizers" +"palettises" = "palettizes" +"palettising" = "palettizing" +"palettizable" = "palettizable" +"palettization" = "palettization" +"palettizations" = "palettizations" +"palettize" = "palettize" +"palettized" = "palettized" +"palettizer" = "palettizer" +"palettizers" = "palettizers" +"palettizes" = "palettizes" +"palettizing" = "palettizing" +"parallelisable" = "parallelizable" +"parallelisation" = "parallelization" +"parallelisations" = "parallelizations" +"parallelise" = "parallelize" +"parallelised" = "parallelized" +"paralleliser" = "parallelizer" +"parallelisers" = "parallelizers" +"parallelises" = "parallelizes" +"parallelising" = "parallelizing" +"parallelizable" = "parallelizable" +"parallelization" = "parallelization" +"parallelizations" = "parallelizations" +"parallelize" = "parallelize" +"parallelized" = "parallelized" +"parallelizer" = "parallelizer" +"parallelizers" = "parallelizers" +"parallelizes" = "parallelizes" +"parallelizing" = "parallelizing" +"parameterisable" = "parameterizable" +"parameterisation" = "parameterization" +"parameterisations" = "parameterizations" +"parameterise" = "parameterize" +"parameterised" = "parameterized" +"parameteriser" = "parameterizer" +"parameterisers" = "parameterizers" +"parameterises" = "parameterizes" +"parameterising" = "parameterizing" +"parameterizable" = "parameterizable" +"parameterization" = "parameterization" +"parameterizations" = "parameterizations" +"parameterize" = "parameterize" +"parameterized" = "parameterized" +"parameterizer" = "parameterizer" +"parameterizers" = "parameterizers" +"parameterizes" = "parameterizes" +"parameterizing" = "parameterizing" +"parametrisable" = "parametrizable" +"parametrisation" = "parametrization" +"parametrisations" = "parametrizations" +"parametrise" = "parametrize" +"parametrised" = "parametrized" +"parametriser" = "parametrizer" +"parametrisers" = "parametrizers" +"parametrises" = "parametrizes" +"parametrising" = "parametrizing" +"parametrizable" = "parametrizable" +"parametrization" = "parametrization" +"parametrizations" = "parametrizations" +"parametrize" = "parametrize" +"parametrized" = "parametrized" +"parametrizer" = "parametrizer" +"parametrizers" = "parametrizers" +"parametrizes" = "parametrizes" +"parametrizing" = "parametrizing" +"parenthesisable" = "parenthesizable" +"parenthesisation" = "parenthesization" +"parenthesisations" = "parenthesizations" +"parenthesise" = "parenthesize" +"parenthesised" = "parenthesized" +"parenthesiser" = "parenthesizer" +"parenthesisers" = "parenthesizers" +"parenthesises" = "parenthesizes" +"parenthesising" = "parenthesizing" +"parenthesizable" = "parenthesizable" +"parenthesization" = "parenthesization" +"parenthesizations" = "parenthesizations" +"parenthesize" = "parenthesize" +"parenthesized" = "parenthesized" +"parenthesizer" = "parenthesizer" +"parenthesizers" = "parenthesizers" +"parenthesizes" = "parenthesizes" +"parenthesizing" = "parenthesizing" +"penalisable" = "penalizable" +"penalisation" = "penalization" +"penalisations" = "penalizations" +"penalise" = "penalize" +"penalised" = "penalized" +"penaliser" = "penalizer" +"penalisers" = "penalizers" +"penalises" = "penalizes" +"penalising" = "penalizing" +"penalizable" = "penalizable" +"penalization" = "penalization" +"penalizations" = "penalizations" +"penalize" = "penalize" +"penalized" = "penalized" +"penalizer" = "penalizer" +"penalizers" = "penalizers" +"penalizes" = "penalizes" +"penalizing" = "penalizing" +"personalisable" = "personalizable" +"personalisation" = "personalization" +"personalisations" = "personalizations" +"personalise" = "personalize" +"personalised" = "personalized" +"personaliser" = "personalizer" +"personalisers" = "personalizers" +"personalises" = "personalizes" +"personalising" = "personalizing" +"personalizable" = "personalizable" +"personalization" = "personalization" +"personalizations" = "personalizations" +"personalize" = "personalize" +"personalized" = "personalized" +"personalizer" = "personalizer" +"personalizers" = "personalizers" +"personalizes" = "personalizes" +"personalizing" = "personalizing" +"pluralisable" = "pluralizable" +"pluralisation" = "pluralization" +"pluralisations" = "pluralizations" +"pluralise" = "pluralize" +"pluralised" = "pluralized" +"pluraliser" = "pluralizer" +"pluralisers" = "pluralizers" +"pluralises" = "pluralizes" +"pluralising" = "pluralizing" +"pluralizable" = "pluralizable" +"pluralization" = "pluralization" +"pluralizations" = "pluralizations" +"pluralize" = "pluralize" +"pluralized" = "pluralized" +"pluralizer" = "pluralizer" +"pluralizers" = "pluralizers" +"pluralizes" = "pluralizes" +"pluralizing" = "pluralizing" +"popularisable" = "popularizable" +"popularisation" = "popularization" +"popularisations" = "popularizations" +"popularise" = "popularize" +"popularised" = "popularized" +"populariser" = "popularizer" +"popularisers" = "popularizers" +"popularises" = "popularizes" +"popularising" = "popularizing" +"popularizable" = "popularizable" +"popularization" = "popularization" +"popularizations" = "popularizations" +"popularize" = "popularize" +"popularized" = "popularized" +"popularizer" = "popularizer" +"popularizers" = "popularizers" +"popularizes" = "popularizes" +"popularizing" = "popularizing" +"prioritisable" = "prioritizable" +"prioritisation" = "prioritization" +"prioritisations" = "prioritizations" +"prioritise" = "prioritize" +"prioritised" = "prioritized" +"prioritiser" = "prioritizer" +"prioritisers" = "prioritizers" +"prioritises" = "prioritizes" +"prioritising" = "prioritizing" +"prioritizable" = "prioritizable" +"prioritization" = "prioritization" +"prioritizations" = "prioritizations" +"prioritize" = "prioritize" +"prioritized" = "prioritized" +"prioritizer" = "prioritizer" +"prioritizers" = "prioritizers" +"prioritizes" = "prioritizes" +"prioritizing" = "prioritizing" +"privatisable" = "privatizable" +"privatisation" = "privatization" +"privatisations" = "privatizations" +"privatise" = "privatize" +"privatised" = "privatized" +"privatiser" = "privatizer" +"privatisers" = "privatizers" +"privatises" = "privatizes" +"privatising" = "privatizing" +"privatizable" = "privatizable" +"privatization" = "privatization" +"privatizations" = "privatizations" +"privatize" = "privatize" +"privatized" = "privatized" +"privatizer" = "privatizer" +"privatizers" = "privatizers" +"privatizes" = "privatizes" +"privatizing" = "privatizing" +"productisable" = "productizable" +"productisation" = "productization" +"productisations" = "productizations" +"productise" = "productize" +"productised" = "productized" +"productiser" = "productizer" +"productisers" = "productizers" +"productises" = "productizes" +"productising" = "productizing" +"productizable" = "productizable" +"productization" = "productization" +"productizations" = "productizations" +"productize" = "productize" +"productized" = "productized" +"productizer" = "productizer" +"productizers" = "productizers" +"productizes" = "productizes" +"productizing" = "productizing" +"publicisable" = "publicizable" +"publicisation" = "publicization" +"publicisations" = "publicizations" +"publicise" = "publicize" +"publicised" = "publicized" +"publiciser" = "publicizer" +"publicisers" = "publicizers" +"publicises" = "publicizes" +"publicising" = "publicizing" +"publicizable" = "publicizable" +"publicization" = "publicization" +"publicizations" = "publicizations" +"publicize" = "publicize" +"publicized" = "publicized" +"publicizer" = "publicizer" +"publicizers" = "publicizers" +"publicizes" = "publicizes" +"publicizing" = "publicizing" +"quantisable" = "quantizable" +"quantisation" = "quantization" +"quantisations" = "quantizations" +"quantise" = "quantize" +"quantised" = "quantized" +"quantiser" = "quantizer" +"quantisers" = "quantizers" +"quantises" = "quantizes" +"quantising" = "quantizing" +"quantizable" = "quantizable" +"quantization" = "quantization" +"quantizations" = "quantizations" +"quantize" = "quantize" +"quantized" = "quantized" +"quantizer" = "quantizer" +"quantizers" = "quantizers" +"quantizes" = "quantizes" +"quantizing" = "quantizing" +"randomisable" = "randomizable" +"randomisation" = "randomization" +"randomisations" = "randomizations" +"randomise" = "randomize" +"randomised" = "randomized" +"randomiser" = "randomizer" +"randomisers" = "randomizers" +"randomises" = "randomizes" +"randomising" = "randomizing" +"randomizable" = "randomizable" +"randomization" = "randomization" +"randomizations" = "randomizations" +"randomize" = "randomize" +"randomized" = "randomized" +"randomizer" = "randomizer" +"randomizers" = "randomizers" +"randomizes" = "randomizes" +"randomizing" = "randomizing" +"rasterisable" = "rasterizable" +"rasterisation" = "rasterization" +"rasterisations" = "rasterizations" +"rasterise" = "rasterize" +"rasterised" = "rasterized" +"rasteriser" = "rasterizer" +"rasterisers" = "rasterizers" +"rasterises" = "rasterizes" +"rasterising" = "rasterizing" +"rasterizable" = "rasterizable" +"rasterization" = "rasterization" +"rasterizations" = "rasterizations" +"rasterize" = "rasterize" +"rasterized" = "rasterized" +"rasterizer" = "rasterizer" +"rasterizers" = "rasterizers" +"rasterizes" = "rasterizes" +"rasterizing" = "rasterizing" +"rationalisable" = "rationalizable" +"rationalisation" = "rationalization" +"rationalisations" = "rationalizations" +"rationalise" = "rationalize" +"rationalised" = "rationalized" +"rationaliser" = "rationalizer" +"rationalisers" = "rationalizers" +"rationalises" = "rationalizes" +"rationalising" = "rationalizing" +"rationalizable" = "rationalizable" +"rationalization" = "rationalization" +"rationalizations" = "rationalizations" +"rationalize" = "rationalize" +"rationalized" = "rationalized" +"rationalizer" = "rationalizer" +"rationalizers" = "rationalizers" +"rationalizes" = "rationalizes" +"rationalizing" = "rationalizing" +"realisable" = "realizable" +"realisation" = "realization" +"realisations" = "realizations" +"realise" = "realize" +"realised" = "realized" +"realiser" = "realizer" +"realisers" = "realizers" +"realises" = "realizes" +"realising" = "realizing" +"realizable" = "realizable" +"realization" = "realization" +"realizations" = "realizations" +"realize" = "realize" +"realized" = "realized" +"realizer" = "realizer" +"realizers" = "realizers" +"realizes" = "realizes" +"realizing" = "realizing" +"recognisable" = "recognizable" +"recognisation" = "recognization" +"recognisations" = "recognizations" +"recognise" = "recognize" +"recognised" = "recognized" +"recogniser" = "recognizer" +"recognisers" = "recognizers" +"recognises" = "recognizes" +"recognising" = "recognizing" +"recognizable" = "recognizable" +"recognization" = "recognization" +"recognizations" = "recognizations" +"recognize" = "recognize" +"recognized" = "recognized" +"recognizer" = "recognizer" +"recognizers" = "recognizers" +"recognizes" = "recognizes" +"recognizing" = "recognizing" +"regularisable" = "regularizable" +"regularisation" = "regularization" +"regularisations" = "regularizations" +"regularise" = "regularize" +"regularised" = "regularized" +"regulariser" = "regularizer" +"regularisers" = "regularizers" +"regularises" = "regularizes" +"regularising" = "regularizing" +"regularizable" = "regularizable" +"regularization" = "regularization" +"regularizations" = "regularizations" +"regularize" = "regularize" +"regularized" = "regularized" +"regularizer" = "regularizer" +"regularizers" = "regularizers" +"regularizes" = "regularizes" +"regularizing" = "regularizing" +"reinitialisable" = "reinitializable" +"reinitialisation" = "reinitialization" +"reinitialisations" = "reinitializations" +"reinitialise" = "reinitialize" +"reinitialised" = "reinitialized" +"reinitialiser" = "reinitializer" +"reinitialisers" = "reinitializers" +"reinitialises" = "reinitializes" +"reinitialising" = "reinitializing" +"reinitializable" = "reinitializable" +"reinitialization" = "reinitialization" +"reinitializations" = "reinitializations" +"reinitialize" = "reinitialize" +"reinitialized" = "reinitialized" +"reinitializer" = "reinitializer" +"reinitializers" = "reinitializers" +"reinitializes" = "reinitializes" +"reinitializing" = "reinitializing" +"reorganisable" = "reorganizable" +"reorganisation" = "reorganization" +"reorganisations" = "reorganizations" +"reorganise" = "reorganize" +"reorganised" = "reorganized" +"reorganiser" = "reorganizer" +"reorganisers" = "reorganizers" +"reorganises" = "reorganizes" +"reorganising" = "reorganizing" +"reorganizable" = "reorganizable" +"reorganization" = "reorganization" +"reorganizations" = "reorganizations" +"reorganize" = "reorganize" +"reorganized" = "reorganized" +"reorganizer" = "reorganizer" +"reorganizers" = "reorganizers" +"reorganizes" = "reorganizes" +"reorganizing" = "reorganizing" +"reserialisable" = "reserializable" +"reserialisation" = "reserialization" +"reserialisations" = "reserializations" +"reserialise" = "reserialize" +"reserialised" = "reserialized" +"reserialiser" = "reserializer" +"reserialisers" = "reserializers" +"reserialises" = "reserializes" +"reserialising" = "reserializing" +"reserializable" = "reserializable" +"reserialization" = "reserialization" +"reserializations" = "reserializations" +"reserialize" = "reserialize" +"reserialized" = "reserialized" +"reserializer" = "reserializer" +"reserializers" = "reserializers" +"reserializes" = "reserializes" +"reserializing" = "reserializing" +"resynchronisable" = "resynchronizable" +"resynchronisation" = "resynchronization" +"resynchronisations" = "resynchronizations" +"resynchronise" = "resynchronize" +"resynchronised" = "resynchronized" +"resynchroniser" = "resynchronizer" +"resynchronisers" = "resynchronizers" +"resynchronises" = "resynchronizes" +"resynchronising" = "resynchronizing" +"resynchronizable" = "resynchronizable" +"resynchronization" = "resynchronization" +"resynchronizations" = "resynchronizations" +"resynchronize" = "resynchronize" +"resynchronized" = "resynchronized" +"resynchronizer" = "resynchronizer" +"resynchronizers" = "resynchronizers" +"resynchronizes" = "resynchronizes" +"resynchronizing" = "resynchronizing" +"retokenisable" = "retokenizable" +"retokenisation" = "retokenization" +"retokenisations" = "retokenizations" +"retokenise" = "retokenize" +"retokenised" = "retokenized" +"retokeniser" = "retokenizer" +"retokenisers" = "retokenizers" +"retokenises" = "retokenizes" +"retokenising" = "retokenizing" +"retokenizable" = "retokenizable" +"retokenization" = "retokenization" +"retokenizations" = "retokenizations" +"retokenize" = "retokenize" +"retokenized" = "retokenized" +"retokenizer" = "retokenizer" +"retokenizers" = "retokenizers" +"retokenizes" = "retokenizes" +"retokenizing" = "retokenizing" +"romanticisable" = "romanticizable" +"romanticisation" = "romanticization" +"romanticisations" = "romanticizations" +"romanticise" = "romanticize" +"romanticised" = "romanticized" +"romanticiser" = "romanticizer" +"romanticisers" = "romanticizers" +"romanticises" = "romanticizes" +"romanticising" = "romanticizing" +"romanticizable" = "romanticizable" +"romanticization" = "romanticization" +"romanticizations" = "romanticizations" +"romanticize" = "romanticize" +"romanticized" = "romanticized" +"romanticizer" = "romanticizer" +"romanticizers" = "romanticizers" +"romanticizes" = "romanticizes" +"romanticizing" = "romanticizing" +"sanitisable" = "sanitizable" +"sanitisation" = "sanitization" +"sanitisations" = "sanitizations" +"sanitise" = "sanitize" +"sanitised" = "sanitized" +"sanitiser" = "sanitizer" +"sanitisers" = "sanitizers" +"sanitises" = "sanitizes" +"sanitising" = "sanitizing" +"sanitizable" = "sanitizable" +"sanitization" = "sanitization" +"sanitizations" = "sanitizations" +"sanitize" = "sanitize" +"sanitized" = "sanitized" +"sanitizer" = "sanitizer" +"sanitizers" = "sanitizers" +"sanitizes" = "sanitizes" +"sanitizing" = "sanitizing" +"scrutinisable" = "scrutinizable" +"scrutinisation" = "scrutinization" +"scrutinisations" = "scrutinizations" +"scrutinise" = "scrutinize" +"scrutinised" = "scrutinized" +"scrutiniser" = "scrutinizer" +"scrutinisers" = "scrutinizers" +"scrutinises" = "scrutinizes" +"scrutinising" = "scrutinizing" +"scrutinizable" = "scrutinizable" +"scrutinization" = "scrutinization" +"scrutinizations" = "scrutinizations" +"scrutinize" = "scrutinize" +"scrutinized" = "scrutinized" +"scrutinizer" = "scrutinizer" +"scrutinizers" = "scrutinizers" +"scrutinizes" = "scrutinizes" +"scrutinizing" = "scrutinizing" +"serialisable" = "serializable" +"serialisation" = "serialization" +"serialisations" = "serializations" +"serialise" = "serialize" +"serialised" = "serialized" +"serialiser" = "serializer" +"serialisers" = "serializers" +"serialises" = "serializes" +"serialising" = "serializing" +"serializable" = "serializable" +"serialization" = "serialization" +"serializations" = "serializations" +"serialize" = "serialize" +"serialized" = "serialized" +"serializer" = "serializer" +"serializers" = "serializers" +"serializes" = "serializes" +"serializing" = "serializing" +"sexualisable" = "sexualizable" +"sexualisation" = "sexualization" +"sexualisations" = "sexualizations" +"sexualise" = "sexualize" +"sexualised" = "sexualized" +"sexualiser" = "sexualizer" +"sexualisers" = "sexualizers" +"sexualises" = "sexualizes" +"sexualising" = "sexualizing" +"sexualizable" = "sexualizable" +"sexualization" = "sexualization" +"sexualizations" = "sexualizations" +"sexualize" = "sexualize" +"sexualized" = "sexualized" +"sexualizer" = "sexualizer" +"sexualizers" = "sexualizers" +"sexualizes" = "sexualizes" +"sexualizing" = "sexualizing" +"singularisable" = "singularizable" +"singularisation" = "singularization" +"singularisations" = "singularizations" +"singularise" = "singularize" +"singularised" = "singularized" +"singulariser" = "singularizer" +"singularisers" = "singularizers" +"singularises" = "singularizes" +"singularising" = "singularizing" +"singularizable" = "singularizable" +"singularization" = "singularization" +"singularizations" = "singularizations" +"singularize" = "singularize" +"singularized" = "singularized" +"singularizer" = "singularizer" +"singularizers" = "singularizers" +"singularizes" = "singularizes" +"singularizing" = "singularizing" +"socialisable" = "socializable" +"socialisation" = "socialization" +"socialisations" = "socializations" +"socialise" = "socialize" +"socialised" = "socialized" +"socialiser" = "socializer" +"socialisers" = "socializers" +"socialises" = "socializes" +"socialising" = "socializing" +"socializable" = "socializable" +"socialization" = "socialization" +"socializations" = "socializations" +"socialize" = "socialize" +"socialized" = "socialized" +"socializer" = "socializer" +"socializers" = "socializers" +"socializes" = "socializes" +"socializing" = "socializing" +"specialisable" = "specializable" +"specialisation" = "specialization" +"specialisations" = "specializations" +"specialise" = "specialize" +"specialised" = "specialized" +"specialiser" = "specializer" +"specialisers" = "specializers" +"specialises" = "specializes" +"specialising" = "specializing" +"specializable" = "specializable" +"specialization" = "specialization" +"specializations" = "specializations" +"specialize" = "specialize" +"specialized" = "specialized" +"specializer" = "specializer" +"specializers" = "specializers" +"specializes" = "specializes" +"specializing" = "specializing" +"stabilisable" = "stabilizable" +"stabilisation" = "stabilization" +"stabilisations" = "stabilizations" +"stabilise" = "stabilize" +"stabilised" = "stabilized" +"stabiliser" = "stabilizer" +"stabilisers" = "stabilizers" +"stabilises" = "stabilizes" +"stabilising" = "stabilizing" +"stabilizable" = "stabilizable" +"stabilization" = "stabilization" +"stabilizations" = "stabilizations" +"stabilize" = "stabilize" +"stabilized" = "stabilized" +"stabilizer" = "stabilizer" +"stabilizers" = "stabilizers" +"stabilizes" = "stabilizes" +"stabilizing" = "stabilizing" +"standardisable" = "standardizable" +"standardisation" = "standardization" +"standardisations" = "standardizations" +"standardise" = "standardize" +"standardised" = "standardized" +"standardiser" = "standardizer" +"standardisers" = "standardizers" +"standardises" = "standardizes" +"standardising" = "standardizing" +"standardizable" = "standardizable" +"standardization" = "standardization" +"standardizations" = "standardizations" +"standardize" = "standardize" +"standardized" = "standardized" +"standardizer" = "standardizer" +"standardizers" = "standardizers" +"standardizes" = "standardizes" +"standardizing" = "standardizing" +"stylisable" = "stylizable" +"stylisation" = "stylization" +"stylisations" = "stylizations" +"stylise" = "stylize" +"stylised" = "stylized" +"styliser" = "stylizer" +"stylisers" = "stylizers" +"stylises" = "stylizes" +"stylising" = "stylizing" +"stylizable" = "stylizable" +"stylization" = "stylization" +"stylizations" = "stylizations" +"stylize" = "stylize" +"stylized" = "stylized" +"stylizer" = "stylizer" +"stylizers" = "stylizers" +"stylizes" = "stylizes" +"stylizing" = "stylizing" +"subsidisable" = "subsidizable" +"subsidisation" = "subsidization" +"subsidisations" = "subsidizations" +"subsidise" = "subsidize" +"subsidised" = "subsidized" +"subsidiser" = "subsidizer" +"subsidisers" = "subsidizers" +"subsidises" = "subsidizes" +"subsidising" = "subsidizing" +"subsidizable" = "subsidizable" +"subsidization" = "subsidization" +"subsidizations" = "subsidizations" +"subsidize" = "subsidize" +"subsidized" = "subsidized" +"subsidizer" = "subsidizer" +"subsidizers" = "subsidizers" +"subsidizes" = "subsidizes" +"subsidizing" = "subsidizing" +"summarisable" = "summarizable" +"summarisation" = "summarization" +"summarisations" = "summarizations" +"summarise" = "summarize" +"summarised" = "summarized" +"summariser" = "summarizer" +"summarisers" = "summarizers" +"summarises" = "summarizes" +"summarising" = "summarizing" +"summarizable" = "summarizable" +"summarization" = "summarization" +"summarizations" = "summarizations" +"summarize" = "summarize" +"summarized" = "summarized" +"summarizer" = "summarizer" +"summarizers" = "summarizers" +"summarizes" = "summarizes" +"summarizing" = "summarizing" +"symbolisable" = "symbolizable" +"symbolisation" = "symbolization" +"symbolisations" = "symbolizations" +"symbolise" = "symbolize" +"symbolised" = "symbolized" +"symboliser" = "symbolizer" +"symbolisers" = "symbolizers" +"symbolises" = "symbolizes" +"symbolising" = "symbolizing" +"symbolizable" = "symbolizable" +"symbolization" = "symbolization" +"symbolizations" = "symbolizations" +"symbolize" = "symbolize" +"symbolized" = "symbolized" +"symbolizer" = "symbolizer" +"symbolizers" = "symbolizers" +"symbolizes" = "symbolizes" +"symbolizing" = "symbolizing" +"synchronisable" = "synchronizable" +"synchronisation" = "synchronization" +"synchronisations" = "synchronizations" +"synchronise" = "synchronize" +"synchronised" = "synchronized" +"synchroniser" = "synchronizer" +"synchronisers" = "synchronizers" +"synchronises" = "synchronizes" +"synchronising" = "synchronizing" +"synchronizable" = "synchronizable" +"synchronization" = "synchronization" +"synchronizations" = "synchronizations" +"synchronize" = "synchronize" +"synchronized" = "synchronized" +"synchronizer" = "synchronizer" +"synchronizers" = "synchronizers" +"synchronizes" = "synchronizes" +"synchronizing" = "synchronizing" +"synthesisable" = "synthesizable" +"synthesisation" = "synthesization" +"synthesisations" = "synthesizations" +"synthesise" = "synthesize" +"synthesised" = "synthesized" +"synthesiser" = "synthesizer" +"synthesisers" = "synthesizers" +"synthesises" = "synthesizes" +"synthesising" = "synthesizing" +"synthesizable" = "synthesizable" +"synthesization" = "synthesization" +"synthesizations" = "synthesizations" +"synthesize" = "synthesize" +"synthesized" = "synthesized" +"synthesizer" = "synthesizer" +"synthesizers" = "synthesizers" +"synthesizes" = "synthesizes" +"synthesizing" = "synthesizing" +"systematisable" = "systematizable" +"systematisation" = "systematization" +"systematisations" = "systematizations" +"systematise" = "systematize" +"systematised" = "systematized" +"systematiser" = "systematizer" +"systematisers" = "systematizers" +"systematises" = "systematizes" +"systematising" = "systematizing" +"systematizable" = "systematizable" +"systematization" = "systematization" +"systematizations" = "systematizations" +"systematize" = "systematize" +"systematized" = "systematized" +"systematizer" = "systematizer" +"systematizers" = "systematizers" +"systematizes" = "systematizes" +"systematizing" = "systematizing" +"systemisable" = "systemizable" +"systemisation" = "systemization" +"systemisations" = "systemizations" +"systemise" = "systemize" +"systemised" = "systemized" +"systemiser" = "systemizer" +"systemisers" = "systemizers" +"systemises" = "systemizes" +"systemising" = "systemizing" +"systemizable" = "systemizable" +"systemization" = "systemization" +"systemizations" = "systemizations" +"systemize" = "systemize" +"systemized" = "systemized" +"systemizer" = "systemizer" +"systemizers" = "systemizers" +"systemizes" = "systemizes" +"systemizing" = "systemizing" +"templatisable" = "templatizable" +"templatisation" = "templatization" +"templatisations" = "templatizations" +"templatise" = "templatize" +"templatised" = "templatized" +"templatiser" = "templatizer" +"templatisers" = "templatizers" +"templatises" = "templatizes" +"templatising" = "templatizing" +"templatizable" = "templatizable" +"templatization" = "templatization" +"templatizations" = "templatizations" +"templatize" = "templatize" +"templatized" = "templatized" +"templatizer" = "templatizer" +"templatizers" = "templatizers" +"templatizes" = "templatizes" +"templatizing" = "templatizing" +"terminalisable" = "terminalizable" +"terminalisation" = "terminalization" +"terminalisations" = "terminalizations" +"terminalise" = "terminalize" +"terminalised" = "terminalized" +"terminaliser" = "terminalizer" +"terminalisers" = "terminalizers" +"terminalises" = "terminalizes" +"terminalising" = "terminalizing" +"terminalizable" = "terminalizable" +"terminalization" = "terminalization" +"terminalizations" = "terminalizations" +"terminalize" = "terminalize" +"terminalized" = "terminalized" +"terminalizer" = "terminalizer" +"terminalizers" = "terminalizers" +"terminalizes" = "terminalizes" +"terminalizing" = "terminalizing" +"theorisable" = "theorizable" +"theorisation" = "theorization" +"theorisations" = "theorizations" +"theorise" = "theorize" +"theorised" = "theorized" +"theoriser" = "theorizer" +"theorisers" = "theorizers" +"theorises" = "theorizes" +"theorising" = "theorizing" +"theorizable" = "theorizable" +"theorization" = "theorization" +"theorizations" = "theorizations" +"theorize" = "theorize" +"theorized" = "theorized" +"theorizer" = "theorizer" +"theorizers" = "theorizers" +"theorizes" = "theorizes" +"theorizing" = "theorizing" +"tokenisable" = "tokenizable" +"tokenisation" = "tokenization" +"tokenisations" = "tokenizations" +"tokenise" = "tokenize" +"tokenised" = "tokenized" +"tokeniser" = "tokenizer" +"tokenisers" = "tokenizers" +"tokenises" = "tokenizes" +"tokenising" = "tokenizing" +"tokenizable" = "tokenizable" +"tokenization" = "tokenization" +"tokenizations" = "tokenizations" +"tokenize" = "tokenize" +"tokenized" = "tokenized" +"tokenizer" = "tokenizer" +"tokenizers" = "tokenizers" +"tokenizes" = "tokenizes" +"tokenizing" = "tokenizing" +"trivialisable" = "trivializable" +"trivialisation" = "trivialization" +"trivialisations" = "trivializations" +"trivialise" = "trivialize" +"trivialised" = "trivialized" +"trivialiser" = "trivializer" +"trivialisers" = "trivializers" +"trivialises" = "trivializes" +"trivialising" = "trivializing" +"trivializable" = "trivializable" +"trivialization" = "trivialization" +"trivializations" = "trivializations" +"trivialize" = "trivialize" +"trivialized" = "trivialized" +"trivializer" = "trivializer" +"trivializers" = "trivializers" +"trivializes" = "trivializes" +"trivializing" = "trivializing" +"unauthorisable" = "unauthorizable" +"unauthorisation" = "unauthorization" +"unauthorisations" = "unauthorizations" +"unauthorise" = "unauthorize" +"unauthorised" = "unauthorized" +"unauthoriser" = "unauthorizer" +"unauthorisers" = "unauthorizers" +"unauthorises" = "unauthorizes" +"unauthorising" = "unauthorizing" +"unauthorizable" = "unauthorizable" +"unauthorization" = "unauthorization" +"unauthorizations" = "unauthorizations" +"unauthorize" = "unauthorize" +"unauthorized" = "unauthorized" +"unauthorizer" = "unauthorizer" +"unauthorizers" = "unauthorizers" +"unauthorizes" = "unauthorizes" +"unauthorizing" = "unauthorizing" +"uncategorisable" = "uncategorizable" +"uncategorisation" = "uncategorization" +"uncategorisations" = "uncategorizations" +"uncategorise" = "uncategorize" +"uncategorised" = "uncategorized" +"uncategoriser" = "uncategorizer" +"uncategorisers" = "uncategorizers" +"uncategorises" = "uncategorizes" +"uncategorising" = "uncategorizing" +"uncategorizable" = "uncategorizable" +"uncategorization" = "uncategorization" +"uncategorizations" = "uncategorizations" +"uncategorize" = "uncategorize" +"uncategorized" = "uncategorized" +"uncategorizer" = "uncategorizer" +"uncategorizers" = "uncategorizers" +"uncategorizes" = "uncategorizes" +"uncategorizing" = "uncategorizing" +"uninitialisable" = "uninitializable" +"uninitialisation" = "uninitialization" +"uninitialisations" = "uninitializations" +"uninitialise" = "uninitialize" +"uninitialised" = "uninitialized" +"uninitialiser" = "uninitializer" +"uninitialisers" = "uninitializers" +"uninitialises" = "uninitializes" +"uninitialising" = "uninitializing" +"uninitializable" = "uninitializable" +"uninitialization" = "uninitialization" +"uninitializations" = "uninitializations" +"uninitialize" = "uninitialize" +"uninitialized" = "uninitialized" +"uninitializer" = "uninitializer" +"uninitializers" = "uninitializers" +"uninitializes" = "uninitializes" +"uninitializing" = "uninitializing" +"unlocalisable" = "unlocalizable" +"unlocalisation" = "unlocalization" +"unlocalisations" = "unlocalizations" +"unlocalise" = "unlocalize" +"unlocalised" = "unlocalized" +"unlocaliser" = "unlocalizer" +"unlocalisers" = "unlocalizers" +"unlocalises" = "unlocalizes" +"unlocalising" = "unlocalizing" +"unlocalizable" = "unlocalizable" +"unlocalization" = "unlocalization" +"unlocalizations" = "unlocalizations" +"unlocalize" = "unlocalize" +"unlocalized" = "unlocalized" +"unlocalizer" = "unlocalizer" +"unlocalizers" = "unlocalizers" +"unlocalizes" = "unlocalizes" +"unlocalizing" = "unlocalizing" +"unoptimisable" = "unoptimizable" +"unoptimisation" = "unoptimization" +"unoptimisations" = "unoptimizations" +"unoptimise" = "unoptimize" +"unoptimised" = "unoptimized" +"unoptimiser" = "unoptimizer" +"unoptimisers" = "unoptimizers" +"unoptimises" = "unoptimizes" +"unoptimising" = "unoptimizing" +"unoptimizable" = "unoptimizable" +"unoptimization" = "unoptimization" +"unoptimizations" = "unoptimizations" +"unoptimize" = "unoptimize" +"unoptimized" = "unoptimized" +"unoptimizer" = "unoptimizer" +"unoptimizers" = "unoptimizers" +"unoptimizes" = "unoptimizes" +"unoptimizing" = "unoptimizing" +"unparameterisable" = "unparameterizable" +"unparameterisation" = "unparameterization" +"unparameterisations" = "unparameterizations" +"unparameterise" = "unparameterize" +"unparameterised" = "unparameterized" +"unparameteriser" = "unparameterizer" +"unparameterisers" = "unparameterizers" +"unparameterises" = "unparameterizes" +"unparameterising" = "unparameterizing" +"unparameterizable" = "unparameterizable" +"unparameterization" = "unparameterization" +"unparameterizations" = "unparameterizations" +"unparameterize" = "unparameterize" +"unparameterized" = "unparameterized" +"unparameterizer" = "unparameterizer" +"unparameterizers" = "unparameterizers" +"unparameterizes" = "unparameterizes" +"unparameterizing" = "unparameterizing" +"unrecognisable" = "unrecognizable" +"unrecognisation" = "unrecognization" +"unrecognisations" = "unrecognizations" +"unrecognise" = "unrecognize" +"unrecognised" = "unrecognized" +"unrecogniser" = "unrecognizer" +"unrecognisers" = "unrecognizers" +"unrecognises" = "unrecognizes" +"unrecognising" = "unrecognizing" +"unrecognizable" = "unrecognizable" +"unrecognization" = "unrecognization" +"unrecognizations" = "unrecognizations" +"unrecognize" = "unrecognize" +"unrecognized" = "unrecognized" +"unrecognizer" = "unrecognizer" +"unrecognizers" = "unrecognizers" +"unrecognizes" = "unrecognizes" +"unrecognizing" = "unrecognizing" +"unsynchronisable" = "unsynchronizable" +"unsynchronisation" = "unsynchronization" +"unsynchronisations" = "unsynchronizations" +"unsynchronise" = "unsynchronize" +"unsynchronised" = "unsynchronized" +"unsynchroniser" = "unsynchronizer" +"unsynchronisers" = "unsynchronizers" +"unsynchronises" = "unsynchronizes" +"unsynchronising" = "unsynchronizing" +"unsynchronizable" = "unsynchronizable" +"unsynchronization" = "unsynchronization" +"unsynchronizations" = "unsynchronizations" +"unsynchronize" = "unsynchronize" +"unsynchronized" = "unsynchronized" +"unsynchronizer" = "unsynchronizer" +"unsynchronizers" = "unsynchronizers" +"unsynchronizes" = "unsynchronizes" +"unsynchronizing" = "unsynchronizing" +"utilisable" = "utilizable" +"utilisation" = "utilization" +"utilisations" = "utilizations" +"utilise" = "utilize" +"utilised" = "utilized" +"utiliser" = "utilizer" +"utilisers" = "utilizers" +"utilises" = "utilizes" +"utilising" = "utilizing" +"utilizable" = "utilizable" +"utilization" = "utilization" +"utilizations" = "utilizations" +"utilize" = "utilize" +"utilized" = "utilized" +"utilizer" = "utilizer" +"utilizers" = "utilizers" +"utilizes" = "utilizes" +"utilizing" = "utilizing" +"vectorisable" = "vectorizable" +"vectorisation" = "vectorization" +"vectorisations" = "vectorizations" +"vectorise" = "vectorize" +"vectorised" = "vectorized" +"vectoriser" = "vectorizer" +"vectorisers" = "vectorizers" +"vectorises" = "vectorizes" +"vectorising" = "vectorizing" +"vectorizable" = "vectorizable" +"vectorization" = "vectorization" +"vectorizations" = "vectorizations" +"vectorize" = "vectorize" +"vectorized" = "vectorized" +"vectorizer" = "vectorizer" +"vectorizers" = "vectorizers" +"vectorizes" = "vectorizes" +"vectorizing" = "vectorizing" +"virtualisable" = "virtualizable" +"virtualisation" = "virtualization" +"virtualisations" = "virtualizations" +"virtualise" = "virtualize" +"virtualised" = "virtualized" +"virtualiser" = "virtualizer" +"virtualisers" = "virtualizers" +"virtualises" = "virtualizes" +"virtualising" = "virtualizing" +"virtualizable" = "virtualizable" +"virtualization" = "virtualization" +"virtualizations" = "virtualizations" +"virtualize" = "virtualize" +"virtualized" = "virtualized" +"virtualizer" = "virtualizer" +"virtualizers" = "virtualizers" +"virtualizes" = "virtualizes" +"virtualizing" = "virtualizing" +"visualisable" = "visualizable" +"visualisation" = "visualization" +"visualisations" = "visualizations" +"visualise" = "visualize" +"visualised" = "visualized" +"visualiser" = "visualizer" +"visualisers" = "visualizers" +"visualises" = "visualizes" +"visualising" = "visualizing" +"visualizable" = "visualizable" +"visualization" = "visualization" +"visualizations" = "visualizations" +"visualize" = "visualize" +"visualized" = "visualized" +"visualizer" = "visualizer" +"visualizers" = "visualizers" +"visualizes" = "visualizes" +"visualizing" = "visualizing" +"weaponisable" = "weaponizable" +"weaponisation" = "weaponization" +"weaponisations" = "weaponizations" +"weaponise" = "weaponize" +"weaponised" = "weaponized" +"weaponiser" = "weaponizer" +"weaponisers" = "weaponizers" +"weaponises" = "weaponizes" +"weaponising" = "weaponizing" +"weaponizable" = "weaponizable" +"weaponization" = "weaponization" +"weaponizations" = "weaponizations" +"weaponize" = "weaponize" +"weaponized" = "weaponized" +"weaponizer" = "weaponizer" +"weaponizers" = "weaponizers" +"weaponizes" = "weaponizes" +"weaponizing" = "weaponizing" +"yse" = "yse" +"zeroisable" = "zeroizable" +"zeroisation" = "zeroization" +"zeroisations" = "zeroizations" +"zeroise" = "zeroize" +"zeroised" = "zeroized" +"zeroiser" = "zeroizer" +"zeroisers" = "zeroizers" +"zeroises" = "zeroizes" +"zeroising" = "zeroizing" +"zeroizable" = "zeroizable" +"zeroization" = "zeroization" +"zeroizations" = "zeroizations" +"zeroize" = "zeroize" +"zeroized" = "zeroized" +"zeroizer" = "zeroizer" +"zeroizers" = "zeroizers" +"zeroizes" = "zeroizes" +"zeroizing" = "zeroizing" From 562d5efe6fd7086dd17d58a47977c005b53c8ed0 Mon Sep 17 00:00:00 2001 From: leynos Date: Fri, 10 Jul 2026 10:32:46 +0200 Subject: [PATCH 2/2] Restore Python 3.13 syntax Keep parentheses around multi-exception clauses in the shared spelling helper. Python 3.14 accepts the compact form produced locally, but generated projects and hosted CI support Python 3.13. --- scripts/typos_rollout.py | 14 ++++++++++---- template/scripts/typos_rollout.py | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/scripts/typos_rollout.py b/scripts/typos_rollout.py index 298b734..8c73cfb 100644 --- a/scripts/typos_rollout.py +++ b/scripts/typos_rollout.py @@ -218,7 +218,7 @@ def _read_metadata(path: pathlib.Path) -> dict[str, object]: """Read best-effort HTTP freshness metadata.""" try: value = json.loads(path.read_text(encoding="utf-8")) - except FileNotFoundError, json.JSONDecodeError: + except (FileNotFoundError, json.JSONDecodeError): return {} return value if isinstance(value, dict) else {} @@ -235,7 +235,13 @@ def _valid_cache(cache: pathlib.Path) -> bool: """Return whether *cache* contains a valid shared dictionary.""" try: load_dictionary(cache) - except FileNotFoundError, OSError, TypeError, ValueError, tomllib.TOMLDecodeError: + except ( + FileNotFoundError, + OSError, + TypeError, + ValueError, + tomllib.TOMLDecodeError, + ): return False return True @@ -256,7 +262,7 @@ def _remote_is_not_newer( return email.utils.parsedate_to_datetime( modified ) <= email.utils.parsedate_to_datetime(saved_modified) - except TypeError, ValueError: + except (TypeError, ValueError): return modified == saved_modified @@ -371,7 +377,7 @@ def _refresh_http( if _valid_cache(cache): return RefreshResult("stale-cache", cache) raise - except OSError, urllib.error.URLError: + except (OSError, urllib.error.URLError): if _valid_cache(cache): return RefreshResult("stale-cache", cache) raise diff --git a/template/scripts/typos_rollout.py b/template/scripts/typos_rollout.py index 298b734..8c73cfb 100644 --- a/template/scripts/typos_rollout.py +++ b/template/scripts/typos_rollout.py @@ -218,7 +218,7 @@ def _read_metadata(path: pathlib.Path) -> dict[str, object]: """Read best-effort HTTP freshness metadata.""" try: value = json.loads(path.read_text(encoding="utf-8")) - except FileNotFoundError, json.JSONDecodeError: + except (FileNotFoundError, json.JSONDecodeError): return {} return value if isinstance(value, dict) else {} @@ -235,7 +235,13 @@ def _valid_cache(cache: pathlib.Path) -> bool: """Return whether *cache* contains a valid shared dictionary.""" try: load_dictionary(cache) - except FileNotFoundError, OSError, TypeError, ValueError, tomllib.TOMLDecodeError: + except ( + FileNotFoundError, + OSError, + TypeError, + ValueError, + tomllib.TOMLDecodeError, + ): return False return True @@ -256,7 +262,7 @@ def _remote_is_not_newer( return email.utils.parsedate_to_datetime( modified ) <= email.utils.parsedate_to_datetime(saved_modified) - except TypeError, ValueError: + except (TypeError, ValueError): return modified == saved_modified @@ -371,7 +377,7 @@ def _refresh_http( if _valid_cache(cache): return RefreshResult("stale-cache", cache) raise - except OSError, urllib.error.URLError: + except (OSError, urllib.error.URLError): if _valid_cache(cache): return RefreshResult("stale-cache", cache) raise