From 613524e341afdb73799dcb247196262cdc298c99 Mon Sep 17 00:00:00 2001 From: leynos Date: Fri, 10 Jul 2026 18:01:16 +0200 Subject: [PATCH] Enforce Oxford spelling Add the shared spelling-policy helper, cached base dictionary, pinned typos gate, and CI integration. Correct all genuine corpus findings while retaining documented local terminology.\n\nRepair the strict test lint surface and stale release target exposed by the full repository gates. --- .github/workflows/ci.yml | 2 + .gitignore | 6 + ...ion-design-raising-handling-and-logging.md | 4 +- .rules/python-pyproject.md | 2 +- .rules/python-typing.md | 2 +- AGENTS.md | 12 +- Makefile | 35 +- ...antipatterns-and-refactoring-strategies.md | 8 +- docs/developers-guide.md | 8 + docs/lag-complexity-function-design.md | 2 +- docs/model-training-pipeline-design.md | 6 +- docs/model-training-pipeline-roadmap.md | 20 +- docs/opentofu-hcl-syntax-guide.md | 10 +- docs/opentofu-module-unit-testing-guide.md | 18 +- ...esting-in-rust-via-dependency-injection.md | 2 +- docs/roadmap.md | 8 +- docs/rstest-bdd-users-guide.md | 2 +- docs/rust-testing-with-rstest-fixtures.md | 4 +- docs/scripting-standards.md | 2 +- scripts/generate_typos_config.py | 86 + scripts/tests/test_typos_rollout.py | 384 +++ scripts/typos_rollout.py | 398 +++ scripts/typos_rollout_cache.py | 52 + tests/ambiguity_heuristic.rs | 37 +- tests/lagc_args.rs | 23 +- typos.local.toml | 18 + typos.toml | 2657 +++++++++++++++++ 27 files changed, 3732 insertions(+), 76 deletions(-) create mode 100644 scripts/generate_typos_config.py create mode 100644 scripts/tests/test_typos_rollout.py create mode 100644 scripts/typos_rollout.py create mode 100644 scripts/typos_rollout_cache.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 cc72f92..f3b247b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,6 +50,8 @@ jobs: with: python-version: '3.13' enable-cache: true + - name: Spelling + run: make spelling - name: Workflow contract tests run: make test-workflow-contracts - name: Test diff --git a/.gitignore b/.gitignore index 3468d0b..09737df 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,9 @@ target/ **/*.rs.bk .memdb/ __pycache__/ +.coverage +.pytest_cache/ +.uv-cache/ +.uv-tools/ +.typos-oxendict-base.json +.typos-oxendict-base.toml diff --git a/.rules/python-exception-design-raising-handling-and-logging.md b/.rules/python-exception-design-raising-handling-and-logging.md index e33d50a..e39da2e 100644 --- a/.rules/python-exception-design-raising-handling-and-logging.md +++ b/.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/.rules/python-pyproject.md b/.rules/python-pyproject.md index 89f8f76..50b20fc 100644 --- a/.rules/python-pyproject.md +++ b/.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/.rules/python-typing.md b/.rules/python-typing.md index 7962287..8110e7a 100644 --- a/.rules/python-typing.md +++ b/.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/AGENTS.md b/AGENTS.md index 715a2ee..1c528d3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,7 +28,7 @@ examples demonstrating the usage and outcome of the function. Test documentation should omit examples where the example serves only to reiterate the test logic. -- **Keep file size managable.** No single code file may be longer than 400 +- **Keep file size manageable.** No single code file may be longer than 400 lines. Long switch statements or dispatch tables should be broken up by feature and constituents colocated with targets. Large blocks of test data should be moved to external data files. @@ -59,7 +59,7 @@ - Where a bug is being fixed, a unittest has been provided demonstrating the behaviour being corrected both to validate the fix and to guard against regression. - - Passes all relevant unit and behavioral tests according to the guidelines + - Passes all relevant unit and behavioural tests according to the guidelines above. (Use `make test` to verify). - Passes lint checks. (Use `make lint` to verify). - Adheres to formatting standards tested using a formatting validator. (Use @@ -106,7 +106,7 @@ - **Separate Atomic Refactors:** If refactoring is deemed necessary: - Perform the refactoring as a **separate, atomic commit** *after* the functional change commit. - - Ensure the refactoring adheres to the testing guidelines (behavioral tests + - Ensure the refactoring adheres to the testing guidelines (behavioural tests pass before and after, unit tests added for new units). - Ensure the refactoring commit itself passes all quality gates. @@ -173,7 +173,7 @@ project: - Lint rule suppressions must be tightly scoped and include a clear reason. - Prefer `expect` over `allow`. - Use `rstest` fixtures for shared setup. -- Replace duplicated tests with `#[rstest(...)]` parameterised cases. +- Replace duplicated tests with `#[rstest(...)]` parameterized cases. - Prefer `mockall` for mocks/stubs. - Prefer `.expect()` over `.unwrap()`. - Use `concat!()` to combine long string literals rather than escaping newlines @@ -199,7 +199,7 @@ project: `into_inner()` and `to_path_buf()`; avoid attempting `impl From for PathBuf` because of the orphan rule. Prefer explicit tuple structs whenever bespoke validation or tailored trait surfaces are - required, customising `Deref`, `AsRef`, and `TryFrom` per type. Use + required, customizing `Deref`, `AsRef`, and `TryFrom` per type. Use `the-newtype` when defining traits and needing blanket implementations that apply across wrappers satisfying `Newtype + AsRef/AsMut`, or when establishing a coherent internal convention that keeps trait forwarding @@ -212,7 +212,7 @@ project: - Write unit and behavioural tests for new functionality. Run both before and after making any change. - Use `rstest` fixtures for shared setup. -- Replace duplicated tests with `#[rstest(...)]` parameterised cases. +- Replace duplicated tests with `#[rstest(...)]` parameterized cases. - Prefer `mockall` for mocks/stubs. - Mock non-deterministic dependencies (e.g., environment variables and the system clock) using dependency injection with the `mockable` crate (traits diff --git a/Makefile b/Makefile index 98626ec..921d604 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,22 @@ -.PHONY: help all clean test test-workflow-contracts build release lint typecheck fmt check-fmt markdownlint nixie bless +.PHONY: help all clean test test-workflow-contracts build release lint typecheck \ + fmt check-fmt markdownlint nixie spelling spelling-helper-test bless -APP ?= lag-complexity +APP ?= lagc CARGO ?= cargo BUILD_JOBS ?= CLIPPY_FLAGS ?= --all-targets --all-features -- -D warnings MDLINT ?= markdownlint-cli2 NIXIE ?= nixie WHITAKER ?= whitaker +UV ?= uv +UV_ENV = UV_CACHE_DIR=.uv-cache UV_TOOL_DIR=.uv-tools +RUFF_VERSION ?= 0.15.12 +TYPOS_VERSION ?= 1.48.0 build: target/debug/$(APP) ## Build debug binary release: target/release/$(APP) ## Build release binary -all: release ## Default target builds release binary +all: release spelling ## Build the release binary and enforce spelling clean: ## Remove build artifacts $(CARGO) clean @@ -39,9 +44,31 @@ fmt: ## Format Rust and Markdown sources check-fmt: ## Verify formatting $(CARGO) fmt --all -- --check -markdownlint: ## Lint Markdown files +markdownlint: spelling ## Lint Markdown files and enforce spelling find . -type f -name '*.md' -not -path './target/*' -print0 | xargs -0 $(MDLINT) +spelling: spelling-helper-test ## Enforce en-GB-oxendict spelling in Markdown prose + @$(UV_ENV) $(UV) run scripts/generate_typos_config.py + @git ls-files -z '*.md' | \ + xargs -0 -r env $(UV_ENV) $(UV) tool run typos@$(TYPOS_VERSION) \ + --config typos.toml --force-exclude + +spelling-helper-test: ## Validate the shared spelling-policy integration + @$(UV_ENV) $(UV) tool run ruff@$(RUFF_VERSION) format --isolated \ + --target-version py313 --check scripts/generate_typos_config.py \ + scripts/typos_rollout.py scripts/typos_rollout_cache.py \ + scripts/tests/test_typos_rollout.py + @$(UV_ENV) $(UV) tool run ruff@$(RUFF_VERSION) check --isolated \ + --target-version py313 scripts/generate_typos_config.py \ + scripts/typos_rollout.py scripts/typos_rollout_cache.py \ + scripts/tests/test_typos_rollout.py + @PYTHONPATH=scripts $(UV_ENV) $(UV) run --no-project --python 3.13 \ + --with pytest==9.0.2 --with pytest-cov==7.0.0 \ + python -m pytest scripts/tests/test_typos_rollout.py \ + -c /dev/null --rootdir=. -p no:cacheprovider \ + --cov=generate_typos_config --cov=typos_rollout \ + --cov=typos_rollout_cache --cov-fail-under=90 + nixie: ## Validate Mermaid diagrams # CI currently requires --no-sandbox; remove once nixie supports # environment variable control for this option diff --git a/docs/complexity-antipatterns-and-refactoring-strategies.md b/docs/complexity-antipatterns-and-refactoring-strategies.md index e52ba21..0f5b4f5 100644 --- a/docs/complexity-antipatterns-and-refactoring-strategies.md +++ b/docs/complexity-antipatterns-and-refactoring-strategies.md @@ -2,7 +2,7 @@ ## I. Introduction: The Challenge of Software Complexity -Software development is an inherently complex endeavor. As systems evolve and +Software development is an inherently complex endeavour. As systems evolve and features are added, the intricacy of the codebase tends to increase, often leading to challenges in maintenance, scalability, and developer productivity. "Any fool can write code that a computer can understand. Good programmers write @@ -95,7 +95,7 @@ Cognitive Complexity is incremented based on three main rules 8: 3. **Shorthand Discount:** Structures that allow multiple statements to be read as a single unit (e.g., a well-named method call) do not incur the same penalties as the raw statements they encapsulate. Method calls are generally - "free" in terms of cognitive complexity, as a well-chosen name summarises + "free" in terms of cognitive complexity, as a well-chosen name summarizes the underlying logic, allowing readers to grasp the high-level view before diving into details. However, recursive calls do increment the score.8 @@ -110,7 +110,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 @@ -338,7 +338,7 @@ perform auto-refactoring for certain languages.6 ### C. Red Flags Portending the Bumpy Road -Recognising early warning signs can prevent minor complexity issues from +Recognizing early warning signs can prevent minor complexity issues from escalating into full-blown Bumpy Roads. 1. **Increasing Cognitive Complexity Scores:** A rising Cognitive Complexity diff --git a/docs/developers-guide.md b/docs/developers-guide.md index f4159ec..4d07d97 100644 --- a/docs/developers-guide.md +++ b/docs/developers-guide.md @@ -4,6 +4,14 @@ This guide records development practices that are specific to maintaining this repository. Follow the project-wide guidance in `AGENTS.md` first, then use this guide for workflow automation details. +## Spelling policy + +Run `make spelling` to enforce en-GB-oxendict prose spelling. The generated +`typos.toml` starts from the shared estate dictionary, refreshes its untracked +local cache only when the authority is newer, and then applies the narrow +repository policy in `typos.local.toml`. Edit the local policy and regenerate +the configuration rather than changing generated entries by hand. + ## Continuous Integration workflow The Continuous Integration (CI) workflow lives in `.github/workflows/ci.yml`. diff --git a/docs/lag-complexity-function-design.md b/docs/lag-complexity-function-design.md index b724d9b..72f38f8 100644 --- a/docs/lag-complexity-function-design.md +++ b/docs/lag-complexity-function-design.md @@ -381,7 +381,7 @@ require a wider retrieval strategy. and results in a dedicated `VarianceError::Empty`. This guards against silent NaNs and ensures caller intent is explicit. - **Non-finite Inputs:** `NaN` or infinite values yield `NaN`. Callers should - sanitise embeddings if such values are not expected. + sanitize embeddings if such values are not expected. #### Embedding providers diff --git a/docs/model-training-pipeline-design.md b/docs/model-training-pipeline-design.md index e3e603f..8c11792 100644 --- a/docs/model-training-pipeline-design.md +++ b/docs/model-training-pipeline-design.md @@ -30,7 +30,7 @@ Key improvements in this design include: (training, evaluation, etc.) is executed on dedicated ephemeral cloud instances. Prefect tasks use Terraform (OpenTofu distribution) to provision the required **spot or on-demand VM instances** (with GPU for training, CPU - for export/evaluation) and tear them down afterward. This ensures + for export/evaluation) and tear them down afterwards. This ensures **cloud-agnostic deployment** – by swapping Terraform modules, the pipeline can target AWS, GCP, or other providers uniformly. It also maximizes cost efficiency by using spot instances and releasing resources immediately when @@ -102,7 +102,7 @@ adhere to several core principles in designing the workflow: versioned. We use **containerization** (Docker images) and infrastructure-as-code to ensure that a given pipeline run can be exactly replicated in the future. This is critical for auditing and for guaranteeing - consistent model behavior between training and production. The pipeline will + consistent model behaviour between training and production. The pipeline will incorporate configuration files (or Prefect configuration blocks) for all adjustable parameters (dataset version, model architecture, learning rates, instance types, etc.), which are stored in version control. By fixing these @@ -220,7 +220,7 @@ automate their lifecycle: 2.3). The Terraform provisioning task can request a spot VM (e.g., AWS EC2 Spot or GCP Preemptible VM) for training; if the request is not fulfilled or the instance is reclaimed mid-training, the Prefect flow will handle - launching a replacement and resuming training. The **cost modeling** takes + launching a replacement and resuming training. The **cost modelling** takes into account the expected interruptions and restart overhead, ensuring that even with occasional restarts, using spot instances yields net savings. For cases where spot is not available or for final runs, the pipeline can easily diff --git a/docs/model-training-pipeline-roadmap.md b/docs/model-training-pipeline-roadmap.md index 365b8f1..9237b39 100644 --- a/docs/model-training-pipeline-roadmap.md +++ b/docs/model-training-pipeline-roadmap.md @@ -47,10 +47,10 @@ progress tracking. - [ ] 1.1.3.4. Wire alerting (Slack, PagerDuty, email) to Prefect block failures and add runbook links for operator response. -### 1.2. Standardise compute procurement and cost controls +### 1.2. Standardize compute procurement and cost controls - [ ] Automate OpenTofu modules for g4dn.xlarge, g6.xlarge, and c6i.xlarge - instances with provider parameterisation and teardown under 10 minutes. + instances with provider parameterization and teardown under 10 minutes. - [ ] Validate spot-to-on-demand fallbacks by injecting capacity failures and confirming retries succeed within three orchestration attempts. - [ ] Publish hourly cost benchmarks for each instance class with variance @@ -75,7 +75,7 @@ progress tracking. - [ ] Build ingestion scripts that hydrate `/datasets/raw/` from approved sources and emit checksums recorded in metadata manifests. -- [ ] Create preprocessing jobs that materialise `/datasets/processed/` +- [ ] Create preprocessing jobs that materialize `/datasets/processed/` artefacts with schema validation and rejection workflows for anomalies. - [ ] Introduce calibration dataset generation producing 100–500 curated samples stored under `/datasets/processed/{dataset}/calibration/`. @@ -84,7 +84,7 @@ progress tracking. - [ ] Develop the `OrdinalRegressionTrainer` with cutpoint ordering guarantees and unit tests covering boundary cases (monotonicity, identical labels). -- [ ] Parameterise model head replacement logic to support both BERT-like and +- [ ] Parameterize model head replacement logic to support both BERT-like and ViT architectures, validated on representative text and image datasets. - [ ] Achieve ≥90% statement coverage on the training module using `pytest` plus fixtures from `rstest`. @@ -100,7 +100,7 @@ progress tracking. - [ ] Capture structured metrics (loss, cutpoints, throughput) and emit them to Prefect Orion and the observability stack with comparison dashboards. -## 3. Operationalise export and optimisation +## 3. Operationalize export and optimization ### 3.1. Build ONNX export automation @@ -111,7 +111,7 @@ progress tracking. - [ ] Execute export and verification Prefect tasks on CPU OpenTofu modules, proving GPU instances are torn down before CPU provisioning. - [ ] Store FP32 exports under `/models/onnx/{experiment}/fp32/` with metadata - capturing opset, optimiser flags, and git references. + capturing opset, optimizer flags, and git references. ### 3.2. Enforce parity verification gates @@ -122,13 +122,13 @@ progress tracking. - [ ] Schedule nightly parity spot-checks on retained models to detect drift in dependencies (CUDA, ONNX Runtime) before release branches freeze. -### 3.3. Deliver quantisation and benchmarking workflow +### 3.3. Deliver quantization and benchmarking workflow -- [ ] Codify static INT8 quantisation scripts with calibration dataset reuse +- [ ] Codify static INT8 quantization scripts with calibration dataset reuse and artefact write-back to `/models/onnx/{experiment}/int8/`. - [ ] Measure INT8 throughput versus FP32 on target CPU instances, documenting improvements and acceptable accuracy deltas (<1% MAE loss). -- [ ] Integrate quantised-model verification into CI with `atol=1e-2` +- [ ] Integrate quantized-model verification into CI with `atol=1e-2` tolerances, including latency smoke tests under realistic batch sizes. ## 4. Integrate with the Rust inference surface @@ -151,7 +151,7 @@ progress tracking. - [ ] Benchmark end-to-end inference latencies (p50, p95) under representative traffic, ensuring INT8 pipelines meet sub-50 ms targets on t4g.large. -### 4.3. Operationalise release governance +### 4.3. Operationalize release governance - [ ] Define promotion criteria linking training experiment success, parity checks, and Rust e2e tests before artefacts become GA releases. diff --git a/docs/opentofu-hcl-syntax-guide.md b/docs/opentofu-hcl-syntax-guide.md index 0c9ddb9..5921d7c 100644 --- a/docs/opentofu-hcl-syntax-guide.md +++ b/docs/opentofu-hcl-syntax-guide.md @@ -19,7 +19,7 @@ infrastructure. OpenTofu, as an Infrastructure as Code (IaC) tool, reads this declarative configuration and takes on the responsibility of figuring out how to achieve that state. -This approach is centered on the concept of state reconciliation. OpenTofu +This approach is centred on the concept of state reconciliation. OpenTofu maintains a state file (by default, `terraform.tfstate`) that records the real-world resources it manages. When a configuration is applied, OpenTofu compares the desired state defined in the HCL files with the current state @@ -620,7 +620,7 @@ provider's API.2 A data source is declared using a `data` block. -#### Syntax and Behavior +#### Syntax and Behaviour The syntax is `data "_" "" {... }`.25 @@ -760,7 +760,7 @@ of the resource or module.5 - **Syntax**: `count = ` -- **Behavior**: It is best suited for creating multiple copies of a resource +- **Behaviour**: It is best suited for creating multiple copies of a resource that are identical or vary only in ways that can be derived from a simple numeric index. @@ -822,7 +822,7 @@ in the collection.29 - **Syntax**: `for_each = ` -- **Behavior**: It creates a more stable association between the configuration +- **Behaviour**: It creates a more stable association between the configuration and the real-world resource. Each instance is tracked by the map key or set value, not by a transient numeric index. @@ -1000,7 +1000,7 @@ of operations for creating, updating, and destroying resources. dependencies is implicitly. When one resource's argument references an attribute of another resource (e.g., `subnet_id = aws_vpc.main.id`), OpenTofu automatically infers that the VPC must be created before the subnet. It - analyzes all such references to build the dependency graph.19 + analyses all such references to build the dependency graph.19 - **Explicit Dependencies with** `depends_on`: In some rare cases, a dependency exists that cannot be inferred from expression references. This typically diff --git a/docs/opentofu-module-unit-testing-guide.md b/docs/opentofu-module-unit-testing-guide.md index 36ff35b..bc18532 100644 --- a/docs/opentofu-module-unit-testing-guide.md +++ b/docs/opentofu-module-unit-testing-guide.md @@ -44,7 +44,7 @@ coverage with an efficient feedback loop.8 Static analysis is the first and most fundamental layer of testing, performed on the code itself without executing it or deploying any infrastructure.9 This -layer acts as a rapid, low-cost first line of defense, catching a wide range of +layer acts as a rapid, low-cost first line of defence, catching a wide range of issues before they enter the main development branch or a CI/CD pipeline. - **Formatting and Syntax Validation**: The most basic checks ensure that the @@ -633,7 +633,7 @@ run "validate_multiple_buckets_creation" { ``` This test suite effectively validates the module's iterative and conditional -logic against the plan, providing high confidence in its behavior without +logic against the plan, providing high confidence in its behaviour without deploying any infrastructure.36 ### 3.2 Validating Complex Conditional Logic @@ -641,7 +641,7 @@ deploying any infrastructure.36 Modules frequently employ conditional expressions (`condition? true_val : false_val`) to create optional resources or modify configurations based on input variables.39 Thoroughly testing this logic is -essential to prevent unexpected behavior. The key strategy is to create a +essential to prevent unexpected behaviour. The key strategy is to create a dedicated `run` block for each significant conditional path your module can take. @@ -836,7 +836,7 @@ and Kubernetes configurations.16 #### Philosophy and Core Concepts -Terratest's philosophy is centered on writing integration and end-to-end tests +Terratest's philosophy is centred on writing integration and end-to-end tests that validate real infrastructure in a real environment. The core pattern of a Terratest test is a sequence of actions orchestrated by Go code 48: @@ -949,7 +949,7 @@ OpenTofu as a drop-in replacement for Terraform.50 By default, Terratest will look for a `terraform` binary in the system's `PATH`. If it's not found, it will -automatically look for a `tofu` binary. This behavior ensures that existing +automatically look for a `tofu` binary. This behaviour ensures that existing test suites can be migrated to OpenTofu with minimal to no changes. For explicit control, the binary can be specified in the `terraform.Options` struct.50 @@ -983,8 +983,8 @@ sandbox environment and then run compliance and validation tests against it.16 However, with the advent of robust native testing in OpenTofu/Terraform and the widespread adoption of the more flexible Terratest framework, Kitchen-Terraform is now largely considered a legacy tool. The project itself has been deprecated -in favor of the native test framework, and while it was a valuable part of the -ecosystem's history, new projects should favor `tofu test` or Terratest for +in favour of the native test framework, and while it was a valuable part of the +ecosystem's history, new projects should favour `tofu test` or Terratest for their testing needs.54 ## Part 5: Architectural Best Practices for Testable OpenTofu Modules @@ -1374,7 +1374,7 @@ these layers: `tofu test` or Terratest. These tests should be plan-based, leveraging mocks and overrides to validate module logic, conditional paths, and input handling in complete isolation. Running these on every PR ensures that the - core behavior of every module is verified before it is merged. + core behaviour of every module is verified before it is merged. 3. **Integration Tests in a Dedicated Environment**: After a change is merged, integration tests should be run in a dedicated, ephemeral test environment. @@ -1394,7 +1394,7 @@ infrastructure changes while optimizing for developer productivity.8 The emergence of powerful, native testing frameworks like `tofu test` and sophisticated third-party libraries like Terratest marks a significant maturation point for Infrastructure as Code. IaC is no longer just a scripting -practice; it is a formal engineering discipline that demands the same rigor and +practice; it is a formal engineering discipline that demands the same rigour and quality assurance as application development. The future of IaC testing will likely see this trend continue and accelerate. diff --git a/docs/reliable-testing-in-rust-via-dependency-injection.md b/docs/reliable-testing-in-rust-via-dependency-injection.md index f26d871..94173e7 100644 --- a/docs/reliable-testing-in-rust-via-dependency-injection.md +++ b/docs/reliable-testing-in-rust-via-dependency-injection.md @@ -1,6 +1,6 @@ # 🛡️ Reliable Testing in Rust via Dependency Injection -Writing robust, reliable, and parallelisable tests requires an intentional +Writing robust, reliable, and parallelizable tests requires an intentional approach to handling external dependencies such as environment variables, the filesystem, or the system clock. Functions that directly call `std::env::var` or `SystemTime::now()` are difficult to test because they depend on global, diff --git a/docs/roadmap.md b/docs/roadmap.md index 768a149..3211bbd 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -7,7 +7,7 @@ primary public interfaces. ### 1.1. Scaffolding & Core API -- [ ] Initialise the Rust project via `cargo new`. +- [ ] Initialize the Rust project via `cargo new`. - [x] Define all public data structures (`Complexity`, `Trace`, `ScopingConfig` and its subtypes) and derive `serde` traits for configuration types. - [x] Define all public traits (`ComplexityFn`, `EmbeddingProvider`, @@ -58,7 +58,7 @@ optimizing for performance. - [ ] 3.1.1.1. Fine-tune the DistilBERT ordinal model on ordered depth bins, confirm the expected-value projection matches the Sigma calibration interface, and export the opset 17 graph with pinned tokenizer assets. - - [ ] 3.1.1.2. Apply post-training static INT8 quantisation, benchmark CPU + - [ ] 3.1.1.2. Apply post-training static INT8 quantization, benchmark CPU latency to p95 ≤ 10 ms, and record calibration coefficients for the provider configuration. - [ ] 3.1.1.3. Publish the model package with checksum manifest, versioned @@ -71,7 +71,7 @@ optimizing for performance. - [ ] 3.1.2.2. Fine-tune the lightweight transformer, export the ONNX graph with the categorical-to-numeric mapping required by Sigma, and pin the tokenizer vocabulary. - - [ ] 3.1.2.3. Quantise and benchmark the graph to meet latency and + - [ ] 3.1.2.3. Quantize and benchmark the graph to meet latency and footprint targets, then publish artefacts and checksum metadata alongside calibration notes. - [ ] 3.1.3. Implement the `DepthClassifierOnnx` provider behind the `onnx` @@ -80,7 +80,7 @@ optimizing for performance. validation, and wire the expected-value scalar projection into `TextProcessor` per the ADR. - [ ] 3.1.3.2. Integrate tracing, metrics, and configuration plumbing (model - paths, quantisation variant selection, calibration coefficients) + paths, quantization variant selection, calibration coefficients) consistent with the Complexity pipeline. - [ ] 3.1.3.3. Extend golden traces and unit tests to cover inference happy paths, error mapping, and deterministic outputs across feature diff --git a/docs/rstest-bdd-users-guide.md b/docs/rstest-bdd-users-guide.md index 0e37a83..6c3e62d 100644 --- a/docs/rstest-bdd-users-guide.md +++ b/docs/rstest-bdd-users-guide.md @@ -75,7 +75,7 @@ annotated with one of the attribute macros `#[given]`, `#[when]` or `#[then]`. The annotation takes a single string literal that must match the text of the corresponding step in the feature file. Placeholders in the form `{name}` or `{name:Type}` are supported. The framework extracts matching substrings and -converts them using `FromStr`; type hints constrain the match using specialised +converts them using `FromStr`; type hints constrain the match using specialized regular expressions. The procedural macro implementation expands the annotated function into two diff --git a/docs/rust-testing-with-rstest-fixtures.md b/docs/rust-testing-with-rstest-fixtures.md index 52ff15c..6f8e1af 100644 --- a/docs/rust-testing-with-rstest-fixtures.md +++ b/docs/rust-testing-with-rstest-fixtures.md @@ -20,7 +20,7 @@ objects used as a baseline for running tests. The primary purpose of a fixture is to ensure that there is a well-known and controlled environment in which tests are run so that results are repeatable. Test dependencies, such as database connections, user objects, or specific configurations, often require -careful setup before a test can execute and, sometimes, teardown afterward. +careful setup before a test can execute and, sometimes, teardown afterwards. Managing this setup and teardown logic within each test function can lead to considerable boilerplate code and repetition, making tests harder to read and maintain. @@ -51,7 +51,7 @@ projects that may share the same name but operate in different ecosystems The `rstest` crate utilizes Rust's procedural macros, such as `#[rstest]` and `#[fixture]`, to achieve its declarative and expressive syntax. These macros allow developers to define fixtures and inject them into test functions simply -by listing them as arguments. This compile-time mechanism analyzes test +by listing them as arguments. This compile-time mechanism analyses test function signatures and fixture definitions to wire up dependencies automatically. diff --git a/docs/scripting-standards.md b/docs/scripting-standards.md index 0c08944..2d5c26d 100644 --- a/docs/scripting-standards.md +++ b/docs/scripting-standards.md @@ -1,6 +1,6 @@ # Scripting standards -Project scripts must prioritise clarity, reproducibility, and testability. The +Project scripts must prioritize clarity, reproducibility, and testability. The baseline tooling is Python and the [`uv`](https://github.com/astral-sh/uv) launcher so that scripts remain dependency‑self‑contained and easy to execute in Continuous Integration (CI) or locally. diff --git a/scripts/generate_typos_config.py b/scripts/generate_typos_config.py new file mode 100644 index 0000000..96aac55 --- /dev/null +++ b/scripts/generate_typos_config.py @@ -0,0 +1,86 @@ +#!/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. +""" + +import tomllib +import urllib.error +import urllib.parse +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 _tracked_remote_fallback( + source: str | Path, + destination: Path, +) -> rollout.RefreshResult | None: + """Return a valid tracked config only for an unavailable HTTPS authority.""" + if not isinstance(source, str) or urllib.parse.urlsplit(source).scheme != "https": + return None + try: + tomllib.loads(destination.read_text(encoding="utf-8")) + except (FileNotFoundError, OSError, tomllib.TOMLDecodeError): + return None + return rollout.RefreshResult("tracked-config", destination) + + +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.""" + destination = output if output is not None else repository / "typos.toml" + try: + result = rollout.refresh_base( + source, + repository / ".typos-oxendict-base.toml", + metadata=repository / ".typos-oxendict-base.json", + offline=offline, + ) + except (OSError, urllib.error.URLError): + fallback = _tracked_remote_fallback(source, destination) + if fallback is not None: + return fallback + raise + 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/tests/test_typos_rollout.py b/scripts/tests/test_typos_rollout.py new file mode 100644 index 0000000..4dd0302 --- /dev/null +++ b/scripts/tests/test_typos_rollout.py @@ -0,0 +1,384 @@ +"""Tests for the repository spelling-policy scripts.""" + +from __future__ import annotations + +import ast +import email.message +import importlib +import json +import os +import tomllib +import typing as typ +import urllib.error +import urllib.request +from pathlib import Path + +import pytest + +if typ.TYPE_CHECKING: + import types + +SCRIPT_DIRECTORY = Path(__file__).resolve().parents[1] + + +def test_rollout_scripts_support_python_313() -> None: + """Every rollout script parses with the declared minimum Python version.""" + for script in SCRIPT_DIRECTORY.glob("*.py"): + ast.parse( + script.read_text(encoding="utf-8"), + filename=str(script), + feature_version=(3, 13), + ) + + +@pytest.fixture(name="rollout_modules") +def rollout_modules_fixture( + monkeypatch: pytest.MonkeyPatch, +) -> tuple[types.ModuleType, types.ModuleType, types.ModuleType]: + """Import the scripts through the same top-level module path used at runtime.""" + monkeypatch.syspath_prepend(str(SCRIPT_DIRECTORY)) + names = ("typos_rollout_cache", "typos_rollout", "generate_typos_config") + importlib.invalidate_caches() + cache, rollout, generator = (importlib.import_module(name) for name in names) + return cache, rollout, generator + + +def _dictionary_text(stem: str = "organ") -> str: + """Return a minimal valid shared-dictionary document.""" + return ( + 'schema = 1\n\n[oxford]\nstems = ["' + + stem + + '"]\n\n[words]\naccepted = []\n\n[words.corrections]\n\n' + + "[patterns]\nignore = []\n\n[files]\nexclude = []\n" + ) + + +def test_rollout_generates_oxford_corrections( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], +) -> None: + """The shared renderer accepts Oxford forms and corrects plain-British ones.""" + _, rollout, _ = rollout_modules + + mappings = rollout.generate_word_mappings(rollout.Dictionary(stems=("organ",))) + + assert mappings["organize"] == "organize" + assert mappings["organise"] == "organize" + + +def test_local_refresh_keeps_a_newer_cache( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + tmp_path: Path, +) -> None: + """An older local authority cannot replace a newer untracked cache.""" + _, rollout, _ = rollout_modules + source = tmp_path / "shared.toml" + cache = tmp_path / ".typos-base.toml" + metadata = tmp_path / ".typos-base.json" + source.write_text(_dictionary_text(), encoding="utf-8") + source.touch() + rollout.refresh_base(source, cache, metadata=metadata) + cache.write_text(_dictionary_text("newer"), encoding="utf-8") + cache.touch() + source_mtime = source.stat().st_mtime_ns + cache_mtime = max(cache.stat().st_mtime_ns, source_mtime + 1) + os.utime(cache, ns=(cache_mtime, cache_mtime)) + + result = rollout.refresh_base(source, cache, metadata=metadata) + + assert result.status == "current" + assert rollout.load_dictionary(cache).stems == ("newer",) + + +def test_https_failure_reuses_valid_tracked_config( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """A clean network-restricted checkout retains its reviewed policy.""" + _, rollout, generator = rollout_modules + tracked_config = tmp_path / "typos.toml" + tracked_config.write_text('[default]\nlocale = "en-gb"\n', encoding="utf-8") + + def unavailable(*_args: object, **_kwargs: object) -> None: + """Model an unavailable HTTPS authority.""" + raise urllib.error.URLError("offline") + + monkeypatch.setattr(rollout, "refresh_base", unavailable) + + result = generator.main(repository=tmp_path, source="https://example.invalid/base") + + assert result.status == "tracked-config" + assert result.cache == tracked_config + + +def test_dictionary_validation_rejects_invalid_documents( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + tmp_path: Path, +) -> None: + """Schema, table, string-list and correction types remain validated.""" + _, rollout, _ = rollout_modules + source = tmp_path / "base.toml" + invalid_documents = ( + _dictionary_text().replace("schema = 1", "schema = 2"), + _dictionary_text().replace('[oxford]\nstems = ["organ"]', 'oxford = "bad"'), + _dictionary_text().replace('stems = ["organ"]', "stems = [1]"), + _dictionary_text().replace( + "[words.corrections]", "[words.corrections]\nteh = 1" + ), + ) + + for document in invalid_documents: + source.write_text(document, encoding="utf-8") + with pytest.raises((TypeError, ValueError)): + rollout.load_dictionary(source) + + +def test_merge_rejects_conflicting_corrections( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], +) -> None: + """A local overlay cannot silently weaken a shared correction.""" + _, rollout, _ = rollout_modules + base = rollout.Dictionary(corrections=(("teh", "the"),)) + local = rollout.Dictionary(corrections=(("teh", "ten"),)) + + with pytest.raises(ValueError, match="conflicting correction"): + rollout.merge_dictionaries(base, local) + + +def test_render_and_write_are_deterministic_valid_toml( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + tmp_path: Path, +) -> None: + """Rendering is stable, parseable and atomically installed.""" + _, rollout, _ = rollout_modules + dictionary = rollout.Dictionary( + stems=("organ",), + accepted=("proper-name",), + ignore_patterns=("https?://",), + excluded_files=("target",), + ) + output = tmp_path / "nested" / "typos.toml" + + first = rollout.render_typos_config(dictionary) + rollout.write_config(output, dictionary) + + assert first == rollout.render_typos_config(dictionary) + assert output.read_text(encoding="utf-8") == first + assert tomllib.loads(first)["default"]["locale"] == "en-gb" + assert list(output.parent.glob(".typos.toml.*")) == [] + + +def test_offline_refresh_requires_and_reuses_valid_cache( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + tmp_path: Path, +) -> None: + """Offline mode fails closed before reusing a validated cache.""" + _, rollout, _ = rollout_modules + cache = tmp_path / "base.toml" + metadata = tmp_path / "base.json" + + with pytest.raises(FileNotFoundError, match="no cached shared dictionary"): + rollout.refresh_base( + "https://example.invalid/base", cache, metadata=metadata, offline=True + ) + + cache.write_text(_dictionary_text(), encoding="utf-8") + result = rollout.refresh_base( + "https://example.invalid/base", cache, metadata=metadata, offline=True + ) + + assert result.status == "offline-cache" + + +def test_local_refresh_switches_authority_and_records_metadata( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + tmp_path: Path, +) -> None: + """A different explicit authority replaces a cache regardless of mtime.""" + _, rollout, _ = rollout_modules + first = tmp_path / "first.toml" + second = tmp_path / "second.toml" + cache = tmp_path / "cache.toml" + metadata = tmp_path / "cache.json" + first.write_text(_dictionary_text("first"), encoding="utf-8") + second.write_text(_dictionary_text("second"), encoding="utf-8") + os.utime(first, ns=(3_000_000_000, 3_000_000_000)) + os.utime(second, ns=(1_000_000_000, 1_000_000_000)) + rollout.refresh_base(first, cache, metadata=metadata) + + result = rollout.refresh_base(second, cache, metadata=metadata) + + assert result.status == "refreshed" + assert rollout.load_dictionary(cache).stems == ("second",) + assert json.loads(metadata.read_text(encoding="utf-8"))["source"] == str( + second.resolve() + ) + + +def test_http_refresh_uses_validators_and_preserves_newer_cache( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Remote refresh persists validators and sends them on the next request.""" + _, rollout, _ = rollout_modules + cache = tmp_path / "cache.toml" + metadata = tmp_path / "cache.json" + requests: list[urllib.request.Request] = [] + + class Response: + """Provide the HTTP response surface consumed by the helper.""" + + status = 200 + headers: typ.ClassVar[dict[str, str]] = { + "ETag": '"estate-v1"', + "Last-Modified": "Fri, 10 Jul 2026 08:00:00 GMT", + } + + def read(self) -> bytes: + """Return a valid shared dictionary.""" + return _dictionary_text().encode() + + def __enter__(self) -> Response: + """Enter the fake response context.""" + return self + + def __exit__(self, *_args: object) -> None: + """Leave the fake response context.""" + + def open_response(request: urllib.request.Request, *, timeout: float) -> Response: + """Capture the request passed to the network boundary.""" + assert timeout == pytest.approx(30.0) + requests.append(request) + return Response() + + monkeypatch.setattr(rollout.urllib.request, "urlopen", open_response) + + first = rollout.refresh_base( + "https://example.test/base.toml", cache, metadata=metadata + ) + second = rollout.refresh_base( + "https://example.test/base.toml", cache, metadata=metadata + ) + + assert first.status == "refreshed" + assert second.status == "current" + assert requests[1].get_header("If-none-match") == '"estate-v1"' + + +def test_remote_failure_reuses_only_a_valid_stale_cache( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Network failure keeps validated data and propagates without it.""" + _, rollout, _ = rollout_modules + cache = tmp_path / "cache.toml" + metadata = tmp_path / "cache.json" + + def fail(*_args: object, **_kwargs: object) -> None: + """Model an unavailable remote authority.""" + message = "offline" + raise urllib.error.URLError(message) + + monkeypatch.setattr(rollout.urllib.request, "urlopen", fail) + + with pytest.raises(urllib.error.URLError): + rollout.refresh_base("https://example.test/base", cache, metadata=metadata) + + cache.write_text(_dictionary_text(), encoding="utf-8") + result = rollout.refresh_base("https://example.test/base", cache, metadata=metadata) + + assert result.status == "stale-cache" + + +def test_remote_refresh_rejects_insecure_and_invalid_content( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """The remote boundary requires HTTPS and validates bytes before install.""" + _, rollout, _ = rollout_modules + cache = tmp_path / "cache.toml" + metadata = tmp_path / "cache.json" + + with pytest.raises(ValueError, match="must use HTTPS"): + rollout.refresh_base("http://example.test/base", cache, metadata=metadata) + + class InvalidResponse: + """Return malformed TOML from an otherwise successful response.""" + + status = 200 + headers: typ.ClassVar[dict[str, str]] = {} + + def read(self) -> bytes: + """Return malformed bytes.""" + return b"not = [valid" + + def __enter__(self) -> InvalidResponse: + """Enter the fake response context.""" + return self + + def __exit__(self, *_args: object) -> None: + """Leave the fake response context.""" + + monkeypatch.setattr( + rollout.urllib.request, "urlopen", lambda *_args, **_kwargs: InvalidResponse() + ) + + with pytest.raises(tomllib.TOMLDecodeError): + rollout.refresh_base("https://example.test/base", cache, metadata=metadata) + assert not cache.exists() + + +def test_metadata_reader_handles_invalid_and_non_object_json( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + tmp_path: Path, +) -> None: + """Malformed or non-object freshness metadata is safely ignored.""" + _, rollout, _ = rollout_modules + metadata = tmp_path / "cache.json" + + metadata.write_text("not-json", encoding="utf-8") + assert rollout._read_metadata(metadata) == {} + metadata.write_text("[]", encoding="utf-8") + assert rollout._read_metadata(metadata) == {} + + +def test_http_error_translation_handles_not_modified_and_stale_cache( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], + tmp_path: Path, +) -> None: + """HTTP status handling distinguishes current, stale and absent data.""" + _, rollout, _ = rollout_modules + cache = tmp_path / "cache.toml" + cache.write_text(_dictionary_text(), encoding="utf-8") + headers = email.message.Message() + not_modified = urllib.error.HTTPError( + "https://example.test/base", 304, "not modified", headers, None + ) + unavailable = urllib.error.HTTPError( + "https://example.test/base", 503, "unavailable", headers, None + ) + + assert rollout._http_error_result(cache, not_modified).status == "current" + assert rollout._http_error_result(cache, unavailable).status == "stale-cache" + cache.unlink() + with pytest.raises(urllib.error.HTTPError): + rollout._http_error_result(cache, unavailable) + + +def test_remote_freshness_uses_dates_and_falls_back_on_invalid_values( + rollout_modules: tuple[types.ModuleType, types.ModuleType, types.ModuleType], +) -> None: + """Last-Modified comparison remains conservative for malformed dates.""" + _, rollout, _ = rollout_modules + + assert rollout._remote_is_not_newer( + {"last_modified": "Fri, 10 Jul 2026 08:00:00 GMT"}, + {"Last-Modified": "Fri, 10 Jul 2026 07:00:00 GMT"}, + ) + assert rollout._remote_is_not_newer( + {"last_modified": "invalid"}, {"Last-Modified": "invalid"} + ) + assert not rollout._remote_is_not_newer({}, {"Last-Modified": "invalid"}) diff --git a/scripts/typos_rollout.py b/scripts/typos_rollout.py new file mode 100644 index 0000000..3720186 --- /dev/null +++ b/scripts/typos_rollout.py @@ -0,0 +1,398 @@ +"""Refresh and render shared en-GB-oxendict ``typos`` configuration.""" + +from __future__ import annotations + +import dataclasses as dc +import email.utils +import json +import pathlib +import tomllib +import typing as typ +import urllib.error +import urllib.parse +import urllib.request + +import typos_rollout_cache + +if typ.TYPE_CHECKING: + import collections.abc as cabc + +RefreshResult = typos_rollout_cache.RefreshResult +_CacheTargets = typos_rollout_cache.CacheTargets +_RemoteResponse = typos_rollout_cache.RemoteResponse +_atomic_write = typos_rollout_cache.atomic_write + +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"), +) + + +@dc.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, ...] = () + + +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 typ.cast("cabc.Mapping[str, object]", 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) + corrections = typ.cast("cabc.Mapping[str, str]", corrections_table) + return Dictionary( + stems=_string_list(oxford, "stems"), + accepted=_string_list(words, "accepted"), + corrections=tuple(sorted(corrections.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 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: dict[str, str] = {} + etag = saved.get("etag") + if isinstance(etag, str): + headers["If-None-Match"] = etag + last_modified = saved.get("last_modified") + if isinstance(last_modified, str): + headers["If-Modified-Since"] = 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 _remote_response_result( + source: str, + targets: _CacheTargets, + saved: cabc.Mapping[str, object], + response: _RemoteResponse, +) -> RefreshResult: + """Return the cache result for a successful HTTP response.""" + if response.status == HTTP_NOT_MODIFIED and _valid_cache(targets.cache): + return RefreshResult("current", targets.cache) + if _valid_cache(targets.cache) and _remote_is_not_newer(saved, response.headers): + return RefreshResult("current", targets.cache) + return _write_remote_cache(source, targets, response.read(), response.headers) + + +def _stale_cache_or_raise( + cache: pathlib.Path, + error: OSError | urllib.error.URLError, +) -> RefreshResult: + """Return a valid stale cache or propagate the download failure.""" + if _valid_cache(cache): + return RefreshResult("stale-cache", cache) + raise error + + +def _http_error_result( + cache: pathlib.Path, + error: urllib.error.HTTPError, +) -> RefreshResult: + """Translate an HTTP failure into the available cache result.""" + if error.code == HTTP_NOT_MODIFIED and _valid_cache(cache): + return RefreshResult("current", cache) + return _stale_cache_or_raise(cache, error) + + +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: + return _remote_response_result( + source, _CacheTargets(cache, metadata), saved, response + ) + except urllib.error.HTTPError as error: + return _http_error_result(cache, error) + except (OSError, urllib.error.URLError) as error: + return _stale_cache_or_raise(cache, error) + + +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/scripts/typos_rollout_cache.py b/scripts/typos_rollout_cache.py new file mode 100644 index 0000000..fdc4b92 --- /dev/null +++ b/scripts/typos_rollout_cache.py @@ -0,0 +1,52 @@ +"""Provide cache support types and atomic writes for the spelling helper.""" + +from __future__ import annotations + +import dataclasses as dc +import pathlib +import tempfile +import typing as typ + +if typ.TYPE_CHECKING: + import collections.abc as cabc + + +@dc.dataclass(frozen=True) +class RefreshResult: + """Describe whether the untracked shared dictionary cache changed.""" + + status: str + cache: pathlib.Path + + +@dc.dataclass(frozen=True) +class CacheTargets: + """Group the untracked dictionary cache and metadata sidecar paths.""" + + cache: pathlib.Path + metadata: pathlib.Path + + +class RemoteResponse(typ.Protocol): + """Expose the HTTP response surface used by cache refresh.""" + + status: int + headers: cabc.Mapping[str, str] + + def read(self) -> bytes: + """Read the response body.""" + ... + + +def atomic_write(path: pathlib.Path, content: bytes) -> None: + """Write content beside a 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) diff --git a/tests/ambiguity_heuristic.rs b/tests/ambiguity_heuristic.rs index 8fe9713..0cf0ae4 100644 --- a/tests/ambiguity_heuristic.rs +++ b/tests/ambiguity_heuristic.rs @@ -6,6 +6,7 @@ use lag_complexity::TextProcessor; use lag_complexity::heuristics::{AmbiguityHeuristic, AmbiguityHeuristicError}; use proptest::prelude::*; +use proptest::test_runner::TestCaseError; use rstest::rstest; mod support; @@ -156,14 +157,22 @@ macro_rules! assert_non_decreasing { "{} base sentence should score but returned {base_result:?}", context ); - let base_score = base_result.unwrap(); + let base_score = base_result.map_err(|err| { + TestCaseError::fail(format!( + "{context} base sentence should score but returned {err:?}" + )) + })?; let augmented_result = $heuristic.process($augmented); prop_assert!( augmented_result.is_ok(), "{} augmented text should score but returned {augmented_result:?}", context ); - let augmented_score = augmented_result.unwrap(); + let augmented_score = augmented_result.map_err(|err| { + TestCaseError::fail(format!( + "{context} augmented text should score but returned {err:?}" + )) + })?; prop_assert!( augmented_score >= base_score, "{} lowered score: base={base_score}, augmented={augmented_score}", @@ -219,9 +228,11 @@ proptest! { ) { let sentence = format!("{adverb} {pronoun}."); let h = AmbiguityHeuristic; - let score = h - .process(&sentence) - .unwrap_or_else(|err| panic!("expected scoring to succeed: {err:?}")); + let score = h.process(&sentence).map_err(|err| { + TestCaseError::fail(format!( + "capitalized function-word sentence should score: {err:?}" + )) + })?; prop_assert!( score >= 3.0, "expected unresolved pronoun score >= 3.0, got {score}" @@ -234,9 +245,11 @@ proptest! { ) { let sentence = format!("{pronoun} failed."); let h = AmbiguityHeuristic; - let score = h - .process(&sentence) - .unwrap_or_else(|err| panic!("expected scoring to succeed: {err:?}")); + let score = h.process(&sentence).map_err(|err| { + TestCaseError::fail(format!( + "demonstrative-pronoun sentence should score: {err:?}" + )) + })?; prop_assert!( approx_eq(score, 2.0, EPSILON), "expected demonstrative pronoun to be anchored by the verb, got {score}" @@ -251,9 +264,11 @@ proptest! { ) { let sentence = format!("{name}'s device failed. {pronoun} {verb}."); let h = AmbiguityHeuristic; - let score = h - .process(&sentence) - .unwrap_or_else(|err| panic!("expected scoring to succeed: {err:?}")); + let score = h.process(&sentence).map_err(|err| { + TestCaseError::fail(format!( + "possessive proper-noun sentence should score: {err:?}" + )) + })?; prop_assert!( approx_eq(score, 2.0, EPSILON), "expected possessive proper noun to anchor the pronoun, got {score}" diff --git a/tests/lagc_args.rs b/tests/lagc_args.rs index 3495ea4..3063b43 100644 --- a/tests/lagc_args.rs +++ b/tests/lagc_args.rs @@ -61,10 +61,13 @@ impl Drop for EnvVarGuard { #[rstest] #[case(vec!["lagc"], false)] #[case(vec!["lagc", "--dry-run=true"], true)] -fn load_parses_dry_run(#[case] argv: Vec<&str>, #[case] expected: bool) { - let cfg = ::load_from_iter(argv) - .unwrap_or_else(|e| panic!("unexpected parse error: {e}")); +fn load_parses_dry_run( + #[case] argv: Vec<&str>, + #[case] expected: bool, +) -> Result<(), Box> { + let cfg = ::load_from_iter(argv)?; assert_eq!(cfg.dry_run, expected); + Ok(()) } #[rstest] @@ -82,11 +85,11 @@ fn load_rejects_invalid_bool(#[case] value: &str) { #[rstest] #[serial] -fn env_var_parsing_sets_dry_run() { +fn env_var_parsing_sets_dry_run() -> Result<(), Box> { let _guard = EnvVarGuard::new("LAGC_DRY_RUN", "true"); - let cfg = - LagcArgs::load_from_env().unwrap_or_else(|e| panic!("unexpected env parse error: {e}")); + let cfg = LagcArgs::load_from_env()?; assert!(cfg.dry_run); + Ok(()) } #[rstest] @@ -125,10 +128,9 @@ fn config_file_loading( #[case] env_value: Option<&str>, #[case] mode: LoadMode, #[case] expected_dry_run: Option, -) { +) -> Result<(), Box> { let _guard = env_value.map(|value| EnvVarGuard::new("LAGC_DRY_RUN", value)); - let file = - written_config(temp_toml_file, content).unwrap_or_else(|e| panic!("prepare config: {e}")); + let file = written_config(temp_toml_file, content)?; let Some(path) = get_config_path(&file) else { panic!("config path is not valid UTF-8") }; @@ -144,9 +146,10 @@ fn config_file_loading( }; match expected_dry_run { Some(expected) => { - let cfg = result.unwrap_or_else(|e| panic!("unexpected parse error: {e}")); + let cfg = result?; assert_eq!(cfg.dry_run, expected); } None => assert!(result.is_err()), } + Ok(()) } diff --git a/typos.local.toml b/typos.local.toml new file mode 100644 index 0000000..ec83a0b --- /dev/null +++ b/typos.local.toml @@ -0,0 +1,18 @@ +# Repository-specific identifiers, quotations and deliberate fixtures. + +schema = 1 + +[oxford] +stems = [] + +[words] +# Official name: HashiCorp. +accepted = ["Hashi"] + +[words.corrections] + +[patterns] +ignore = ["mis-predictions"] + +[files] +exclude = [] diff --git a/typos.toml b/typos.toml new file mode 100644 index 0000000..9b63a60 --- /dev/null +++ b/typos.toml @@ -0,0 +1,2657 @@ +# 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", + ".terraform", + ".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)```.*?```", + "`[^`\\n]+`", + "mis-predictions", +] + +[default.extend-words] +"Hashi" = "Hashi" +"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" +"artifact" = "artifact" +"artifacts" = "artifacts" +"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" +"dialog" = "dialog" +"dialogs" = "dialogs" +"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" +"organisational" = "organizational" +"organisations" = "organizations" +"organise" = "organize" +"organised" = "organized" +"organiser" = "organizer" +"organisers" = "organizers" +"organises" = "organizes" +"organising" = "organizing" +"organizable" = "organizable" +"organization" = "organization" +"organizational" = "organizational" +"organizations" = "organizations" +"organize" = "organize" +"organized" = "organized" +"organizer" = "organizer" +"organizers" = "organizers" +"organizes" = "organizes" +"organizing" = "organizing" +"oxendict" = "oxendict" +"oxidisable" = "oxidizable" +"oxidisation" = "oxidization" +"oxidisations" = "oxidizations" +"oxidise" = "oxidize" +"oxidised" = "oxidized" +"oxidiser" = "oxidizer" +"oxidisers" = "oxidizers" +"oxidises" = "oxidizes" +"oxidising" = "oxidizing" +"oxidizable" = "oxidizable" +"oxidization" = "oxidization" +"oxidizations" = "oxidizations" +"oxidize" = "oxidize" +"oxidized" = "oxidized" +"oxidizer" = "oxidizer" +"oxidizers" = "oxidizers" +"oxidizes" = "oxidizes" +"oxidizing" = "oxidizing" +"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"