diff --git a/1.13/404.html b/1.13/404.html new file mode 100644 index 000000000..0a5e595b8 --- /dev/null +++ b/1.13/404.html @@ -0,0 +1 @@ + Hatch

404 - Not found

\ No newline at end of file diff --git a/1.13/assets/_mkdocstrings.css b/1.13/assets/_mkdocstrings.css new file mode 100644 index 000000000..85449ec79 --- /dev/null +++ b/1.13/assets/_mkdocstrings.css @@ -0,0 +1,119 @@ + +/* Avoid breaking parameter names, etc. in table cells. */ +.doc-contents td code { + word-break: normal !important; +} + +/* No line break before first paragraph of descriptions. */ +.doc-md-description, +.doc-md-description>p:first-child { + display: inline; +} + +/* Max width for docstring sections tables. */ +.doc .md-typeset__table, +.doc .md-typeset__table table { + display: table !important; + width: 100%; +} + +.doc .md-typeset__table tr { + display: table-row; +} + +/* Defaults in Spacy table style. */ +.doc-param-default { + float: right; +} + +/* Backward-compatibility: docstring section titles in bold. */ +.doc-section-title { + font-weight: bold; +} + +/* Symbols in Navigation and ToC. */ +:root, +[data-md-color-scheme="default"] { + --doc-symbol-attribute-fg-color: #953800; + --doc-symbol-function-fg-color: #8250df; + --doc-symbol-method-fg-color: #8250df; + --doc-symbol-class-fg-color: #0550ae; + --doc-symbol-module-fg-color: #5cad0f; + + --doc-symbol-attribute-bg-color: #9538001a; + --doc-symbol-function-bg-color: #8250df1a; + --doc-symbol-method-bg-color: #8250df1a; + --doc-symbol-class-bg-color: #0550ae1a; + --doc-symbol-module-bg-color: #5cad0f1a; +} + +[data-md-color-scheme="slate"] { + --doc-symbol-attribute-fg-color: #ffa657; + --doc-symbol-function-fg-color: #d2a8ff; + --doc-symbol-method-fg-color: #d2a8ff; + --doc-symbol-class-fg-color: #79c0ff; + --doc-symbol-module-fg-color: #baff79; + + --doc-symbol-attribute-bg-color: #ffa6571a; + --doc-symbol-function-bg-color: #d2a8ff1a; + --doc-symbol-method-bg-color: #d2a8ff1a; + --doc-symbol-class-bg-color: #79c0ff1a; + --doc-symbol-module-bg-color: #baff791a; +} + +code.doc-symbol { + border-radius: .1rem; + font-size: .85em; + padding: 0 .3em; + font-weight: bold; +} + +code.doc-symbol-attribute { + color: var(--doc-symbol-attribute-fg-color); + background-color: var(--doc-symbol-attribute-bg-color); +} + +code.doc-symbol-attribute::after { + content: "attr"; +} + +code.doc-symbol-function { + color: var(--doc-symbol-function-fg-color); + background-color: var(--doc-symbol-function-bg-color); +} + +code.doc-symbol-function::after { + content: "func"; +} + +code.doc-symbol-method { + color: var(--doc-symbol-method-fg-color); + background-color: var(--doc-symbol-method-bg-color); +} + +code.doc-symbol-method::after { + content: "meth"; +} + +code.doc-symbol-class { + color: var(--doc-symbol-class-fg-color); + background-color: var(--doc-symbol-class-bg-color); +} + +code.doc-symbol-class::after { + content: "class"; +} + +code.doc-symbol-module { + color: var(--doc-symbol-module-fg-color); + background-color: var(--doc-symbol-module-bg-color); +} + +code.doc-symbol-module::after { + content: "mod"; +} + +.doc-signature .autorefs { + color: inherit; + border-bottom: 1px dotted currentcolor; +} diff --git a/1.13/assets/css/custom.css b/1.13/assets/css/custom.css new file mode 100644 index 000000000..32fb73e9d --- /dev/null +++ b/1.13/assets/css/custom.css @@ -0,0 +1,22 @@ +:root > * { + /* Use font but disable ligatures, see https://github.com/pypa/hatch/issues/104 */ + font-variant-ligatures: none; +} + +/* Brighter links for dark mode */ +[data-md-color-scheme=slate] { + /* https://github.com/squidfunk/mkdocs-material/blob/9.1.2/src/assets/stylesheets/main/_colors.scss#L91-L92 */ + --md-typeset-a-color: var(--md-primary-fg-color--light); +} + +/* FiraCode https://github.com/tonsky/FiraCode */ +code { font-family: 'Fira Code', monospace; } +@supports (font-variation-settings: normal) { + code { font-family: 'Fira Code VF', monospace; } +} + +/* https://github.com/squidfunk/mkdocs-material/issues/1522 */ +.md-typeset h5 { + color: var(--md-default-fg-color); + text-transform: none; +} diff --git a/1.13/assets/images/favicon.png b/1.13/assets/images/favicon.png new file mode 100644 index 000000000..1cf13b9f9 Binary files /dev/null and b/1.13/assets/images/favicon.png differ diff --git a/1.13/assets/images/logo.svg b/1.13/assets/images/logo.svg new file mode 100644 index 000000000..cbd3be341 --- /dev/null +++ b/1.13/assets/images/logo.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/1.13/assets/images/social/blog/2022/10/08/hatch-v160.png b/1.13/assets/images/social/blog/2022/10/08/hatch-v160.png new file mode 100644 index 000000000..e9565adda Binary files /dev/null and b/1.13/assets/images/social/blog/2022/10/08/hatch-v160.png differ diff --git a/1.13/assets/images/social/blog/2023/12/11/hatch-v180.png b/1.13/assets/images/social/blog/2023/12/11/hatch-v180.png new file mode 100644 index 000000000..d9c4289ff Binary files /dev/null and b/1.13/assets/images/social/blog/2023/12/11/hatch-v180.png differ diff --git a/1.13/assets/images/social/blog/2023/12/18/hatch-v190.png b/1.13/assets/images/social/blog/2023/12/18/hatch-v190.png new file mode 100644 index 000000000..50b6c2935 Binary files /dev/null and b/1.13/assets/images/social/blog/2023/12/18/hatch-v190.png differ diff --git a/1.13/assets/images/social/blog/2024/05/02/hatch-v1100.png b/1.13/assets/images/social/blog/2024/05/02/hatch-v1100.png new file mode 100644 index 000000000..db2e21ab8 Binary files /dev/null and b/1.13/assets/images/social/blog/2024/05/02/hatch-v1100.png differ diff --git a/1.13/assets/images/social/blog/archive/2022.png b/1.13/assets/images/social/blog/archive/2022.png new file mode 100644 index 000000000..eac607eb8 Binary files /dev/null and b/1.13/assets/images/social/blog/archive/2022.png differ diff --git a/1.13/assets/images/social/blog/archive/2023.png b/1.13/assets/images/social/blog/archive/2023.png new file mode 100644 index 000000000..639537e73 Binary files /dev/null and b/1.13/assets/images/social/blog/archive/2023.png differ diff --git a/1.13/assets/images/social/blog/archive/2024.png b/1.13/assets/images/social/blog/archive/2024.png new file mode 100644 index 000000000..f8c7ce8b3 Binary files /dev/null and b/1.13/assets/images/social/blog/archive/2024.png differ diff --git a/1.13/assets/images/social/blog/category/release.png b/1.13/assets/images/social/blog/category/release.png new file mode 100644 index 000000000..f244e3a47 Binary files /dev/null and b/1.13/assets/images/social/blog/category/release.png differ diff --git a/1.13/assets/images/social/blog/index.png b/1.13/assets/images/social/blog/index.png new file mode 100644 index 000000000..95b2b832c Binary files /dev/null and b/1.13/assets/images/social/blog/index.png differ diff --git a/1.13/assets/images/social/build.png b/1.13/assets/images/social/build.png new file mode 100644 index 000000000..04071432a Binary files /dev/null and b/1.13/assets/images/social/build.png differ diff --git a/1.13/assets/images/social/cli/about.png b/1.13/assets/images/social/cli/about.png new file mode 100644 index 000000000..9b3e27084 Binary files /dev/null and b/1.13/assets/images/social/cli/about.png differ diff --git a/1.13/assets/images/social/cli/reference.png b/1.13/assets/images/social/cli/reference.png new file mode 100644 index 000000000..54d412bcd Binary files /dev/null and b/1.13/assets/images/social/cli/reference.png differ diff --git a/1.13/assets/images/social/community/contributing.png b/1.13/assets/images/social/community/contributing.png new file mode 100644 index 000000000..e7755f58c Binary files /dev/null and b/1.13/assets/images/social/community/contributing.png differ diff --git a/1.13/assets/images/social/community/highlights.png b/1.13/assets/images/social/community/highlights.png new file mode 100644 index 000000000..48ad26a6d Binary files /dev/null and b/1.13/assets/images/social/community/highlights.png differ diff --git a/1.13/assets/images/social/community/users.png b/1.13/assets/images/social/community/users.png new file mode 100644 index 000000000..aa66276af Binary files /dev/null and b/1.13/assets/images/social/community/users.png differ diff --git a/1.13/assets/images/social/config/build.png b/1.13/assets/images/social/config/build.png new file mode 100644 index 000000000..14c6c041d Binary files /dev/null and b/1.13/assets/images/social/config/build.png differ diff --git a/1.13/assets/images/social/config/context.png b/1.13/assets/images/social/config/context.png new file mode 100644 index 000000000..cb0c2bfb8 Binary files /dev/null and b/1.13/assets/images/social/config/context.png differ diff --git a/1.13/assets/images/social/config/dependency.png b/1.13/assets/images/social/config/dependency.png new file mode 100644 index 000000000..f14cc869e Binary files /dev/null and b/1.13/assets/images/social/config/dependency.png differ diff --git a/1.13/assets/images/social/config/environment/advanced.png b/1.13/assets/images/social/config/environment/advanced.png new file mode 100644 index 000000000..29c456d93 Binary files /dev/null and b/1.13/assets/images/social/config/environment/advanced.png differ diff --git a/1.13/assets/images/social/config/environment/overview.png b/1.13/assets/images/social/config/environment/overview.png new file mode 100644 index 000000000..28b45b4be Binary files /dev/null and b/1.13/assets/images/social/config/environment/overview.png differ diff --git a/1.13/assets/images/social/config/hatch.png b/1.13/assets/images/social/config/hatch.png new file mode 100644 index 000000000..a635c2caa Binary files /dev/null and b/1.13/assets/images/social/config/hatch.png differ diff --git a/1.13/assets/images/social/config/internal/static-analysis.png b/1.13/assets/images/social/config/internal/static-analysis.png new file mode 100644 index 000000000..f536757fa Binary files /dev/null and b/1.13/assets/images/social/config/internal/static-analysis.png differ diff --git a/1.13/assets/images/social/config/internal/testing.png b/1.13/assets/images/social/config/internal/testing.png new file mode 100644 index 000000000..6ff4976be Binary files /dev/null and b/1.13/assets/images/social/config/internal/testing.png differ diff --git a/1.13/assets/images/social/config/metadata.png b/1.13/assets/images/social/config/metadata.png new file mode 100644 index 000000000..3bd059a51 Binary files /dev/null and b/1.13/assets/images/social/config/metadata.png differ diff --git a/1.13/assets/images/social/config/project-templates.png b/1.13/assets/images/social/config/project-templates.png new file mode 100644 index 000000000..d08857753 Binary files /dev/null and b/1.13/assets/images/social/config/project-templates.png differ diff --git a/1.13/assets/images/social/environment.png b/1.13/assets/images/social/environment.png new file mode 100644 index 000000000..a12bf2ef5 Binary files /dev/null and b/1.13/assets/images/social/environment.png differ diff --git a/1.13/assets/images/social/history/hatch.png b/1.13/assets/images/social/history/hatch.png new file mode 100644 index 000000000..467665a85 Binary files /dev/null and b/1.13/assets/images/social/history/hatch.png differ diff --git a/1.13/assets/images/social/history/hatchling.png b/1.13/assets/images/social/history/hatchling.png new file mode 100644 index 000000000..a19672dd4 Binary files /dev/null and b/1.13/assets/images/social/history/hatchling.png differ diff --git a/1.13/assets/images/social/how-to/config/dynamic-metadata.png b/1.13/assets/images/social/how-to/config/dynamic-metadata.png new file mode 100644 index 000000000..a023e4e34 Binary files /dev/null and b/1.13/assets/images/social/how-to/config/dynamic-metadata.png differ diff --git a/1.13/assets/images/social/how-to/environment/dependency-resolution.png b/1.13/assets/images/social/how-to/environment/dependency-resolution.png new file mode 100644 index 000000000..01356b694 Binary files /dev/null and b/1.13/assets/images/social/how-to/environment/dependency-resolution.png differ diff --git a/1.13/assets/images/social/how-to/environment/select-installer.png b/1.13/assets/images/social/how-to/environment/select-installer.png new file mode 100644 index 000000000..bee2769d0 Binary files /dev/null and b/1.13/assets/images/social/how-to/environment/select-installer.png differ diff --git a/1.13/assets/images/social/how-to/integrate/vscode.png b/1.13/assets/images/social/how-to/integrate/vscode.png new file mode 100644 index 000000000..985069414 Binary files /dev/null and b/1.13/assets/images/social/how-to/integrate/vscode.png differ diff --git a/1.13/assets/images/social/how-to/meta/report-issues.png b/1.13/assets/images/social/how-to/meta/report-issues.png new file mode 100644 index 000000000..34f6c4899 Binary files /dev/null and b/1.13/assets/images/social/how-to/meta/report-issues.png differ diff --git a/1.13/assets/images/social/how-to/plugins/testing-builds.png b/1.13/assets/images/social/how-to/plugins/testing-builds.png new file mode 100644 index 000000000..af7abc4fa Binary files /dev/null and b/1.13/assets/images/social/how-to/plugins/testing-builds.png differ diff --git a/1.13/assets/images/social/how-to/publish/auth.png b/1.13/assets/images/social/how-to/publish/auth.png new file mode 100644 index 000000000..bf150f2e3 Binary files /dev/null and b/1.13/assets/images/social/how-to/publish/auth.png differ diff --git a/1.13/assets/images/social/how-to/publish/repo.png b/1.13/assets/images/social/how-to/publish/repo.png new file mode 100644 index 000000000..0dfd02d41 Binary files /dev/null and b/1.13/assets/images/social/how-to/publish/repo.png differ diff --git a/1.13/assets/images/social/how-to/python/custom.png b/1.13/assets/images/social/how-to/python/custom.png new file mode 100644 index 000000000..767b44e26 Binary files /dev/null and b/1.13/assets/images/social/how-to/python/custom.png differ diff --git a/1.13/assets/images/social/how-to/run/python-scripts.png b/1.13/assets/images/social/how-to/run/python-scripts.png new file mode 100644 index 000000000..db0241c34 Binary files /dev/null and b/1.13/assets/images/social/how-to/run/python-scripts.png differ diff --git a/1.13/assets/images/social/how-to/static-analysis/behavior.png b/1.13/assets/images/social/how-to/static-analysis/behavior.png new file mode 100644 index 000000000..e7a2715b7 Binary files /dev/null and b/1.13/assets/images/social/how-to/static-analysis/behavior.png differ diff --git a/1.13/assets/images/social/index.png b/1.13/assets/images/social/index.png new file mode 100644 index 000000000..a37eaa0f1 Binary files /dev/null and b/1.13/assets/images/social/index.png differ diff --git a/1.13/assets/images/social/install.png b/1.13/assets/images/social/install.png new file mode 100644 index 000000000..a7361c9df Binary files /dev/null and b/1.13/assets/images/social/install.png differ diff --git a/1.13/assets/images/social/intro.png b/1.13/assets/images/social/intro.png new file mode 100644 index 000000000..05a3b25d9 Binary files /dev/null and b/1.13/assets/images/social/intro.png differ diff --git a/1.13/assets/images/social/meta/authors.png b/1.13/assets/images/social/meta/authors.png new file mode 100644 index 000000000..48d7b3d95 Binary files /dev/null and b/1.13/assets/images/social/meta/authors.png differ diff --git a/1.13/assets/images/social/meta/faq.png b/1.13/assets/images/social/meta/faq.png new file mode 100644 index 000000000..3dd7abd0d Binary files /dev/null and b/1.13/assets/images/social/meta/faq.png differ diff --git a/1.13/assets/images/social/next-steps.png b/1.13/assets/images/social/next-steps.png new file mode 100644 index 000000000..91f3b10c3 Binary files /dev/null and b/1.13/assets/images/social/next-steps.png differ diff --git a/1.13/assets/images/social/plugins/about.png b/1.13/assets/images/social/plugins/about.png new file mode 100644 index 000000000..52550ba88 Binary files /dev/null and b/1.13/assets/images/social/plugins/about.png differ diff --git a/1.13/assets/images/social/plugins/build-hook/custom.png b/1.13/assets/images/social/plugins/build-hook/custom.png new file mode 100644 index 000000000..aca28ce3a Binary files /dev/null and b/1.13/assets/images/social/plugins/build-hook/custom.png differ diff --git a/1.13/assets/images/social/plugins/build-hook/reference.png b/1.13/assets/images/social/plugins/build-hook/reference.png new file mode 100644 index 000000000..6b5074823 Binary files /dev/null and b/1.13/assets/images/social/plugins/build-hook/reference.png differ diff --git a/1.13/assets/images/social/plugins/build-hook/version.png b/1.13/assets/images/social/plugins/build-hook/version.png new file mode 100644 index 000000000..9e01b7301 Binary files /dev/null and b/1.13/assets/images/social/plugins/build-hook/version.png differ diff --git a/1.13/assets/images/social/plugins/builder/binary.png b/1.13/assets/images/social/plugins/builder/binary.png new file mode 100644 index 000000000..8233dd7bf Binary files /dev/null and b/1.13/assets/images/social/plugins/builder/binary.png differ diff --git a/1.13/assets/images/social/plugins/builder/custom.png b/1.13/assets/images/social/plugins/builder/custom.png new file mode 100644 index 000000000..662920f0a Binary files /dev/null and b/1.13/assets/images/social/plugins/builder/custom.png differ diff --git a/1.13/assets/images/social/plugins/builder/reference.png b/1.13/assets/images/social/plugins/builder/reference.png new file mode 100644 index 000000000..be5443763 Binary files /dev/null and b/1.13/assets/images/social/plugins/builder/reference.png differ diff --git a/1.13/assets/images/social/plugins/builder/sdist.png b/1.13/assets/images/social/plugins/builder/sdist.png new file mode 100644 index 000000000..707d68d3b Binary files /dev/null and b/1.13/assets/images/social/plugins/builder/sdist.png differ diff --git a/1.13/assets/images/social/plugins/builder/wheel.png b/1.13/assets/images/social/plugins/builder/wheel.png new file mode 100644 index 000000000..6e40e8823 Binary files /dev/null and b/1.13/assets/images/social/plugins/builder/wheel.png differ diff --git a/1.13/assets/images/social/plugins/environment-collector/custom.png b/1.13/assets/images/social/plugins/environment-collector/custom.png new file mode 100644 index 000000000..186d89992 Binary files /dev/null and b/1.13/assets/images/social/plugins/environment-collector/custom.png differ diff --git a/1.13/assets/images/social/plugins/environment-collector/default.png b/1.13/assets/images/social/plugins/environment-collector/default.png new file mode 100644 index 000000000..f2198f8c2 Binary files /dev/null and b/1.13/assets/images/social/plugins/environment-collector/default.png differ diff --git a/1.13/assets/images/social/plugins/environment-collector/reference.png b/1.13/assets/images/social/plugins/environment-collector/reference.png new file mode 100644 index 000000000..97f3c0dde Binary files /dev/null and b/1.13/assets/images/social/plugins/environment-collector/reference.png differ diff --git a/1.13/assets/images/social/plugins/environment/reference.png b/1.13/assets/images/social/plugins/environment/reference.png new file mode 100644 index 000000000..e9a61fefb Binary files /dev/null and b/1.13/assets/images/social/plugins/environment/reference.png differ diff --git a/1.13/assets/images/social/plugins/environment/virtual.png b/1.13/assets/images/social/plugins/environment/virtual.png new file mode 100644 index 000000000..9f29598bb Binary files /dev/null and b/1.13/assets/images/social/plugins/environment/virtual.png differ diff --git a/1.13/assets/images/social/plugins/metadata-hook/custom.png b/1.13/assets/images/social/plugins/metadata-hook/custom.png new file mode 100644 index 000000000..931c36b6d Binary files /dev/null and b/1.13/assets/images/social/plugins/metadata-hook/custom.png differ diff --git a/1.13/assets/images/social/plugins/metadata-hook/reference.png b/1.13/assets/images/social/plugins/metadata-hook/reference.png new file mode 100644 index 000000000..0731491d5 Binary files /dev/null and b/1.13/assets/images/social/plugins/metadata-hook/reference.png differ diff --git a/1.13/assets/images/social/plugins/publisher/package-index.png b/1.13/assets/images/social/plugins/publisher/package-index.png new file mode 100644 index 000000000..4cac9e7c2 Binary files /dev/null and b/1.13/assets/images/social/plugins/publisher/package-index.png differ diff --git a/1.13/assets/images/social/plugins/publisher/reference.png b/1.13/assets/images/social/plugins/publisher/reference.png new file mode 100644 index 000000000..f133eb429 Binary files /dev/null and b/1.13/assets/images/social/plugins/publisher/reference.png differ diff --git a/1.13/assets/images/social/plugins/utilities.png b/1.13/assets/images/social/plugins/utilities.png new file mode 100644 index 000000000..975c6d460 Binary files /dev/null and b/1.13/assets/images/social/plugins/utilities.png differ diff --git a/1.13/assets/images/social/plugins/version-scheme/reference.png b/1.13/assets/images/social/plugins/version-scheme/reference.png new file mode 100644 index 000000000..fd5abdf90 Binary files /dev/null and b/1.13/assets/images/social/plugins/version-scheme/reference.png differ diff --git a/1.13/assets/images/social/plugins/version-scheme/standard.png b/1.13/assets/images/social/plugins/version-scheme/standard.png new file mode 100644 index 000000000..d35a317f8 Binary files /dev/null and b/1.13/assets/images/social/plugins/version-scheme/standard.png differ diff --git a/1.13/assets/images/social/plugins/version-source/code.png b/1.13/assets/images/social/plugins/version-source/code.png new file mode 100644 index 000000000..77e79391f Binary files /dev/null and b/1.13/assets/images/social/plugins/version-source/code.png differ diff --git a/1.13/assets/images/social/plugins/version-source/env.png b/1.13/assets/images/social/plugins/version-source/env.png new file mode 100644 index 000000000..f48a3f385 Binary files /dev/null and b/1.13/assets/images/social/plugins/version-source/env.png differ diff --git a/1.13/assets/images/social/plugins/version-source/reference.png b/1.13/assets/images/social/plugins/version-source/reference.png new file mode 100644 index 000000000..df1ec71cc Binary files /dev/null and b/1.13/assets/images/social/plugins/version-source/reference.png differ diff --git a/1.13/assets/images/social/plugins/version-source/regex.png b/1.13/assets/images/social/plugins/version-source/regex.png new file mode 100644 index 000000000..82c13e28d Binary files /dev/null and b/1.13/assets/images/social/plugins/version-source/regex.png differ diff --git a/1.13/assets/images/social/publish.png b/1.13/assets/images/social/publish.png new file mode 100644 index 000000000..42e3b2bc3 Binary files /dev/null and b/1.13/assets/images/social/publish.png differ diff --git a/1.13/assets/images/social/tutorials/environment/basic-usage.png b/1.13/assets/images/social/tutorials/environment/basic-usage.png new file mode 100644 index 000000000..ebe29f81b Binary files /dev/null and b/1.13/assets/images/social/tutorials/environment/basic-usage.png differ diff --git a/1.13/assets/images/social/tutorials/python/manage.png b/1.13/assets/images/social/tutorials/python/manage.png new file mode 100644 index 000000000..cd05f5b7d Binary files /dev/null and b/1.13/assets/images/social/tutorials/python/manage.png differ diff --git a/1.13/assets/images/social/tutorials/testing/overview.png b/1.13/assets/images/social/tutorials/testing/overview.png new file mode 100644 index 000000000..2247a82c2 Binary files /dev/null and b/1.13/assets/images/social/tutorials/testing/overview.png differ diff --git a/1.13/assets/images/social/version.png b/1.13/assets/images/social/version.png new file mode 100644 index 000000000..425714afb Binary files /dev/null and b/1.13/assets/images/social/version.png differ diff --git a/1.13/assets/images/social/why.png b/1.13/assets/images/social/why.png new file mode 100644 index 000000000..2e56d774d Binary files /dev/null and b/1.13/assets/images/social/why.png differ diff --git a/1.13/assets/javascripts/bundle.e3055991.min.js b/1.13/assets/javascripts/bundle.e3055991.min.js new file mode 100644 index 000000000..d36733df1 --- /dev/null +++ b/1.13/assets/javascripts/bundle.e3055991.min.js @@ -0,0 +1,3 @@ +"use strict";(()=>{var Bi=Object.create;var _r=Object.defineProperty;var Gi=Object.getOwnPropertyDescriptor;var Ji=Object.getOwnPropertyNames,Bt=Object.getOwnPropertySymbols,Xi=Object.getPrototypeOf,Ar=Object.prototype.hasOwnProperty,uo=Object.prototype.propertyIsEnumerable;var fo=(e,t,r)=>t in e?_r(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,j=(e,t)=>{for(var r in t||(t={}))Ar.call(t,r)&&fo(e,r,t[r]);if(Bt)for(var r of Bt(t))uo.call(t,r)&&fo(e,r,t[r]);return e};var ho=(e,t)=>{var r={};for(var o in e)Ar.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(e!=null&&Bt)for(var o of Bt(e))t.indexOf(o)<0&&uo.call(e,o)&&(r[o]=e[o]);return r};var Cr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Zi=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ji(t))!Ar.call(e,n)&&n!==r&&_r(e,n,{get:()=>t[n],enumerable:!(o=Gi(t,n))||o.enumerable});return e};var Gt=(e,t,r)=>(r=e!=null?Bi(Xi(e)):{},Zi(t||!e||!e.__esModule?_r(r,"default",{value:e,enumerable:!0}):r,e));var bo=(e,t,r)=>new Promise((o,n)=>{var i=c=>{try{a(r.next(c))}catch(p){n(p)}},s=c=>{try{a(r.throw(c))}catch(p){n(p)}},a=c=>c.done?o(c.value):Promise.resolve(c.value).then(i,s);a((r=r.apply(e,t)).next())});var go=Cr((Hr,vo)=>{(function(e,t){typeof Hr=="object"&&typeof vo!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(Hr,function(){"use strict";function e(r){var o=!0,n=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(H){return!!(H&&H!==document&&H.nodeName!=="HTML"&&H.nodeName!=="BODY"&&"classList"in H&&"contains"in H.classList)}function c(H){var ft=H.type,Fe=H.tagName;return!!(Fe==="INPUT"&&s[ft]&&!H.readOnly||Fe==="TEXTAREA"&&!H.readOnly||H.isContentEditable)}function p(H){H.classList.contains("focus-visible")||(H.classList.add("focus-visible"),H.setAttribute("data-focus-visible-added",""))}function l(H){H.hasAttribute("data-focus-visible-added")&&(H.classList.remove("focus-visible"),H.removeAttribute("data-focus-visible-added"))}function f(H){H.metaKey||H.altKey||H.ctrlKey||(a(r.activeElement)&&p(r.activeElement),o=!0)}function u(H){o=!1}function d(H){a(H.target)&&(o||c(H.target))&&p(H.target)}function g(H){a(H.target)&&(H.target.classList.contains("focus-visible")||H.target.hasAttribute("data-focus-visible-added"))&&(n=!0,window.clearTimeout(i),i=window.setTimeout(function(){n=!1},100),l(H.target))}function L(H){document.visibilityState==="hidden"&&(n&&(o=!0),ee())}function ee(){document.addEventListener("mousemove",Z),document.addEventListener("mousedown",Z),document.addEventListener("mouseup",Z),document.addEventListener("pointermove",Z),document.addEventListener("pointerdown",Z),document.addEventListener("pointerup",Z),document.addEventListener("touchmove",Z),document.addEventListener("touchstart",Z),document.addEventListener("touchend",Z)}function ne(){document.removeEventListener("mousemove",Z),document.removeEventListener("mousedown",Z),document.removeEventListener("mouseup",Z),document.removeEventListener("pointermove",Z),document.removeEventListener("pointerdown",Z),document.removeEventListener("pointerup",Z),document.removeEventListener("touchmove",Z),document.removeEventListener("touchstart",Z),document.removeEventListener("touchend",Z)}function Z(H){H.target.nodeName&&H.target.nodeName.toLowerCase()==="html"||(o=!1,ne())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",u,!0),document.addEventListener("pointerdown",u,!0),document.addEventListener("touchstart",u,!0),document.addEventListener("visibilitychange",L,!0),ee(),r.addEventListener("focus",d,!0),r.addEventListener("blur",g,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var io=Cr((Vt,no)=>{(function(t,r){typeof Vt=="object"&&typeof no=="object"?no.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Vt=="object"?Vt.ClipboardJS=r():t.ClipboardJS=r()})(Vt,function(){return function(){var e={686:function(o,n,i){"use strict";i.d(n,{default:function(){return Yi}});var s=i(279),a=i.n(s),c=i(370),p=i.n(c),l=i(817),f=i.n(l);function u(z){try{return document.execCommand(z)}catch(C){return!1}}var d=function(C){var _=f()(C);return u("cut"),_},g=d;function L(z){var C=document.documentElement.getAttribute("dir")==="rtl",_=document.createElement("textarea");_.style.fontSize="12pt",_.style.border="0",_.style.padding="0",_.style.margin="0",_.style.position="absolute",_.style[C?"right":"left"]="-9999px";var D=window.pageYOffset||document.documentElement.scrollTop;return _.style.top="".concat(D,"px"),_.setAttribute("readonly",""),_.value=z,_}var ee=function(C,_){var D=L(C);_.container.appendChild(D);var N=f()(D);return u("copy"),D.remove(),N},ne=function(C){var _=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},D="";return typeof C=="string"?D=ee(C,_):C instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(C==null?void 0:C.type)?D=ee(C.value,_):(D=f()(C),u("copy")),D},Z=ne;function H(z){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?H=function(_){return typeof _}:H=function(_){return _&&typeof Symbol=="function"&&_.constructor===Symbol&&_!==Symbol.prototype?"symbol":typeof _},H(z)}var ft=function(){var C=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},_=C.action,D=_===void 0?"copy":_,N=C.container,G=C.target,Ue=C.text;if(D!=="copy"&&D!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(G!==void 0)if(G&&H(G)==="object"&&G.nodeType===1){if(D==="copy"&&G.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(D==="cut"&&(G.hasAttribute("readonly")||G.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Ue)return Z(Ue,{container:N});if(G)return D==="cut"?g(G):Z(G,{container:N})},Fe=ft;function R(z){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?R=function(_){return typeof _}:R=function(_){return _&&typeof Symbol=="function"&&_.constructor===Symbol&&_!==Symbol.prototype?"symbol":typeof _},R(z)}function se(z,C){if(!(z instanceof C))throw new TypeError("Cannot call a class as a function")}function ce(z,C){for(var _=0;_0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof N.action=="function"?N.action:this.defaultAction,this.target=typeof N.target=="function"?N.target:this.defaultTarget,this.text=typeof N.text=="function"?N.text:this.defaultText,this.container=R(N.container)==="object"?N.container:document.body}},{key:"listenClick",value:function(N){var G=this;this.listener=p()(N,"click",function(Ue){return G.onClick(Ue)})}},{key:"onClick",value:function(N){var G=N.delegateTarget||N.currentTarget,Ue=this.action(G)||"copy",Yt=Fe({action:Ue,container:this.container,target:this.target(G),text:this.text(G)});this.emit(Yt?"success":"error",{action:Ue,text:Yt,trigger:G,clearSelection:function(){G&&G.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(N){return Mr("action",N)}},{key:"defaultTarget",value:function(N){var G=Mr("target",N);if(G)return document.querySelector(G)}},{key:"defaultText",value:function(N){return Mr("text",N)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(N){var G=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return Z(N,G)}},{key:"cut",value:function(N){return g(N)}},{key:"isSupported",value:function(){var N=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],G=typeof N=="string"?[N]:N,Ue=!!document.queryCommandSupported;return G.forEach(function(Yt){Ue=Ue&&!!document.queryCommandSupported(Yt)}),Ue}}]),_}(a()),Yi=Qi},828:function(o){var n=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,c){for(;a&&a.nodeType!==n;){if(typeof a.matches=="function"&&a.matches(c))return a;a=a.parentNode}}o.exports=s},438:function(o,n,i){var s=i(828);function a(l,f,u,d,g){var L=p.apply(this,arguments);return l.addEventListener(u,L,g),{destroy:function(){l.removeEventListener(u,L,g)}}}function c(l,f,u,d,g){return typeof l.addEventListener=="function"?a.apply(null,arguments):typeof u=="function"?a.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(L){return a(L,f,u,d,g)}))}function p(l,f,u,d){return function(g){g.delegateTarget=s(g.target,f),g.delegateTarget&&d.call(l,g)}}o.exports=c},879:function(o,n){n.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},n.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||n.node(i[0]))},n.string=function(i){return typeof i=="string"||i instanceof String},n.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(o,n,i){var s=i(879),a=i(438);function c(u,d,g){if(!u&&!d&&!g)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(g))throw new TypeError("Third argument must be a Function");if(s.node(u))return p(u,d,g);if(s.nodeList(u))return l(u,d,g);if(s.string(u))return f(u,d,g);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function p(u,d,g){return u.addEventListener(d,g),{destroy:function(){u.removeEventListener(d,g)}}}function l(u,d,g){return Array.prototype.forEach.call(u,function(L){L.addEventListener(d,g)}),{destroy:function(){Array.prototype.forEach.call(u,function(L){L.removeEventListener(d,g)})}}}function f(u,d,g){return a(document.body,u,d,g)}o.exports=c},817:function(o){function n(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var c=window.getSelection(),p=document.createRange();p.selectNodeContents(i),c.removeAllRanges(),c.addRange(p),s=c.toString()}return s}o.exports=n},279:function(o){function n(){}n.prototype={on:function(i,s,a){var c=this.e||(this.e={});return(c[i]||(c[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var c=this;function p(){c.off(i,p),s.apply(a,arguments)}return p._=s,this.on(i,p,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),c=0,p=a.length;for(c;c{"use strict";var fs=/["'&<>]/;di.exports=us;function us(e){var t=""+e,r=fs.exec(t);if(!r)return t;var o,n="",i=0,s=0;for(i=r.index;i0&&i[i.length-1])&&(p[0]===6||p[0]===2)){r=0;continue}if(p[0]===3&&(!i||p[1]>i[0]&&p[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function q(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],s;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(a){s={error:a}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(s)throw s.error}}return i}function B(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o1||a(u,d)})})}function a(u,d){try{c(o[u](d))}catch(g){f(i[0][3],g)}}function c(u){u.value instanceof ut?Promise.resolve(u.value.v).then(p,l):f(i[0][2],u)}function p(u){a("next",u)}function l(u){a("throw",u)}function f(u,d){u(d),i.shift(),i.length&&a(i[0][0],i[0][1])}}function Eo(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof Oe=="function"?Oe(e):e[Symbol.iterator](),r={},o("next"),o("throw"),o("return"),r[Symbol.asyncIterator]=function(){return this},r);function o(i){r[i]=e[i]&&function(s){return new Promise(function(a,c){s=e[i](s),n(a,c,s.done,s.value)})}}function n(i,s,a,c){Promise.resolve(c).then(function(p){i({value:p,done:a})},s)}}function P(e){return typeof e=="function"}function xt(e){var t=function(o){Error.call(o),o.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var Xt=xt(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(o,n){return n+1+") "+o.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Xe(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var ze=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,o,n,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=Oe(s),c=a.next();!c.done;c=a.next()){var p=c.value;p.remove(this)}}catch(L){t={error:L}}finally{try{c&&!c.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var l=this.initialTeardown;if(P(l))try{l()}catch(L){i=L instanceof Xt?L.errors:[L]}var f=this._finalizers;if(f){this._finalizers=null;try{for(var u=Oe(f),d=u.next();!d.done;d=u.next()){var g=d.value;try{wo(g)}catch(L){i=i!=null?i:[],L instanceof Xt?i=B(B([],q(i)),q(L.errors)):i.push(L)}}}catch(L){o={error:L}}finally{try{d&&!d.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}}if(i)throw new Xt(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)wo(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Xe(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Xe(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var $r=ze.EMPTY;function Zt(e){return e instanceof ze||e&&"closed"in e&&P(e.remove)&&P(e.add)&&P(e.unsubscribe)}function wo(e){P(e)?e():e.unsubscribe()}var We={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var yt={setTimeout:function(e,t){for(var r=[],o=2;o0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var o=this,n=this,i=n.hasError,s=n.isStopped,a=n.observers;return i||s?$r:(this.currentObservers=null,a.push(r),new ze(function(){o.currentObservers=null,Xe(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var o=this,n=o.hasError,i=o.thrownError,s=o.isStopped;n?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new I;return r.source=this,r},t.create=function(r,o){return new Co(r,o)},t}(I);var Co=function(e){ie(t,e);function t(r,o){var n=e.call(this)||this;return n.destination=r,n.source=o,n}return t.prototype.next=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.next)===null||n===void 0||n.call(o,r)},t.prototype.error=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.error)===null||n===void 0||n.call(o,r)},t.prototype.complete=function(){var r,o;(o=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||o===void 0||o.call(r)},t.prototype._subscribe=function(r){var o,n;return(n=(o=this.source)===null||o===void 0?void 0:o.subscribe(r))!==null&&n!==void 0?n:$r},t}(T);var jr=function(e){ie(t,e);function t(r){var o=e.call(this)||this;return o._value=r,o}return Object.defineProperty(t.prototype,"value",{get:function(){return this.getValue()},enumerable:!1,configurable:!0}),t.prototype._subscribe=function(r){var o=e.prototype._subscribe.call(this,r);return!o.closed&&r.next(this._value),o},t.prototype.getValue=function(){var r=this,o=r.hasError,n=r.thrownError,i=r._value;if(o)throw n;return this._throwIfClosed(),i},t.prototype.next=function(r){e.prototype.next.call(this,this._value=r)},t}(T);var Pt={now:function(){return(Pt.delegate||Date).now()},delegate:void 0};var It=function(e){ie(t,e);function t(r,o,n){r===void 0&&(r=1/0),o===void 0&&(o=1/0),n===void 0&&(n=Pt);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=o,i._timestampProvider=n,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=o===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,o),i}return t.prototype.next=function(r){var o=this,n=o.isStopped,i=o._buffer,s=o._infiniteTimeWindow,a=o._timestampProvider,c=o._windowTime;n||(i.push(r),!s&&i.push(a.now()+c)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var o=this._innerSubscribe(r),n=this,i=n._infiniteTimeWindow,s=n._buffer,a=s.slice(),c=0;c0?e.prototype.schedule.call(this,r,o):(this.delay=o,this.state=r,this.scheduler.flush(this),this)},t.prototype.execute=function(r,o){return o>0||this.closed?e.prototype.execute.call(this,r,o):this._execute(r,o)},t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!=null&&n>0||n==null&&this.delay>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.flush(this),0)},t}(St);var $o=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t}(Ot);var Dr=new $o(ko);var Ro=function(e){ie(t,e);function t(r,o){var n=e.call(this,r,o)||this;return n.scheduler=r,n.work=o,n}return t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!==null&&n>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.actions.push(this),r._scheduled||(r._scheduled=Tt.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,o,n){var i;if(n===void 0&&(n=0),n!=null?n>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,o,n);var s=r.actions;o!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==o&&(Tt.cancelAnimationFrame(o),r._scheduled=void 0)},t}(St);var Po=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var o=this._scheduled;this._scheduled=void 0;var n=this.actions,i;r=r||n.shift();do if(i=r.execute(r.state,r.delay))break;while((r=n[0])&&r.id===o&&n.shift());if(this._active=!1,i){for(;(r=n[0])&&r.id===o&&n.shift();)r.unsubscribe();throw i}},t}(Ot);var ge=new Po(Ro);var x=new I(function(e){return e.complete()});function rr(e){return e&&P(e.schedule)}function Nr(e){return e[e.length-1]}function ct(e){return P(Nr(e))?e.pop():void 0}function Ie(e){return rr(Nr(e))?e.pop():void 0}function or(e,t){return typeof Nr(e)=="number"?e.pop():t}var Lt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function nr(e){return P(e==null?void 0:e.then)}function ir(e){return P(e[wt])}function ar(e){return Symbol.asyncIterator&&P(e==null?void 0:e[Symbol.asyncIterator])}function sr(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function ca(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var cr=ca();function pr(e){return P(e==null?void 0:e[cr])}function lr(e){return yo(this,arguments,function(){var r,o,n,i;return Jt(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,ut(r.read())];case 3:return o=s.sent(),n=o.value,i=o.done,i?[4,ut(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,ut(n)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function mr(e){return P(e==null?void 0:e.getReader)}function U(e){if(e instanceof I)return e;if(e!=null){if(ir(e))return pa(e);if(Lt(e))return la(e);if(nr(e))return ma(e);if(ar(e))return Io(e);if(pr(e))return fa(e);if(mr(e))return ua(e)}throw sr(e)}function pa(e){return new I(function(t){var r=e[wt]();if(P(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function la(e){return new I(function(t){for(var r=0;r=2;return function(o){return o.pipe(e?v(function(n,i){return e(n,i,o)}):be,Ee(1),r?rt(t):Zo(function(){return new ur}))}}function Yr(e){return e<=0?function(){return x}:E(function(t,r){var o=[];t.subscribe(w(r,function(n){o.push(n),e=2,!0))}function le(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new T}:t,o=e.resetOnError,n=o===void 0?!0:o,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,c=a===void 0?!0:a;return function(p){var l,f,u,d=0,g=!1,L=!1,ee=function(){f==null||f.unsubscribe(),f=void 0},ne=function(){ee(),l=u=void 0,g=L=!1},Z=function(){var H=l;ne(),H==null||H.unsubscribe()};return E(function(H,ft){d++,!L&&!g&&ee();var Fe=u=u!=null?u:r();ft.add(function(){d--,d===0&&!L&&!g&&(f=Br(Z,c))}),Fe.subscribe(ft),!l&&d>0&&(l=new ht({next:function(R){return Fe.next(R)},error:function(R){L=!0,ee(),f=Br(ne,n,R),Fe.error(R)},complete:function(){g=!0,ee(),f=Br(ne,s),Fe.complete()}}),U(H).subscribe(l))})(p)}}function Br(e,t){for(var r=[],o=2;oe.next(document)),e}function M(e,t=document){return Array.from(t.querySelectorAll(e))}function F(e,t=document){let r=ue(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function ue(e,t=document){return t.querySelector(e)||void 0}function Ve(){var e,t,r,o;return(o=(r=(t=(e=document.activeElement)==null?void 0:e.shadowRoot)==null?void 0:t.activeElement)!=null?r:document.activeElement)!=null?o:void 0}var Ha=O(h(document.body,"focusin"),h(document.body,"focusout")).pipe(Ae(1),K(void 0),m(()=>Ve()||document.body),X(1));function Ke(e){return Ha.pipe(m(t=>e.contains(t)),Y())}function nt(e,t){return k(()=>O(h(e,"mouseenter").pipe(m(()=>!0)),h(e,"mouseleave").pipe(m(()=>!1))).pipe(t?jt(r=>ke(+!r*t)):be,K(e.matches(":hover"))))}function nn(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)nn(e,r)}function y(e,t,...r){let o=document.createElement(e);if(t)for(let n of Object.keys(t))typeof t[n]!="undefined"&&(typeof t[n]!="boolean"?o.setAttribute(n,t[n]):o.setAttribute(n,""));for(let n of r)nn(o,n);return o}function br(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function At(e){let t=y("script",{src:e});return k(()=>(document.head.appendChild(t),O(h(t,"load"),h(t,"error").pipe(b(()=>Vr(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),A(()=>document.head.removeChild(t)),Ee(1))))}var an=new T,ka=k(()=>typeof ResizeObserver=="undefined"?At("https://unpkg.com/resize-observer-polyfill"):$(void 0)).pipe(m(()=>new ResizeObserver(e=>e.forEach(t=>an.next(t)))),b(e=>O(et,$(e)).pipe(A(()=>e.disconnect()))),X(1));function de(e){return{width:e.offsetWidth,height:e.offsetHeight}}function Le(e){let t=e;for(;t.clientWidth===0&&t.parentElement;)t=t.parentElement;return ka.pipe(S(r=>r.observe(t)),b(r=>an.pipe(v(o=>o.target===t),A(()=>r.unobserve(t)))),m(()=>de(e)),K(de(e)))}function Ct(e){return{width:e.scrollWidth,height:e.scrollHeight}}function vr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}function sn(e){let t=[],r=e.parentElement;for(;r;)(e.clientWidth>r.clientWidth||e.clientHeight>r.clientHeight)&&t.push(r),r=(e=r).parentElement;return t.length===0&&t.push(document.documentElement),t}function Qe(e){return{x:e.offsetLeft,y:e.offsetTop}}function cn(e){let t=e.getBoundingClientRect();return{x:t.x+window.scrollX,y:t.y+window.scrollY}}function pn(e){return O(h(window,"load"),h(window,"resize")).pipe($e(0,ge),m(()=>Qe(e)),K(Qe(e)))}function gr(e){return{x:e.scrollLeft,y:e.scrollTop}}function Ye(e){return O(h(e,"scroll"),h(window,"scroll"),h(window,"resize")).pipe($e(0,ge),m(()=>gr(e)),K(gr(e)))}var ln=new T,$a=k(()=>$(new IntersectionObserver(e=>{for(let t of e)ln.next(t)},{threshold:0}))).pipe(b(e=>O(et,$(e)).pipe(A(()=>e.disconnect()))),X(1));function lt(e){return $a.pipe(S(t=>t.observe(e)),b(t=>ln.pipe(v(({target:r})=>r===e),A(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function mn(e,t=16){return Ye(e).pipe(m(({y:r})=>{let o=de(e),n=Ct(e);return r>=n.height-o.height-t}),Y())}var xr={drawer:F("[data-md-toggle=drawer]"),search:F("[data-md-toggle=search]")};function fn(e){return xr[e].checked}function it(e,t){xr[e].checked!==t&&xr[e].click()}function Be(e){let t=xr[e];return h(t,"change").pipe(m(()=>t.checked),K(t.checked))}function Ra(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Pa(){return O(h(window,"compositionstart").pipe(m(()=>!0)),h(window,"compositionend").pipe(m(()=>!1))).pipe(K(!1))}function un(){let e=h(window,"keydown").pipe(v(t=>!(t.metaKey||t.ctrlKey)),m(t=>({mode:fn("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),v(({mode:t,type:r})=>{if(t==="global"){let o=Ve();if(typeof o!="undefined")return!Ra(o,r)}return!0}),le());return Pa().pipe(b(t=>t?x:e))}function we(){return new URL(location.href)}function at(e,t=!1){if(Q("navigation.instant")&&!t){let r=y("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function dn(){return new T}function hn(){return location.hash.slice(1)}function bn(e){let t=y("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Zr(e){return O(h(window,"hashchange"),e).pipe(m(hn),K(hn()),v(t=>t.length>0),X(1))}function vn(e){return Zr(e).pipe(m(t=>ue(`[id="${t}"]`)),v(t=>typeof t!="undefined"))}function Wt(e){let t=matchMedia(e);return dr(r=>t.addListener(()=>r(t.matches))).pipe(K(t.matches))}function gn(){let e=matchMedia("print");return O(h(window,"beforeprint").pipe(m(()=>!0)),h(window,"afterprint").pipe(m(()=>!1))).pipe(K(e.matches))}function eo(e,t){return e.pipe(b(r=>r?t():x))}function to(e,t){return new I(r=>{let o=new XMLHttpRequest;return o.open("GET",`${e}`),o.responseType="blob",o.addEventListener("load",()=>{o.status>=200&&o.status<300?(r.next(o.response),r.complete()):r.error(new Error(o.statusText))}),o.addEventListener("error",()=>{r.error(new Error("Network error"))}),o.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(o.addEventListener("progress",n=>{var i;if(n.lengthComputable)t.progress$.next(n.loaded/n.total*100);else{let s=(i=o.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(n.loaded/+s*100)}}),t.progress$.next(5)),o.send(),()=>o.abort()})}function Ge(e,t){return to(e,t).pipe(b(r=>r.text()),m(r=>JSON.parse(r)),X(1))}function yr(e,t){let r=new DOMParser;return to(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/html")),X(1))}function xn(e,t){let r=new DOMParser;return to(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/xml")),X(1))}function yn(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function En(){return O(h(window,"scroll",{passive:!0}),h(window,"resize",{passive:!0})).pipe(m(yn),K(yn()))}function wn(){return{width:innerWidth,height:innerHeight}}function Tn(){return h(window,"resize",{passive:!0}).pipe(m(wn),K(wn()))}function Sn(){return V([En(),Tn()]).pipe(m(([e,t])=>({offset:e,size:t})),X(1))}function Er(e,{viewport$:t,header$:r}){let o=t.pipe(oe("size")),n=V([o,r]).pipe(m(()=>Qe(e)));return V([r,t,n]).pipe(m(([{height:i},{offset:s,size:a},{x:c,y:p}])=>({offset:{x:s.x-c,y:s.y-p+i},size:a})))}function Ia(e){return h(e,"message",t=>t.data)}function Fa(e){let t=new T;return t.subscribe(r=>e.postMessage(r)),t}function On(e,t=new Worker(e)){let r=Ia(t),o=Fa(t),n=new T;n.subscribe(o);let i=o.pipe(re(),ae(!0));return n.pipe(re(),Ne(r.pipe(W(i))),le())}var ja=F("#__config"),Ht=JSON.parse(ja.textContent);Ht.base=`${new URL(Ht.base,we())}`;function Te(){return Ht}function Q(e){return Ht.features.includes(e)}function Me(e,t){return typeof t!="undefined"?Ht.translations[e].replace("#",t.toString()):Ht.translations[e]}function Ce(e,t=document){return F(`[data-md-component=${e}]`,t)}function me(e,t=document){return M(`[data-md-component=${e}]`,t)}function Ua(e){let t=F(".md-typeset > :first-child",e);return h(t,"click",{once:!0}).pipe(m(()=>F(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function Ln(e){if(!Q("announce.dismiss")||!e.childElementCount)return x;if(!e.hidden){let t=F(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return k(()=>{let t=new T;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),Ua(e).pipe(S(r=>t.next(r)),A(()=>t.complete()),m(r=>j({ref:e},r)))})}function Wa(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function Mn(e,t){let r=new T;return r.subscribe(({hidden:o})=>{e.hidden=o}),Wa(e,t).pipe(S(o=>r.next(o)),A(()=>r.complete()),m(o=>j({ref:e},o)))}function Dt(e,t){return t==="inline"?y("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},y("div",{class:"md-tooltip__inner md-typeset"})):y("div",{class:"md-tooltip",id:e,role:"tooltip"},y("div",{class:"md-tooltip__inner md-typeset"}))}function wr(...e){return y("div",{class:"md-tooltip2",role:"dialog"},y("div",{class:"md-tooltip2__inner md-typeset"},e))}function _n(...e){return y("div",{class:"md-tooltip2",role:"tooltip"},y("div",{class:"md-tooltip2__inner md-typeset"},e))}function An(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return y("aside",{class:"md-annotation",tabIndex:0},Dt(t),y("a",{href:r,class:"md-annotation__index",tabIndex:-1},y("span",{"data-md-annotation-id":e})))}else return y("aside",{class:"md-annotation",tabIndex:0},Dt(t),y("span",{class:"md-annotation__index",tabIndex:-1},y("span",{"data-md-annotation-id":e})))}function Cn(e){return y("button",{class:"md-code__button",title:Me("clipboard.copy"),"data-clipboard-target":`#${e} > code`,"data-md-type":"copy"})}function Hn(){return y("button",{class:"md-code__button",title:"Toggle line selection","data-md-type":"select"})}function kn(){return y("nav",{class:"md-code__nav"})}function ro(e,t){let r=t&2,o=t&1,n=Object.keys(e.terms).filter(c=>!e.terms[c]).reduce((c,p)=>[...c,y("del",null,p)," "],[]).slice(0,-1),i=Te(),s=new URL(e.location,i.base);Q("search.highlight")&&s.searchParams.set("h",Object.entries(e.terms).filter(([,c])=>c).reduce((c,[p])=>`${c} ${p}`.trim(),""));let{tags:a}=Te();return y("a",{href:`${s}`,class:"md-search-result__link",tabIndex:-1},y("article",{class:"md-search-result__article md-typeset","data-md-score":e.score.toFixed(2)},r>0&&y("div",{class:"md-search-result__icon md-icon"}),r>0&&y("h1",null,e.title),r<=0&&y("h2",null,e.title),o>0&&e.text.length>0&&e.text,e.tags&&e.tags.map(c=>{let p=a?c in a?`md-tag-icon md-tag--${a[c]}`:"md-tag-icon":"";return y("span",{class:`md-tag ${p}`},c)}),o>0&&n.length>0&&y("p",{class:"md-search-result__terms"},Me("search.result.term.missing"),": ",...n)))}function $n(e){let t=e[0].score,r=[...e],o=Te(),n=r.findIndex(l=>!`${new URL(l.location,o.base)}`.includes("#")),[i]=r.splice(n,1),s=r.findIndex(l=>l.scorero(l,1)),...c.length?[y("details",{class:"md-search-result__more"},y("summary",{tabIndex:-1},y("div",null,c.length>0&&c.length===1?Me("search.result.more.one"):Me("search.result.more.other",c.length))),...c.map(l=>ro(l,1)))]:[]];return y("li",{class:"md-search-result__item"},p)}function Rn(e){return y("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>y("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?br(r):r)))}function oo(e){let t=`tabbed-control tabbed-control--${e}`;return y("div",{class:t,hidden:!0},y("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function Pn(e){return y("div",{class:"md-typeset__scrollwrap"},y("div",{class:"md-typeset__table"},e))}function Da(e){var o;let t=Te(),r=new URL(`../${e.version}/`,t.base);return y("li",{class:"md-version__item"},y("a",{href:`${r}`,class:"md-version__link"},e.title,((o=t.version)==null?void 0:o.alias)&&e.aliases.length>0&&y("span",{class:"md-version__alias"},e.aliases[0])))}function In(e,t){var o;let r=Te();return e=e.filter(n=>{var i;return!((i=n.properties)!=null&&i.hidden)}),y("div",{class:"md-version"},y("button",{class:"md-version__current","aria-label":Me("select.version")},t.title,((o=r.version)==null?void 0:o.alias)&&t.aliases.length>0&&y("span",{class:"md-version__alias"},t.aliases[0])),y("ul",{class:"md-version__list"},e.map(Da)))}var Na=0;function Va(e,t=250){let r=V([Ke(e),nt(e,t)]).pipe(m(([n,i])=>n||i),Y()),o=k(()=>sn(e)).pipe(J(Ye),gt(1),m(()=>cn(e)));return r.pipe(Re(n=>n),b(()=>V([r,o])),m(([n,i])=>({active:n,offset:i})),le())}function Nt(e,t,r=250){let{content$:o,viewport$:n}=t,i=`__tooltip2_${Na++}`;return k(()=>{let s=new T,a=new jr(!1);s.pipe(re(),ae(!1)).subscribe(a);let c=a.pipe(jt(l=>ke(+!l*250,Dr)),Y(),b(l=>l?o:x),S(l=>l.id=i),le());V([s.pipe(m(({active:l})=>l)),c.pipe(b(l=>nt(l,250)),K(!1))]).pipe(m(l=>l.some(f=>f))).subscribe(a);let p=a.pipe(v(l=>l),te(c,n),m(([l,f,{size:u}])=>{let d=e.getBoundingClientRect(),g=d.width/2;if(f.role==="tooltip")return{x:g,y:8+d.height};if(d.y>=u.height/2){let{height:L}=de(f);return{x:g,y:-16-L}}else return{x:g,y:16+d.height}}));return V([c,s,p]).subscribe(([l,{offset:f},u])=>{l.style.setProperty("--md-tooltip-host-x",`${f.x}px`),l.style.setProperty("--md-tooltip-host-y",`${f.y}px`),l.style.setProperty("--md-tooltip-x",`${u.x}px`),l.style.setProperty("--md-tooltip-y",`${u.y}px`),l.classList.toggle("md-tooltip2--top",u.y<0),l.classList.toggle("md-tooltip2--bottom",u.y>=0)}),a.pipe(v(l=>l),te(c,(l,f)=>f),v(l=>l.role==="tooltip")).subscribe(l=>{let f=de(F(":scope > *",l));l.style.setProperty("--md-tooltip-width",`${f.width}px`),l.style.setProperty("--md-tooltip-tail","0px")}),a.pipe(Y(),xe(ge),te(c)).subscribe(([l,f])=>{f.classList.toggle("md-tooltip2--active",l)}),V([a.pipe(v(l=>l)),c]).subscribe(([l,f])=>{f.role==="dialog"?(e.setAttribute("aria-controls",i),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",i)}),a.pipe(v(l=>!l)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),Va(e,r).pipe(S(l=>s.next(l)),A(()=>s.complete()),m(l=>j({ref:e},l)))})}function Je(e,{viewport$:t},r=document.body){return Nt(e,{content$:new I(o=>{let n=e.title,i=_n(n);return o.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",n)}}),viewport$:t},0)}function za(e,t){let r=k(()=>V([pn(e),Ye(t)])).pipe(m(([{x:o,y:n},i])=>{let{width:s,height:a}=de(e);return{x:o-i.x+s/2,y:n-i.y+a/2}}));return Ke(e).pipe(b(o=>r.pipe(m(n=>({active:o,offset:n})),Ee(+!o||1/0))))}function Fn(e,t,{target$:r}){let[o,n]=Array.from(e.children);return k(()=>{let i=new T,s=i.pipe(re(),ae(!0));return i.subscribe({next({offset:a}){e.style.setProperty("--md-tooltip-x",`${a.x}px`),e.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),lt(e).pipe(W(s)).subscribe(a=>{e.toggleAttribute("data-md-visible",a)}),O(i.pipe(v(({active:a})=>a)),i.pipe(Ae(250),v(({active:a})=>!a))).subscribe({next({active:a}){a?e.prepend(o):o.remove()},complete(){e.prepend(o)}}),i.pipe($e(16,ge)).subscribe(({active:a})=>{o.classList.toggle("md-tooltip--active",a)}),i.pipe(gt(125,ge),v(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?e.style.setProperty("--md-tooltip-0",`${-a}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),h(n,"click").pipe(W(s),v(a=>!(a.metaKey||a.ctrlKey))).subscribe(a=>{a.stopPropagation(),a.preventDefault()}),h(n,"mousedown").pipe(W(s),te(i)).subscribe(([a,{active:c}])=>{var p;if(a.button!==0||a.metaKey||a.ctrlKey)a.preventDefault();else if(c){a.preventDefault();let l=e.parentElement.closest(".md-annotation");l instanceof HTMLElement?l.focus():(p=Ve())==null||p.blur()}}),r.pipe(W(s),v(a=>a===o),ot(125)).subscribe(()=>e.focus()),za(e,t).pipe(S(a=>i.next(a)),A(()=>i.complete()),m(a=>j({ref:e},a)))})}function qa(e){let t=Te();if(e.tagName!=="CODE")return[e];let r=[".c",".c1",".cm"];if(typeof t.annotate!="undefined"){let o=e.closest("[class|=language]");if(o)for(let n of Array.from(o.classList)){if(!n.startsWith("language-"))continue;let[,i]=n.split("-");i in t.annotate&&r.push(...t.annotate[i])}}return M(r.join(", "),e)}function Ka(e){let t=[];for(let r of qa(e)){let o=[],n=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=n.nextNode();i;i=n.nextNode())o.push(i);for(let i of o){let s;for(;s=/(\(\d+\))(!)?/.exec(i.textContent);){let[,a,c]=s;if(typeof c=="undefined"){let p=i.splitText(s.index);i=p.splitText(a.length),t.push(p)}else{i.textContent=a,t.push(i);break}}}}return t}function jn(e,t){t.append(...Array.from(e.childNodes))}function Tr(e,t,{target$:r,print$:o}){let n=t.closest("[id]"),i=n==null?void 0:n.id,s=new Map;for(let a of Ka(t)){let[,c]=a.textContent.match(/\((\d+)\)/);ue(`:scope > li:nth-child(${c})`,e)&&(s.set(c,An(c,i)),a.replaceWith(s.get(c)))}return s.size===0?x:k(()=>{let a=new T,c=a.pipe(re(),ae(!0)),p=[];for(let[l,f]of s)p.push([F(".md-typeset",f),F(`:scope > li:nth-child(${l})`,e)]);return o.pipe(W(c)).subscribe(l=>{e.hidden=!l,e.classList.toggle("md-annotation-list",l);for(let[f,u]of p)l?jn(f,u):jn(u,f)}),O(...[...s].map(([,l])=>Fn(l,t,{target$:r}))).pipe(A(()=>a.complete()),le())})}function Un(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Un(t)}}function Wn(e,t){return k(()=>{let r=Un(e);return typeof r!="undefined"?Tr(r,e,t):x})}var Nn=Gt(io());var Qa=0,Dn=O(h(window,"keydown").pipe(m(()=>!0)),O(h(window,"keyup"),h(window,"contextmenu")).pipe(m(()=>!1))).pipe(K(!1),X(1));function Vn(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Vn(t)}}function Ya(e){return Le(e).pipe(m(({width:t})=>({scrollable:Ct(e).width>t})),oe("scrollable"))}function zn(e,t){let{matches:r}=matchMedia("(hover)"),o=k(()=>{let n=new T,i=n.pipe(Yr(1));n.subscribe(({scrollable:d})=>{d&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let s=[],a=e.closest("pre"),c=a.closest("[id]"),p=c?c.id:Qa++;a.id=`__code_${p}`;let l=[],f=e.closest(".highlight");if(f instanceof HTMLElement){let d=Vn(f);if(typeof d!="undefined"&&(f.classList.contains("annotate")||Q("content.code.annotate"))){let g=Tr(d,e,t);l.push(Le(f).pipe(W(i),m(({width:L,height:ee})=>L&&ee),Y(),b(L=>L?g:x)))}}let u=M(":scope > span[id]",e);if(u.length&&(e.classList.add("md-code__content"),e.closest(".select")||Q("content.code.select")&&!e.closest(".no-select"))){let d=+u[0].id.split("-").pop(),g=Hn();s.push(g),Q("content.tooltips")&&l.push(Je(g,{viewport$}));let L=h(g,"click").pipe(Ut(R=>!R,!1),S(()=>g.blur()),le());L.subscribe(R=>{g.classList.toggle("md-code__button--active",R)});let ee=fe(u).pipe(J(R=>nt(R).pipe(m(se=>[R,se]))));L.pipe(b(R=>R?ee:x)).subscribe(([R,se])=>{let ce=ue(".hll.select",R);if(ce&&!se)ce.replaceWith(...Array.from(ce.childNodes));else if(!ce&&se){let he=document.createElement("span");he.className="hll select",he.append(...Array.from(R.childNodes).slice(1)),R.append(he)}});let ne=fe(u).pipe(J(R=>h(R,"mousedown").pipe(S(se=>se.preventDefault()),m(()=>R)))),Z=L.pipe(b(R=>R?ne:x),te(Dn),m(([R,se])=>{var he;let ce=u.indexOf(R)+d;if(se===!1)return[ce,ce];{let Se=M(".hll",e).map(je=>u.indexOf(je.parentElement)+d);return(he=window.getSelection())==null||he.removeAllRanges(),[Math.min(ce,...Se),Math.max(ce,...Se)]}})),H=Zr(x).pipe(v(R=>R.startsWith(`__codelineno-${p}-`)));H.subscribe(R=>{let[,,se]=R.split("-"),ce=se.split(":").map(Se=>+Se-d+1);ce.length===1&&ce.push(ce[0]);for(let Se of M(".hll:not(.select)",e))Se.replaceWith(...Array.from(Se.childNodes));let he=u.slice(ce[0]-1,ce[1]);for(let Se of he){let je=document.createElement("span");je.className="hll",je.append(...Array.from(Se.childNodes).slice(1)),Se.append(je)}}),H.pipe(Ee(1),xe(pe)).subscribe(R=>{if(R.includes(":")){let se=document.getElementById(R.split(":")[0]);se&&setTimeout(()=>{let ce=se,he=-64;for(;ce!==document.body;)he+=ce.offsetTop,ce=ce.offsetParent;window.scrollTo({top:he})},1)}});let Fe=fe(M('a[href^="#__codelineno"]',f)).pipe(J(R=>h(R,"click").pipe(S(se=>se.preventDefault()),m(()=>R)))).pipe(W(i),te(Dn),m(([R,se])=>{let he=+F(`[id="${R.hash.slice(1)}"]`).parentElement.id.split("-").pop();if(se===!1)return[he,he];{let Se=M(".hll",e).map(je=>+je.parentElement.id.split("-").pop());return[Math.min(he,...Se),Math.max(he,...Se)]}}));O(Z,Fe).subscribe(R=>{let se=`#__codelineno-${p}-`;R[0]===R[1]?se+=R[0]:se+=`${R[0]}:${R[1]}`,history.replaceState({},"",se),window.dispatchEvent(new HashChangeEvent("hashchange",{newURL:window.location.origin+window.location.pathname+se,oldURL:window.location.href}))})}if(Nn.default.isSupported()&&(e.closest(".copy")||Q("content.code.copy")&&!e.closest(".no-copy"))){let d=Cn(a.id);s.push(d),Q("content.tooltips")&&l.push(Je(d,{viewport$}))}if(s.length){let d=kn();d.append(...s),a.insertBefore(d,e)}return Ya(e).pipe(S(d=>n.next(d)),A(()=>n.complete()),m(d=>j({ref:e},d)),Ne(O(...l).pipe(W(i))))});return Q("content.lazy")?lt(e).pipe(v(n=>n),Ee(1),b(()=>o)):o}function Ba(e,{target$:t,print$:r}){let o=!0;return O(t.pipe(m(n=>n.closest("details:not([open])")),v(n=>e===n),m(()=>({action:"open",reveal:!0}))),r.pipe(v(n=>n||!o),S(()=>o=e.open),m(n=>({action:n?"open":"close"}))))}function qn(e,t){return k(()=>{let r=new T;return r.subscribe(({action:o,reveal:n})=>{e.toggleAttribute("open",o==="open"),n&&e.scrollIntoView()}),Ba(e,t).pipe(S(o=>r.next(o)),A(()=>r.complete()),m(o=>j({ref:e},o)))})}function Ga(e){let t=document.createElement("h3");t.innerHTML=e.innerHTML;let r=[t],o=e.nextElementSibling;for(;o&&!(o instanceof HTMLHeadingElement);)r.push(o),o=o.nextElementSibling;return r}function Ja(e,t){for(let r of M("[href], [src]",e))for(let o of["href","src"]){let n=r.getAttribute(o);if(n&&!/^(?:[a-z]+:)?\/\//i.test(n)){r[o]=new URL(r.getAttribute(o),t).toString();break}}return $(e)}function Kn(e,t){let{sitemap$:r}=t;if(!(e instanceof HTMLAnchorElement))return x;if(!(Q("navigation.instant.preview")||e.hasAttribute("data-preview")))return x;let o=V([Ke(e),nt(e)]).pipe(m(([i,s])=>i||s),Y(),v(i=>i));return bt([r,o]).pipe(b(([i])=>{let s=new URL(e.href);return s.search=s.hash="",i.has(`${s}`)?$(s):x}),b(i=>yr(i).pipe(b(s=>Ja(s,i)))),b(i=>{let s=e.hash?`article [id="${e.hash.slice(1)}"]`:"article h1",a=ue(s,i);return typeof a=="undefined"?x:$(Ga(a))})).pipe(b(i=>{let s=new I(a=>{let c=wr(...i);return a.next(c),document.body.append(c),()=>c.remove()});return Nt(e,j({content$:s},t))}))}var Qn=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel rect,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel rect{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color);stroke-width:.05rem}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs #classDiagram-compositionEnd,defs #classDiagram-compositionStart,defs #classDiagram-dependencyEnd,defs #classDiagram-dependencyStart,defs #classDiagram-extensionEnd,defs #classDiagram-extensionStart{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs #classDiagram-aggregationEnd,defs #classDiagram-aggregationStart{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}.attributeBoxEven,.attributeBoxOdd{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityBox{fill:var(--md-mermaid-label-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityLabel{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.relationshipLabelBox{fill:var(--md-mermaid-label-bg-color);fill-opacity:1;background-color:var(--md-mermaid-label-bg-color);opacity:1}.relationshipLabel{fill:var(--md-mermaid-label-fg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs #ONE_OR_MORE_END *,defs #ONE_OR_MORE_START *,defs #ONLY_ONE_END *,defs #ONLY_ONE_START *,defs #ZERO_OR_MORE_END *,defs #ZERO_OR_MORE_START *,defs #ZERO_OR_ONE_END *,defs #ZERO_OR_ONE_START *{stroke:var(--md-mermaid-edge-color)!important}defs #ZERO_OR_MORE_END circle,defs #ZERO_OR_MORE_START circle{fill:var(--md-mermaid-label-bg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var ao,Za=0;function es(){return typeof mermaid=="undefined"||mermaid instanceof Element?At("https://unpkg.com/mermaid@10/dist/mermaid.min.js"):$(void 0)}function Yn(e){return e.classList.remove("mermaid"),ao||(ao=es().pipe(S(()=>mermaid.initialize({startOnLoad:!1,themeCSS:Qn,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),X(1))),ao.subscribe(()=>bo(this,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${Za++}`,r=y("div",{class:"mermaid"}),o=e.textContent,{svg:n,fn:i}=yield mermaid.render(t,o),s=r.attachShadow({mode:"closed"});s.innerHTML=n,e.replaceWith(r),i==null||i(s)})),ao.pipe(m(()=>({ref:e})))}var Bn=y("table");function Gn(e){return e.replaceWith(Bn),Bn.replaceWith(Pn(e)),$({ref:e})}function ts(e){let t=e.find(r=>r.checked)||e[0];return O(...e.map(r=>h(r,"change").pipe(m(()=>F(`label[for="${r.id}"]`))))).pipe(K(F(`label[for="${t.id}"]`)),m(r=>({active:r})))}function Jn(e,{viewport$:t,target$:r}){let o=F(".tabbed-labels",e),n=M(":scope > input",e),i=oo("prev");e.append(i);let s=oo("next");return e.append(s),k(()=>{let a=new T,c=a.pipe(re(),ae(!0));V([a,Le(e)]).pipe(W(c),$e(1,ge)).subscribe({next([{active:p},l]){let f=Qe(p),{width:u}=de(p);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let d=gr(o);(f.xd.x+l.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),V([Ye(o),Le(o)]).pipe(W(c)).subscribe(([p,l])=>{let f=Ct(o);i.hidden=p.x<16,s.hidden=p.x>f.width-l.width-16}),O(h(i,"click").pipe(m(()=>-1)),h(s,"click").pipe(m(()=>1))).pipe(W(c)).subscribe(p=>{let{width:l}=de(o);o.scrollBy({left:l*p,behavior:"smooth"})}),r.pipe(W(c),v(p=>n.includes(p))).subscribe(p=>p.click()),o.classList.add("tabbed-labels--linked");for(let p of n){let l=F(`label[for="${p.id}"]`);l.replaceChildren(y("a",{href:`#${l.htmlFor}`,tabIndex:-1},...Array.from(l.childNodes))),h(l.firstElementChild,"click").pipe(W(c),v(f=>!(f.metaKey||f.ctrlKey)),S(f=>{f.preventDefault(),f.stopPropagation()})).subscribe(()=>{history.replaceState({},"",`#${l.htmlFor}`),l.click()})}return Q("content.tabs.link")&&a.pipe(Pe(1),te(t)).subscribe(([{active:p},{offset:l}])=>{let f=p.innerText.trim();if(p.hasAttribute("data-md-switching"))p.removeAttribute("data-md-switching");else{let u=e.offsetTop-l.y;for(let g of M("[data-tabs]"))for(let L of M(":scope > input",g)){let ee=F(`label[for="${L.id}"]`);if(ee!==p&&ee.innerText.trim()===f){ee.setAttribute("data-md-switching",""),L.click();break}}window.scrollTo({top:e.offsetTop-u});let d=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...d])])}}),a.pipe(W(c)).subscribe(()=>{for(let p of M("audio, video",e))p.pause()}),lt(e).pipe(b(()=>ts(n)),S(p=>a.next(p)),A(()=>a.complete()),m(p=>j({ref:e},p)))}).pipe(Ze(pe))}function Xn(e,t){let{viewport$:r,target$:o,print$:n}=t;return O(...M(".annotate:not(.highlight)",e).map(i=>Wn(i,{target$:o,print$:n})),...M("pre:not(.mermaid) > code",e).map(i=>zn(i,{target$:o,print$:n})),...M("a:not([title])",e).map(i=>Kn(i,t)),...M("pre.mermaid",e).map(i=>Yn(i)),...M("table:not([class])",e).map(i=>Gn(i)),...M("details",e).map(i=>qn(i,{target$:o,print$:n})),...M("[data-tabs]",e).map(i=>Jn(i,{viewport$:r,target$:o})),...M("[title]",e).filter(()=>Q("content.tooltips")).map(i=>Je(i,{viewport$:r})),...M(".footnote-ref",e).filter(()=>Q("content.footnote.tooltips")).map(i=>Nt(i,{content$:new I(s=>{let a=new URL(i.href).hash.slice(1),c=Array.from(document.getElementById(a).cloneNode(!0).children),p=wr(...c);return s.next(p),document.body.append(p),()=>p.remove()}),viewport$:r})))}function rs(e,{alert$:t}){return t.pipe(b(r=>O($(!0),$(!1).pipe(ot(2e3))).pipe(m(o=>({message:r,active:o})))))}function Zn(e,t){let r=F(".md-typeset",e);return k(()=>{let o=new T;return o.subscribe(({message:n,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=n}),rs(e,t).pipe(S(n=>o.next(n)),A(()=>o.complete()),m(n=>j({ref:e},n)))})}var os=0;function ns(e,t){document.body.append(e);let{width:r}=de(e);e.style.setProperty("--md-tooltip-width",`${r}px`),e.remove();let o=vr(t),n=typeof o!="undefined"?Ye(o):$({x:0,y:0}),i=O(Ke(t),nt(t)).pipe(Y());return V([i,n]).pipe(m(([s,a])=>{let{x:c,y:p}=Qe(t),l=de(t),f=t.closest("table");return f&&t.parentElement&&(c+=f.offsetLeft+t.parentElement.offsetLeft,p+=f.offsetTop+t.parentElement.offsetTop),{active:s,offset:{x:c-a.x+l.width/2-r/2,y:p-a.y+l.height+8}}}))}function ei(e){let t=e.title;if(!t.length)return x;let r=`__tooltip_${os++}`,o=Dt(r,"inline"),n=F(".md-typeset",o);return n.innerHTML=t,k(()=>{let i=new T;return i.subscribe({next({offset:s}){o.style.setProperty("--md-tooltip-x",`${s.x}px`),o.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){o.style.removeProperty("--md-tooltip-x"),o.style.removeProperty("--md-tooltip-y")}}),O(i.pipe(v(({active:s})=>s)),i.pipe(Ae(250),v(({active:s})=>!s))).subscribe({next({active:s}){s?(e.insertAdjacentElement("afterend",o),e.setAttribute("aria-describedby",r),e.removeAttribute("title")):(o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t))},complete(){o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t)}}),i.pipe($e(16,ge)).subscribe(({active:s})=>{o.classList.toggle("md-tooltip--active",s)}),i.pipe(gt(125,ge),v(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:s})=>s)).subscribe({next(s){s?o.style.setProperty("--md-tooltip-0",`${-s}px`):o.style.removeProperty("--md-tooltip-0")},complete(){o.style.removeProperty("--md-tooltip-0")}}),ns(o,e).pipe(S(s=>i.next(s)),A(()=>i.complete()),m(s=>j({ref:e},s)))}).pipe(Ze(pe))}function is({viewport$:e}){if(!Q("header.autohide"))return $(!1);let t=e.pipe(m(({offset:{y:n}})=>n),tt(2,1),m(([n,i])=>[nMath.abs(i-n.y)>100),m(([,[n]])=>n),Y()),o=Be("search");return V([e,o]).pipe(m(([{offset:n},i])=>n.y>400&&!i),Y(),b(n=>n?r:$(!1)),K(!1))}function ti(e,t){return k(()=>V([Le(e),is(t)])).pipe(m(([{height:r},o])=>({height:r,hidden:o})),Y((r,o)=>r.height===o.height&&r.hidden===o.hidden),X(1))}function ri(e,{header$:t,main$:r}){return k(()=>{let o=new T,n=o.pipe(re(),ae(!0));o.pipe(oe("active"),De(t)).subscribe(([{active:s},{hidden:a}])=>{e.classList.toggle("md-header--shadow",s&&!a),e.hidden=a});let i=fe(M("[title]",e)).pipe(v(()=>Q("content.tooltips")),J(s=>ei(s)));return r.subscribe(o),t.pipe(W(n),m(s=>j({ref:e},s)),Ne(i.pipe(W(n))))})}function as(e,{viewport$:t,header$:r}){return Er(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:o}})=>{let{height:n}=de(e);return{active:o>=n}}),oe("active"))}function oi(e,t){return k(()=>{let r=new T;r.subscribe({next({active:n}){e.classList.toggle("md-header__title--active",n)},complete(){e.classList.remove("md-header__title--active")}});let o=ue(".md-content h1");return typeof o=="undefined"?x:as(o,t).pipe(S(n=>r.next(n)),A(()=>r.complete()),m(n=>j({ref:e},n)))})}function ni(e,{viewport$:t,header$:r}){let o=r.pipe(m(({height:i})=>i),Y()),n=o.pipe(b(()=>Le(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),oe("bottom"))));return V([o,n,t]).pipe(m(([i,{top:s,bottom:a},{offset:{y:c},size:{height:p}}])=>(p=Math.max(0,p-Math.max(0,s-c,i)-Math.max(0,p+c-a)),{offset:s-i,height:p,active:s-i<=c})),Y((i,s)=>i.offset===s.offset&&i.height===s.height&&i.active===s.active))}function ss(e){let t=__md_get("__palette")||{index:e.findIndex(o=>matchMedia(o.getAttribute("data-md-color-media")).matches)},r=Math.max(0,Math.min(t.index,e.length-1));return $(...e).pipe(J(o=>h(o,"change").pipe(m(()=>o))),K(e[r]),m(o=>({index:e.indexOf(o),color:{media:o.getAttribute("data-md-color-media"),scheme:o.getAttribute("data-md-color-scheme"),primary:o.getAttribute("data-md-color-primary"),accent:o.getAttribute("data-md-color-accent")}})),X(1))}function ii(e){let t=M("input",e),r=y("meta",{name:"theme-color"});document.head.appendChild(r);let o=y("meta",{name:"color-scheme"});document.head.appendChild(o);let n=Wt("(prefers-color-scheme: light)");return k(()=>{let i=new T;return i.subscribe(s=>{if(document.body.setAttribute("data-md-color-switching",""),s.color.media==="(prefers-color-scheme)"){let a=matchMedia("(prefers-color-scheme: light)"),c=document.querySelector(a.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");s.color.scheme=c.getAttribute("data-md-color-scheme"),s.color.primary=c.getAttribute("data-md-color-primary"),s.color.accent=c.getAttribute("data-md-color-accent")}for(let[a,c]of Object.entries(s.color))document.body.setAttribute(`data-md-color-${a}`,c);for(let a=0;as.key==="Enter"),te(i,(s,a)=>a)).subscribe(({index:s})=>{s=(s+1)%t.length,t[s].click(),t[s].focus()}),i.pipe(m(()=>{let s=Ce("header"),a=window.getComputedStyle(s);return o.content=a.colorScheme,a.backgroundColor.match(/\d+/g).map(c=>(+c).toString(16).padStart(2,"0")).join("")})).subscribe(s=>r.content=`#${s}`),i.pipe(xe(pe)).subscribe(()=>{document.body.removeAttribute("data-md-color-switching")}),ss(t).pipe(W(n.pipe(Pe(1))),vt(),S(s=>i.next(s)),A(()=>i.complete()),m(s=>j({ref:e},s)))})}function ai(e,{progress$:t}){return k(()=>{let r=new T;return r.subscribe(({value:o})=>{e.style.setProperty("--md-progress-value",`${o}`)}),t.pipe(S(o=>r.next({value:o})),A(()=>r.complete()),m(o=>({ref:e,value:o})))})}function si(e,t){return e.protocol=t.protocol,e.hostname=t.hostname,e}function cs(e,t){let r=new Map;for(let o of M("url",e)){let n=F("loc",o),i=[si(new URL(n.textContent),t)];r.set(`${i[0]}`,i);for(let s of M("[rel=alternate]",o)){let a=s.getAttribute("href");a!=null&&i.push(si(new URL(a),t))}}return r}function kt(e){return xn(new URL("sitemap.xml",e)).pipe(m(t=>cs(t,new URL(e))),ye(()=>$(new Map)),le())}function ci({document$:e}){let t=new Map;e.pipe(b(()=>M("link[rel=alternate]")),m(r=>new URL(r.href)),v(r=>!t.has(r.toString())),J(r=>kt(r).pipe(m(o=>[r,o]),ye(()=>x)))).subscribe(([r,o])=>{t.set(r.toString().replace(/\/$/,""),o)}),h(document.body,"click").pipe(v(r=>!r.metaKey&&!r.ctrlKey),b(r=>{if(r.target instanceof Element){let o=r.target.closest("a");if(o&&!o.target){let n=[...t].find(([f])=>o.href.startsWith(`${f}/`));if(typeof n=="undefined")return x;let[i,s]=n,a=we();if(a.href.startsWith(i))return x;let c=Te(),p=a.href.replace(c.base,"");p=`${i}/${p}`;let l=s.has(p.split("#")[0])?new URL(p,c.base):new URL(i);return r.preventDefault(),$(l)}}return x})).subscribe(r=>at(r,!0))}var so=Gt(io());function ps(e){e.setAttribute("data-md-copying","");let t=e.closest("[data-copy]"),r=t?t.getAttribute("data-copy"):e.innerText;return e.removeAttribute("data-md-copying"),r.trimEnd()}function pi({alert$:e}){so.default.isSupported()&&new I(t=>{new so.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||ps(F(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(S(t=>{t.trigger.focus()}),m(()=>Me("clipboard.copied"))).subscribe(e)}function li(e,t){if(!(e.target instanceof Element))return x;let r=e.target.closest("a");if(r===null)return x;if(r.target||e.metaKey||e.ctrlKey)return x;let o=new URL(r.href);return o.search=o.hash="",t.has(`${o}`)?(e.preventDefault(),$(r)):x}function mi(e){let t=new Map;for(let r of M(":scope > *",e.head))t.set(r.outerHTML,r);return t}function fi(e){for(let t of M("[href], [src]",e))for(let r of["href","src"]){let o=t.getAttribute(r);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){t[r]=t[r];break}}return $(e)}function ls(e){for(let o of["[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...Q("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let n=ue(o),i=ue(o,e);typeof n!="undefined"&&typeof i!="undefined"&&n.replaceWith(i)}let t=mi(document);for(let[o,n]of mi(e))t.has(o)?t.delete(o):document.head.appendChild(n);for(let o of t.values()){let n=o.getAttribute("name");n!=="theme-color"&&n!=="color-scheme"&&o.remove()}let r=Ce("container");return qe(M("script",r)).pipe(b(o=>{let n=e.createElement("script");if(o.src){for(let i of o.getAttributeNames())n.setAttribute(i,o.getAttribute(i));return o.replaceWith(n),new I(i=>{n.onload=()=>i.complete()})}else return n.textContent=o.textContent,o.replaceWith(n),x}),re(),ae(document))}function ui({sitemap$:e,location$:t,viewport$:r,progress$:o}){if(location.protocol==="file:")return x;$(document).subscribe(fi);let n=h(document.body,"click").pipe(De(e),b(([a,c])=>li(a,c)),m(({href:a})=>new URL(a)),le()),i=h(window,"popstate").pipe(m(we),le());n.pipe(te(r)).subscribe(([a,{offset:c}])=>{history.replaceState(c,""),history.pushState(null,"",a)}),O(n,i).subscribe(t);let s=t.pipe(oe("pathname"),b(a=>yr(a,{progress$:o}).pipe(ye(()=>(at(a,!0),x)))),b(fi),b(ls),le());return O(s.pipe(te(t,(a,c)=>c)),s.pipe(b(()=>t),oe("pathname"),b(()=>t),oe("hash")),t.pipe(Y((a,c)=>a.pathname===c.pathname&&a.hash===c.hash),b(()=>n),S(()=>history.back()))).subscribe(a=>{var c,p;history.state!==null||!a.hash?window.scrollTo(0,(p=(c=history.state)==null?void 0:c.y)!=null?p:0):(history.scrollRestoration="auto",bn(a.hash),history.scrollRestoration="manual")}),t.subscribe(()=>{history.scrollRestoration="manual"}),h(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}),r.pipe(oe("offset"),Ae(100)).subscribe(({offset:a})=>{history.replaceState(a,"")}),Q("navigation.instant.prefetch")&&O(h(document.body,"mousemove"),h(document.body,"focusin")).pipe(De(e),b(([a,c])=>li(a,c)),Ae(25),Qr(({href:a})=>a),hr(a=>{let c=document.createElement("link");return c.rel="prefetch",c.href=a.toString(),document.head.appendChild(c),h(c,"load").pipe(m(()=>c),Ee(1))})).subscribe(a=>a.remove()),s}var bi=Gt(hi());function vi(e){let t=e.separator.split("|").map(n=>n.replace(/(\(\?[!=<][^)]+\))/g,"").length===0?"\uFFFD":n).join("|"),r=new RegExp(t,"img"),o=(n,i,s)=>`${i}${s}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();let i=new RegExp(`(^|${e.separator}|)(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return s=>(0,bi.default)(s).replace(i,o).replace(/<\/mark>(\s+)]*>/img,"$1")}}function zt(e){return e.type===1}function Sr(e){return e.type===3}function gi(e,t){let r=On(e);return O($(location.protocol!=="file:"),Be("search")).pipe(Re(o=>o),b(()=>t)).subscribe(({config:o,docs:n})=>r.next({type:0,data:{config:o,docs:n,options:{suggest:Q("search.suggest")}}})),r}function xi({document$:e}){let t=Te(),r=Ge(new URL("../versions.json",t.base)).pipe(ye(()=>x)),o=r.pipe(m(n=>{let[,i]=t.base.match(/([^/]+)\/?$/);return n.find(({version:s,aliases:a})=>s===i||a.includes(i))||n[0]}));r.pipe(m(n=>new Map(n.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),b(n=>h(document.body,"click").pipe(v(i=>!i.metaKey&&!i.ctrlKey),te(o),b(([i,s])=>{if(i.target instanceof Element){let a=i.target.closest("a");if(a&&!a.target&&n.has(a.href)){let c=a.href;return!i.target.closest(".md-version")&&n.get(c)===s?x:(i.preventDefault(),$(c))}}return x}),b(i=>kt(new URL(i)).pipe(m(s=>{let c=we().href.replace(t.base,i);return s.has(c.split("#")[0])?new URL(c):new URL(i)})))))).subscribe(n=>at(n,!0)),V([r,o]).subscribe(([n,i])=>{F(".md-header__topic").appendChild(In(n,i))}),e.pipe(b(()=>o)).subscribe(n=>{var s;let i=__md_get("__outdated",sessionStorage);if(i===null){i=!0;let a=((s=t.version)==null?void 0:s.default)||"latest";Array.isArray(a)||(a=[a]);e:for(let c of a)for(let p of n.aliases.concat(n.version))if(new RegExp(c,"i").test(p)){i=!1;break e}__md_set("__outdated",i,sessionStorage)}if(i)for(let a of me("outdated"))a.hidden=!1})}function hs(e,{worker$:t}){let{searchParams:r}=we();r.has("q")&&(it("search",!0),e.value=r.get("q"),e.focus(),Be("search").pipe(Re(i=>!i)).subscribe(()=>{let i=we();i.searchParams.delete("q"),history.replaceState({},"",`${i}`)}));let o=Ke(e),n=O(t.pipe(Re(zt)),h(e,"keyup"),o).pipe(m(()=>e.value),Y());return V([n,o]).pipe(m(([i,s])=>({value:i,focus:s})),X(1))}function yi(e,{worker$:t}){let r=new T,o=r.pipe(re(),ae(!0));V([t.pipe(Re(zt)),r],(i,s)=>s).pipe(oe("value")).subscribe(({value:i})=>t.next({type:2,data:i})),r.pipe(oe("focus")).subscribe(({focus:i})=>{i&&it("search",i)}),h(e.form,"reset").pipe(W(o)).subscribe(()=>e.focus());let n=F("header [for=__search]");return h(n,"click").subscribe(()=>e.focus()),hs(e,{worker$:t}).pipe(S(i=>r.next(i)),A(()=>r.complete()),m(i=>j({ref:e},i)),X(1))}function Ei(e,{worker$:t,query$:r}){let o=new T,n=mn(e.parentElement).pipe(v(Boolean)),i=e.parentElement,s=F(":scope > :first-child",e),a=F(":scope > :last-child",e);Be("search").subscribe(l=>a.setAttribute("role",l?"list":"presentation")),o.pipe(te(r),Gr(t.pipe(Re(zt)))).subscribe(([{items:l},{value:f}])=>{switch(l.length){case 0:s.textContent=f.length?Me("search.result.none"):Me("search.result.placeholder");break;case 1:s.textContent=Me("search.result.one");break;default:let u=br(l.length);s.textContent=Me("search.result.other",u)}});let c=o.pipe(S(()=>a.innerHTML=""),b(({items:l})=>O($(...l.slice(0,10)),$(...l.slice(10)).pipe(tt(4),Xr(n),b(([f])=>f)))),m($n),le());return c.subscribe(l=>a.appendChild(l)),c.pipe(J(l=>{let f=ue("details",l);return typeof f=="undefined"?x:h(f,"toggle").pipe(W(o),m(()=>f))})).subscribe(l=>{l.open===!1&&l.offsetTop<=i.scrollTop&&i.scrollTo({top:l.offsetTop})}),t.pipe(v(Sr),m(({data:l})=>l)).pipe(S(l=>o.next(l)),A(()=>o.complete()),m(l=>j({ref:e},l)))}function bs(e,{query$:t}){return t.pipe(m(({value:r})=>{let o=we();return o.hash="",r=r.replace(/\s+/g,"+").replace(/&/g,"%26").replace(/=/g,"%3D"),o.search=`q=${r}`,{url:o}}))}function wi(e,t){let r=new T,o=r.pipe(re(),ae(!0));return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),h(e,"click").pipe(W(o)).subscribe(n=>n.preventDefault()),bs(e,t).pipe(S(n=>r.next(n)),A(()=>r.complete()),m(n=>j({ref:e},n)))}function Ti(e,{worker$:t,keyboard$:r}){let o=new T,n=Ce("search-query"),i=O(h(n,"keydown"),h(n,"focus")).pipe(xe(pe),m(()=>n.value),Y());return o.pipe(De(i),m(([{suggest:a},c])=>{let p=c.split(/([\s-]+)/);if(a!=null&&a.length&&p[p.length-1]){let l=a[a.length-1];l.startsWith(p[p.length-1])&&(p[p.length-1]=l)}else p.length=0;return p})).subscribe(a=>e.innerHTML=a.join("").replace(/\s/g," ")),r.pipe(v(({mode:a})=>a==="search")).subscribe(a=>{switch(a.type){case"ArrowRight":e.innerText.length&&n.selectionStart===n.value.length&&(n.value=e.innerText);break}}),t.pipe(v(Sr),m(({data:a})=>a)).pipe(S(a=>o.next(a)),A(()=>o.complete()),m(()=>({ref:e})))}function Si(e,{index$:t,keyboard$:r}){let o=Te();try{let n=gi(o.search,t),i=Ce("search-query",e),s=Ce("search-result",e);h(e,"click").pipe(v(({target:c})=>c instanceof Element&&!!c.closest("a"))).subscribe(()=>it("search",!1)),r.pipe(v(({mode:c})=>c==="search")).subscribe(c=>{let p=Ve();switch(c.type){case"Enter":if(p===i){let l=new Map;for(let f of M(":first-child [href]",s)){let u=f.firstElementChild;l.set(f,parseFloat(u.getAttribute("data-md-score")))}if(l.size){let[[f]]=[...l].sort(([,u],[,d])=>d-u);f.click()}c.claim()}break;case"Escape":case"Tab":it("search",!1),i.blur();break;case"ArrowUp":case"ArrowDown":if(typeof p=="undefined")i.focus();else{let l=[i,...M(":not(details) > [href], summary, details[open] [href]",s)],f=Math.max(0,(Math.max(0,l.indexOf(p))+l.length+(c.type==="ArrowUp"?-1:1))%l.length);l[f].focus()}c.claim();break;default:i!==Ve()&&i.focus()}}),r.pipe(v(({mode:c})=>c==="global")).subscribe(c=>{switch(c.type){case"f":case"s":case"/":i.focus(),i.select(),c.claim();break}});let a=yi(i,{worker$:n});return O(a,Ei(s,{worker$:n,query$:a})).pipe(Ne(...me("search-share",e).map(c=>wi(c,{query$:a})),...me("search-suggest",e).map(c=>Ti(c,{worker$:n,keyboard$:r}))))}catch(n){return e.hidden=!0,et}}function Oi(e,{index$:t,location$:r}){return V([t,r.pipe(K(we()),v(o=>!!o.searchParams.get("h")))]).pipe(m(([o,n])=>vi(o.config)(n.searchParams.get("h"))),m(o=>{var s;let n=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let a=i.nextNode();a;a=i.nextNode())if((s=a.parentElement)!=null&&s.offsetHeight){let c=a.textContent,p=o(c);p.length>c.length&&n.set(a,p)}for(let[a,c]of n){let{childNodes:p}=y("span",null,c);a.replaceWith(...Array.from(p))}return{ref:e,nodes:n}}))}function vs(e,{viewport$:t,main$:r}){let o=e.closest(".md-grid"),n=o.offsetTop-o.parentElement.offsetTop;return V([r,t]).pipe(m(([{offset:i,height:s},{offset:{y:a}}])=>(s=s+Math.min(n,Math.max(0,a-i))-n,{height:s,locked:a>=i+n})),Y((i,s)=>i.height===s.height&&i.locked===s.locked))}function co(e,o){var n=o,{header$:t}=n,r=ho(n,["header$"]);let i=F(".md-sidebar__scrollwrap",e),{y:s}=Qe(i);return k(()=>{let a=new T,c=a.pipe(re(),ae(!0)),p=a.pipe($e(0,ge));return p.pipe(te(t)).subscribe({next([{height:l},{height:f}]){i.style.height=`${l-2*s}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),p.pipe(Re()).subscribe(()=>{for(let l of M(".md-nav__link--active[href]",e)){if(!l.clientHeight)continue;let f=l.closest(".md-sidebar__scrollwrap");if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=de(f);f.scrollTo({top:u-d/2})}}}),fe(M("label[tabindex]",e)).pipe(J(l=>h(l,"click").pipe(xe(pe),m(()=>l),W(c)))).subscribe(l=>{let f=F(`[id="${l.htmlFor}"]`);F(`[aria-labelledby="${l.id}"]`).setAttribute("aria-expanded",`${f.checked}`)}),Q("content.tooltips")&&fe(M("abbr[title]",e)).pipe(J(l=>Je(l,{viewport$})),W(c)).subscribe(),vs(e,r).pipe(S(l=>a.next(l)),A(()=>a.complete()),m(l=>j({ref:e},l)))})}function Li(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return bt(Ge(`${r}/releases/latest`).pipe(ye(()=>x),m(o=>({version:o.tag_name})),rt({})),Ge(r).pipe(ye(()=>x),m(o=>({stars:o.stargazers_count,forks:o.forks_count})),rt({}))).pipe(m(([o,n])=>j(j({},o),n)))}else{let r=`https://api.github.com/users/${e}`;return Ge(r).pipe(m(o=>({repositories:o.public_repos})),rt({}))}}function Mi(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return Ge(r).pipe(ye(()=>x),m(({star_count:o,forks_count:n})=>({stars:o,forks:n})),rt({}))}function _i(e){let t=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);if(t){let[,r,o]=t;return Li(r,o)}if(t=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i),t){let[,r,o]=t;return Mi(r,o)}return x}var gs;function xs(e){return gs||(gs=k(()=>{let t=__md_get("__source",sessionStorage);if(t)return $(t);if(me("consent").length){let o=__md_get("__consent");if(!(o&&o.github))return x}return _i(e.href).pipe(S(o=>__md_set("__source",o,sessionStorage)))}).pipe(ye(()=>x),v(t=>Object.keys(t).length>0),m(t=>({facts:t})),X(1)))}function Ai(e){let t=F(":scope > :last-child",e);return k(()=>{let r=new T;return r.subscribe(({facts:o})=>{t.appendChild(Rn(o)),t.classList.add("md-source__repository--active")}),xs(e).pipe(S(o=>r.next(o)),A(()=>r.complete()),m(o=>j({ref:e},o)))})}function ys(e,{viewport$:t,header$:r}){return Le(document.body).pipe(b(()=>Er(e,{header$:r,viewport$:t})),m(({offset:{y:o}})=>({hidden:o>=10})),oe("hidden"))}function Ci(e,t){return k(()=>{let r=new T;return r.subscribe({next({hidden:o}){e.hidden=o},complete(){e.hidden=!1}}),(Q("navigation.tabs.sticky")?$({hidden:!1}):ys(e,t)).pipe(S(o=>r.next(o)),A(()=>r.complete()),m(o=>j({ref:e},o)))})}function Es(e,{viewport$:t,header$:r}){let o=new Map,n=M(".md-nav__link",e);for(let a of n){let c=decodeURIComponent(a.hash.substring(1)),p=ue(`[id="${c}"]`);typeof p!="undefined"&&o.set(a,p)}let i=r.pipe(oe("height"),m(({height:a})=>{let c=Ce("main"),p=F(":scope > :first-child",c);return a+.8*(p.offsetTop-c.offsetTop)}),le());return Le(document.body).pipe(oe("height"),b(a=>k(()=>{let c=[];return $([...o].reduce((p,[l,f])=>{for(;c.length&&o.get(c[c.length-1]).tagName>=f.tagName;)c.pop();let u=f.offsetTop;for(;!u&&f.parentElement;)f=f.parentElement,u=f.offsetTop;let d=f.offsetParent;for(;d;d=d.offsetParent)u+=d.offsetTop;return p.set([...c=[...c,l]].reverse(),u)},new Map))}).pipe(m(c=>new Map([...c].sort(([,p],[,l])=>p-l))),De(i),b(([c,p])=>t.pipe(Ut(([l,f],{offset:{y:u},size:d})=>{let g=u+d.height>=Math.floor(a.height);for(;f.length;){let[,L]=f[0];if(L-p=u&&!g)f=[l.pop(),...f];else break}return[l,f]},[[],[...c]]),Y((l,f)=>l[0]===f[0]&&l[1]===f[1])))))).pipe(m(([a,c])=>({prev:a.map(([p])=>p),next:c.map(([p])=>p)})),K({prev:[],next:[]}),tt(2,1),m(([a,c])=>a.prev.length{let i=new T,s=i.pipe(re(),ae(!0));if(i.subscribe(({prev:a,next:c})=>{for(let[p]of c)p.classList.remove("md-nav__link--passed"),p.classList.remove("md-nav__link--active");for(let[p,[l]]of a.entries())l.classList.add("md-nav__link--passed"),l.classList.toggle("md-nav__link--active",p===a.length-1)}),Q("toc.follow")){let a=O(t.pipe(Ae(1),m(()=>{})),t.pipe(Ae(250),m(()=>"smooth")));i.pipe(v(({prev:c})=>c.length>0),De(o.pipe(xe(pe))),te(a)).subscribe(([[{prev:c}],p])=>{let[l]=c[c.length-1];if(l.offsetHeight){let f=vr(l);if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=de(f);f.scrollTo({top:u-d/2,behavior:p})}}})}return Q("navigation.tracking")&&t.pipe(W(s),oe("offset"),Ae(250),Pe(1),W(n.pipe(Pe(1))),vt({delay:250}),te(i)).subscribe(([,{prev:a}])=>{let c=we(),p=a[a.length-1];if(p&&p.length){let[l]=p,{hash:f}=new URL(l.href);c.hash!==f&&(c.hash=f,history.replaceState({},"",`${c}`))}else c.hash="",history.replaceState({},"",`${c}`)}),Es(e,{viewport$:t,header$:r}).pipe(S(a=>i.next(a)),A(()=>i.complete()),m(a=>j({ref:e},a)))})}function ws(e,{viewport$:t,main$:r,target$:o}){let n=t.pipe(m(({offset:{y:s}})=>s),tt(2,1),m(([s,a])=>s>a&&a>0),Y()),i=r.pipe(m(({active:s})=>s));return V([i,n]).pipe(m(([s,a])=>!(s&&a)),Y(),W(o.pipe(Pe(1))),ae(!0),vt({delay:250}),m(s=>({hidden:s})))}function ki(e,{viewport$:t,header$:r,main$:o,target$:n}){let i=new T,s=i.pipe(re(),ae(!0));return i.subscribe({next({hidden:a}){e.hidden=a,a?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(W(s),oe("height")).subscribe(({height:a})=>{e.style.top=`${a+16}px`}),h(e,"click").subscribe(a=>{a.preventDefault(),window.scrollTo({top:0})}),ws(e,{viewport$:t,main$:o,target$:n}).pipe(S(a=>i.next(a)),A(()=>i.complete()),m(a=>j({ref:e},a)))}function $i({document$:e,viewport$:t}){e.pipe(b(()=>M(".md-ellipsis")),J(r=>lt(r).pipe(W(e.pipe(Pe(1))),v(o=>o),m(()=>r),Ee(1))),v(r=>r.offsetWidth{let o=r.innerText,n=r.closest("a")||r;return n.title=o,Je(n,{viewport$:t}).pipe(W(e.pipe(Pe(1))),A(()=>n.removeAttribute("title")))})).subscribe(),e.pipe(b(()=>M(".md-status")),J(r=>Je(r,{viewport$:t}))).subscribe()}function Ri({document$:e,tablet$:t}){e.pipe(b(()=>M(".md-toggle--indeterminate")),S(r=>{r.indeterminate=!0,r.checked=!1}),J(r=>h(r,"change").pipe(Jr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),te(t)).subscribe(([r,o])=>{r.classList.remove("md-toggle--indeterminate"),o&&(r.checked=!1)})}function Ts(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function Pi({document$:e}){e.pipe(b(()=>M("[data-md-scrollfix]")),S(t=>t.removeAttribute("data-md-scrollfix")),v(Ts),J(t=>h(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function Ii({viewport$:e,tablet$:t}){V([Be("search"),t]).pipe(m(([r,o])=>r&&!o),b(r=>$(r).pipe(ot(r?400:100))),te(e)).subscribe(([r,{offset:{y:o}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${o}px`;else{let n=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",n&&window.scrollTo(0,n)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let o=e[r];typeof o=="string"?o=document.createTextNode(o):o.parentNode&&o.parentNode.removeChild(o),r?t.insertBefore(this.previousSibling,o):t.replaceChild(o,this)}}}));function Ss(){return location.protocol==="file:"?At(`${new URL("search/search_index.js",Or.base)}`).pipe(m(()=>__index),X(1)):Ge(new URL("search/search_index.json",Or.base))}document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var st=on(),Kt=dn(),$t=vn(Kt),po=un(),He=Sn(),Lr=Wt("(min-width: 960px)"),ji=Wt("(min-width: 1220px)"),Ui=gn(),Or=Te(),Wi=document.forms.namedItem("search")?Ss():et,lo=new T;pi({alert$:lo});ci({document$:st});var mo=new T,Di=kt(Or.base);Q("navigation.instant")&&ui({sitemap$:Di,location$:Kt,viewport$:He,progress$:mo}).subscribe(st);var Fi;((Fi=Or.version)==null?void 0:Fi.provider)==="mike"&&xi({document$:st});O(Kt,$t).pipe(ot(125)).subscribe(()=>{it("drawer",!1),it("search",!1)});po.pipe(v(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=ue("link[rel=prev]");typeof t!="undefined"&&at(t);break;case"n":case".":let r=ue("link[rel=next]");typeof r!="undefined"&&at(r);break;case"Enter":let o=Ve();o instanceof HTMLLabelElement&&o.click()}});$i({viewport$:He,document$:st});Ri({document$:st,tablet$:Lr});Pi({document$:st});Ii({viewport$:He,tablet$:Lr});var mt=ti(Ce("header"),{viewport$:He}),qt=st.pipe(m(()=>Ce("main")),b(e=>ni(e,{viewport$:He,header$:mt})),X(1)),Os=O(...me("consent").map(e=>Mn(e,{target$:$t})),...me("dialog").map(e=>Zn(e,{alert$:lo})),...me("header").map(e=>ri(e,{viewport$:He,header$:mt,main$:qt})),...me("palette").map(e=>ii(e)),...me("progress").map(e=>ai(e,{progress$:mo})),...me("search").map(e=>Si(e,{index$:Wi,keyboard$:po})),...me("source").map(e=>Ai(e))),Ls=k(()=>O(...me("announce").map(e=>Ln(e)),...me("content").map(e=>Xn(e,{sitemap$:Di,viewport$:He,target$:$t,print$:Ui})),...me("content").map(e=>Q("search.highlight")?Oi(e,{index$:Wi,location$:Kt}):x),...me("header-title").map(e=>oi(e,{viewport$:He,header$:mt})),...me("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?eo(ji,()=>co(e,{viewport$:He,header$:mt,main$:qt})):eo(Lr,()=>co(e,{viewport$:He,header$:mt,main$:qt}))),...me("tabs").map(e=>Ci(e,{viewport$:He,header$:mt})),...me("toc").map(e=>Hi(e,{viewport$:He,header$:mt,main$:qt,target$:$t})),...me("top").map(e=>ki(e,{viewport$:He,header$:mt,main$:qt,target$:$t})))),Ni=st.pipe(b(()=>Ls),Ne(Os),X(1));Ni.subscribe();window.document$=st;window.location$=Kt;window.target$=$t;window.keyboard$=po;window.viewport$=He;window.tablet$=Lr;window.screen$=ji;window.print$=Ui;window.alert$=lo;window.progress$=mo;window.component$=Ni;})(); diff --git a/1.13/assets/javascripts/glightbox.min.js b/1.13/assets/javascripts/glightbox.min.js new file mode 100644 index 000000000..614fb1888 --- /dev/null +++ b/1.13/assets/javascripts/glightbox.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).GLightbox=t()}(this,(function(){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var i=0;i1&&void 0!==arguments[1]?arguments[1]:null,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,n=e[s]=e[s]||[],l={all:n,evt:null,found:null};return t&&i&&P(n)>0&&o(n,(function(e,n){if(e.eventName==t&&e.fn.toString()==i.toString())return l.found=!0,l.evt=n,!1})),l}function a(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=t.onElement,n=t.withCallback,s=t.avoidDuplicate,l=void 0===s||s,a=t.once,h=void 0!==a&&a,d=t.useCapture,c=void 0!==d&&d,u=arguments.length>2?arguments[2]:void 0,g=i||[];function v(e){T(n)&&n.call(u,e,this),h&&v.destroy()}return C(g)&&(g=document.querySelectorAll(g)),v.destroy=function(){o(g,(function(t){var i=r(t,e,v);i.found&&i.all.splice(i.evt,1),t.removeEventListener&&t.removeEventListener(e,v,c)}))},o(g,(function(t){var i=r(t,e,v);(t.addEventListener&&l&&!i.found||!l)&&(t.addEventListener(e,v,c),i.all.push({eventName:e,fn:v}))})),v}function h(e,t){o(t.split(" "),(function(t){return e.classList.add(t)}))}function d(e,t){o(t.split(" "),(function(t){return e.classList.remove(t)}))}function c(e,t){return e.classList.contains(t)}function u(e,t){for(;e!==document.body;){if(!(e=e.parentElement))return!1;if("function"==typeof e.matches?e.matches(t):e.msMatchesSelector(t))return e}}function g(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!e||""===t)return!1;if("none"==t)return T(i)&&i(),!1;var n=x(),s=t.split(" ");o(s,(function(t){h(e,"g"+t)})),a(n,{onElement:e,avoidDuplicate:!1,once:!0,withCallback:function(e,t){o(s,(function(e){d(t,"g"+e)})),T(i)&&i()}})}function v(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";if(""==t)return e.style.webkitTransform="",e.style.MozTransform="",e.style.msTransform="",e.style.OTransform="",e.style.transform="",!1;e.style.webkitTransform=t,e.style.MozTransform=t,e.style.msTransform=t,e.style.OTransform=t,e.style.transform=t}function f(e){e.style.display="block"}function p(e){e.style.display="none"}function m(e){var t=document.createDocumentFragment(),i=document.createElement("div");for(i.innerHTML=e;i.firstChild;)t.appendChild(i.firstChild);return t}function y(){return{width:window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,height:window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight}}function x(){var e,t=document.createElement("fakeelement"),i={animation:"animationend",OAnimation:"oAnimationEnd",MozAnimation:"animationend",WebkitAnimation:"webkitAnimationEnd"};for(e in i)if(void 0!==t.style[e])return i[e]}function b(e,t,i,n){if(e())t();else{var s;i||(i=100);var l=setInterval((function(){e()&&(clearInterval(l),s&&clearTimeout(s),t())}),i);n&&(s=setTimeout((function(){clearInterval(l)}),n))}}function S(e,t,i){if(I(e))console.error("Inject assets error");else if(T(t)&&(i=t,t=!1),C(t)&&t in window)T(i)&&i();else{var n;if(-1!==e.indexOf(".css")){if((n=document.querySelectorAll('link[href="'+e+'"]'))&&n.length>0)return void(T(i)&&i());var s=document.getElementsByTagName("head")[0],l=s.querySelectorAll('link[rel="stylesheet"]'),o=document.createElement("link");return o.rel="stylesheet",o.type="text/css",o.href=e,o.media="all",l?s.insertBefore(o,l[0]):s.appendChild(o),void(T(i)&&i())}if((n=document.querySelectorAll('script[src="'+e+'"]'))&&n.length>0){if(T(i)){if(C(t))return b((function(){return void 0!==window[t]}),(function(){i()})),!1;i()}}else{var r=document.createElement("script");r.type="text/javascript",r.src=e,r.onload=function(){if(T(i)){if(C(t))return b((function(){return void 0!==window[t]}),(function(){i()})),!1;i()}},document.body.appendChild(r)}}}function w(){return"navigator"in window&&window.navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)|(Android)|(PlayBook)|(BB10)|(BlackBerry)|(Opera Mini)|(IEMobile)|(webOS)|(MeeGo)/i)}function T(e){return"function"==typeof e}function C(e){return"string"==typeof e}function k(e){return!(!e||!e.nodeType||1!=e.nodeType)}function E(e){return Array.isArray(e)}function A(e){return e&&e.length&&isFinite(e.length)}function L(t){return"object"===e(t)&&null!=t&&!T(t)&&!E(t)}function I(e){return null==e}function O(e,t){return null!==e&&hasOwnProperty.call(e,t)}function P(e){if(L(e)){if(e.keys)return e.keys().length;var t=0;for(var i in e)O(e,i)&&t++;return t}return e.length}function M(e){return!isNaN(parseFloat(e))&&isFinite(e)}function z(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:-1,t=document.querySelectorAll(".gbtn[data-taborder]:not(.disabled)");if(!t.length)return!1;if(1==t.length)return t[0];"string"==typeof e&&(e=parseInt(e));var i=[];o(t,(function(e){i.push(e.getAttribute("data-taborder"))}));var n=Math.max.apply(Math,i.map((function(e){return parseInt(e)}))),s=e<0?1:e+1;s>n&&(s="1");var l=i.filter((function(e){return e>=parseInt(s)})),r=l.sort()[0];return document.querySelector('.gbtn[data-taborder="'.concat(r,'"]'))}function X(e){if(e.events.hasOwnProperty("keyboard"))return!1;e.events.keyboard=a("keydown",{onElement:window,withCallback:function(t,i){var n=(t=t||window.event).keyCode;if(9==n){var s=document.querySelector(".gbtn.focused");if(!s){var l=!(!document.activeElement||!document.activeElement.nodeName)&&document.activeElement.nodeName.toLocaleLowerCase();if("input"==l||"textarea"==l||"button"==l)return}t.preventDefault();var o=document.querySelectorAll(".gbtn[data-taborder]");if(!o||o.length<=0)return;if(!s){var r=z();return void(r&&(r.focus(),h(r,"focused")))}var a=z(s.getAttribute("data-taborder"));d(s,"focused"),a&&(a.focus(),h(a,"focused"))}39==n&&e.nextSlide(),37==n&&e.prevSlide(),27==n&&e.close()}})}function Y(e){return Math.sqrt(e.x*e.x+e.y*e.y)}function q(e,t){var i=function(e,t){var i=Y(e)*Y(t);if(0===i)return 0;var n=function(e,t){return e.x*t.x+e.y*t.y}(e,t)/i;return n>1&&(n=1),Math.acos(n)}(e,t);return function(e,t){return e.x*t.y-t.x*e.y}(e,t)>0&&(i*=-1),180*i/Math.PI}var N=function(){function e(i){t(this,e),this.handlers=[],this.el=i}return n(e,[{key:"add",value:function(e){this.handlers.push(e)}},{key:"del",value:function(e){e||(this.handlers=[]);for(var t=this.handlers.length;t>=0;t--)this.handlers[t]===e&&this.handlers.splice(t,1)}},{key:"dispatch",value:function(){for(var e=0,t=this.handlers.length;e=0)console.log("ignore drag for this touched element",e.target.nodeName.toLowerCase());else{this.now=Date.now(),this.x1=e.touches[0].pageX,this.y1=e.touches[0].pageY,this.delta=this.now-(this.last||this.now),this.touchStart.dispatch(e,this.element),null!==this.preTapPosition.x&&(this.isDoubleTap=this.delta>0&&this.delta<=250&&Math.abs(this.preTapPosition.x-this.x1)<30&&Math.abs(this.preTapPosition.y-this.y1)<30,this.isDoubleTap&&clearTimeout(this.singleTapTimeout)),this.preTapPosition.x=this.x1,this.preTapPosition.y=this.y1,this.last=this.now;var t=this.preV;if(e.touches.length>1){this._cancelLongTap(),this._cancelSingleTap();var i={x:e.touches[1].pageX-this.x1,y:e.touches[1].pageY-this.y1};t.x=i.x,t.y=i.y,this.pinchStartLen=Y(t),this.multipointStart.dispatch(e,this.element)}this._preventTap=!1,this.longTapTimeout=setTimeout(function(){this.longTap.dispatch(e,this.element),this._preventTap=!0}.bind(this),750)}}}},{key:"move",value:function(e){if(e.touches){var t=this.preV,i=e.touches.length,n=e.touches[0].pageX,s=e.touches[0].pageY;if(this.isDoubleTap=!1,i>1){var l=e.touches[1].pageX,o=e.touches[1].pageY,r={x:e.touches[1].pageX-n,y:e.touches[1].pageY-s};null!==t.x&&(this.pinchStartLen>0&&(e.zoom=Y(r)/this.pinchStartLen,this.pinch.dispatch(e,this.element)),e.angle=q(r,t),this.rotate.dispatch(e,this.element)),t.x=r.x,t.y=r.y,null!==this.x2&&null!==this.sx2?(e.deltaX=(n-this.x2+l-this.sx2)/2,e.deltaY=(s-this.y2+o-this.sy2)/2):(e.deltaX=0,e.deltaY=0),this.twoFingerPressMove.dispatch(e,this.element),this.sx2=l,this.sy2=o}else{if(null!==this.x2){e.deltaX=n-this.x2,e.deltaY=s-this.y2;var a=Math.abs(this.x1-this.x2),h=Math.abs(this.y1-this.y2);(a>10||h>10)&&(this._preventTap=!0)}else e.deltaX=0,e.deltaY=0;this.pressMove.dispatch(e,this.element)}this.touchMove.dispatch(e,this.element),this._cancelLongTap(),this.x2=n,this.y2=s,i>1&&e.preventDefault()}}},{key:"end",value:function(e){if(e.changedTouches){this._cancelLongTap();var t=this;e.touches.length<2&&(this.multipointEnd.dispatch(e,this.element),this.sx2=this.sy2=null),this.x2&&Math.abs(this.x1-this.x2)>30||this.y2&&Math.abs(this.y1-this.y2)>30?(e.direction=this._swipeDirection(this.x1,this.x2,this.y1,this.y2),this.swipeTimeout=setTimeout((function(){t.swipe.dispatch(e,t.element)}),0)):(this.tapTimeout=setTimeout((function(){t._preventTap||t.tap.dispatch(e,t.element),t.isDoubleTap&&(t.doubleTap.dispatch(e,t.element),t.isDoubleTap=!1)}),0),t.isDoubleTap||(t.singleTapTimeout=setTimeout((function(){t.singleTap.dispatch(e,t.element)}),250))),this.touchEnd.dispatch(e,this.element),this.preV.x=0,this.preV.y=0,this.zoom=1,this.pinchStartLen=null,this.x1=this.x2=this.y1=this.y2=null}}},{key:"cancelAll",value:function(){this._preventTap=!0,clearTimeout(this.singleTapTimeout),clearTimeout(this.tapTimeout),clearTimeout(this.longTapTimeout),clearTimeout(this.swipeTimeout)}},{key:"cancel",value:function(e){this.cancelAll(),this.touchCancel.dispatch(e,this.element)}},{key:"_cancelLongTap",value:function(){clearTimeout(this.longTapTimeout)}},{key:"_cancelSingleTap",value:function(){clearTimeout(this.singleTapTimeout)}},{key:"_swipeDirection",value:function(e,t,i,n){return Math.abs(e-t)>=Math.abs(i-n)?e-t>0?"Left":"Right":i-n>0?"Up":"Down"}},{key:"on",value:function(e,t){this[e]&&this[e].add(t)}},{key:"off",value:function(e,t){this[e]&&this[e].del(t)}},{key:"destroy",value:function(){return this.singleTapTimeout&&clearTimeout(this.singleTapTimeout),this.tapTimeout&&clearTimeout(this.tapTimeout),this.longTapTimeout&&clearTimeout(this.longTapTimeout),this.swipeTimeout&&clearTimeout(this.swipeTimeout),this.element.removeEventListener("touchstart",this.start),this.element.removeEventListener("touchmove",this.move),this.element.removeEventListener("touchend",this.end),this.element.removeEventListener("touchcancel",this.cancel),this.rotate.del(),this.touchStart.del(),this.multipointStart.del(),this.multipointEnd.del(),this.pinch.del(),this.swipe.del(),this.tap.del(),this.doubleTap.del(),this.longTap.del(),this.singleTap.del(),this.pressMove.del(),this.twoFingerPressMove.del(),this.touchMove.del(),this.touchEnd.del(),this.touchCancel.del(),this.preV=this.pinchStartLen=this.zoom=this.isDoubleTap=this.delta=this.last=this.now=this.tapTimeout=this.singleTapTimeout=this.longTapTimeout=this.swipeTimeout=this.x1=this.x2=this.y1=this.y2=this.preTapPosition=this.rotate=this.touchStart=this.multipointStart=this.multipointEnd=this.pinch=this.swipe=this.tap=this.doubleTap=this.longTap=this.singleTap=this.pressMove=this.touchMove=this.touchEnd=this.touchCancel=this.twoFingerPressMove=null,window.removeEventListener("scroll",this._cancelAllHandler),null}}]),e}();function W(e){var t=function(){var e,t=document.createElement("fakeelement"),i={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(e in i)if(void 0!==t.style[e])return i[e]}(),i=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,n=c(e,"gslide-media")?e:e.querySelector(".gslide-media"),s=u(n,".ginner-container"),l=e.querySelector(".gslide-description");i>769&&(n=s),h(n,"greset"),v(n,"translate3d(0, 0, 0)"),a(t,{onElement:n,once:!0,withCallback:function(e,t){d(n,"greset")}}),n.style.opacity="",l&&(l.style.opacity="")}function B(e){if(e.events.hasOwnProperty("touch"))return!1;var t,i,n,s=y(),l=s.width,o=s.height,r=!1,a=null,g=null,f=null,p=!1,m=1,x=1,b=!1,S=!1,w=null,T=null,C=null,k=null,E=0,A=0,L=!1,I=!1,O={},P={},M=0,z=0,X=document.getElementById("glightbox-slider"),Y=document.querySelector(".goverlay"),q=new _(X,{touchStart:function(t){if(r=!0,(c(t.targetTouches[0].target,"ginner-container")||u(t.targetTouches[0].target,".gslide-desc")||"a"==t.targetTouches[0].target.nodeName.toLowerCase())&&(r=!1),u(t.targetTouches[0].target,".gslide-inline")&&!c(t.targetTouches[0].target.parentNode,"gslide-inline")&&(r=!1),r){if(P=t.targetTouches[0],O.pageX=t.targetTouches[0].pageX,O.pageY=t.targetTouches[0].pageY,M=t.targetTouches[0].clientX,z=t.targetTouches[0].clientY,a=e.activeSlide,g=a.querySelector(".gslide-media"),n=a.querySelector(".gslide-inline"),f=null,c(g,"gslide-image")&&(f=g.querySelector("img")),(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)>769&&(g=a.querySelector(".ginner-container")),d(Y,"greset"),t.pageX>20&&t.pageXo){var a=O.pageX-P.pageX;if(Math.abs(a)<=13)return!1}p=!0;var h,d=s.targetTouches[0].clientX,c=s.targetTouches[0].clientY,u=M-d,m=z-c;if(Math.abs(u)>Math.abs(m)?(L=!1,I=!0):(I=!1,L=!0),t=P.pageX-O.pageX,E=100*t/l,i=P.pageY-O.pageY,A=100*i/o,L&&f&&(h=1-Math.abs(i)/o,Y.style.opacity=h,e.settings.touchFollowAxis&&(E=0)),I&&(h=1-Math.abs(t)/l,g.style.opacity=h,e.settings.touchFollowAxis&&(A=0)),!f)return v(g,"translate3d(".concat(E,"%, 0, 0)"));v(g,"translate3d(".concat(E,"%, ").concat(A,"%, 0)"))}},touchEnd:function(){if(r){if(p=!1,S||b)return C=w,void(k=T);var t=Math.abs(parseInt(A)),i=Math.abs(parseInt(E));if(!(t>29&&f))return t<29&&i<25?(h(Y,"greset"),Y.style.opacity=1,W(g)):void 0;e.close()}},multipointEnd:function(){setTimeout((function(){b=!1}),50)},multipointStart:function(){b=!0,m=x||1},pinch:function(e){if(!f||p)return!1;b=!0,f.scaleX=f.scaleY=m*e.zoom;var t=m*e.zoom;if(S=!0,t<=1)return S=!1,t=1,k=null,C=null,w=null,T=null,void f.setAttribute("style","");t>4.5&&(t=4.5),f.style.transform="scale3d(".concat(t,", ").concat(t,", 1)"),x=t},pressMove:function(e){if(S&&!b){var t=P.pageX-O.pageX,i=P.pageY-O.pageY;C&&(t+=C),k&&(i+=k),w=t,T=i;var n="translate3d(".concat(t,"px, ").concat(i,"px, 0)");x&&(n+=" scale3d(".concat(x,", ").concat(x,", 1)")),v(f,n)}},swipe:function(t){if(!S)if(b)b=!1;else{if("Left"==t.direction){if(e.index==e.elements.length-1)return W(g);e.nextSlide()}if("Right"==t.direction){if(0==e.index)return W(g);e.prevSlide()}}}});e.events.touch=q}var H=function(){function e(i,n){var s=this,l=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(t(this,e),this.img=i,this.slide=n,this.onclose=l,this.img.setZoomEvents)return!1;this.active=!1,this.zoomedIn=!1,this.dragging=!1,this.currentX=null,this.currentY=null,this.initialX=null,this.initialY=null,this.xOffset=0,this.yOffset=0,this.img.addEventListener("mousedown",(function(e){return s.dragStart(e)}),!1),this.img.addEventListener("mouseup",(function(e){return s.dragEnd(e)}),!1),this.img.addEventListener("mousemove",(function(e){return s.drag(e)}),!1),this.img.addEventListener("click",(function(e){return s.slide.classList.contains("dragging-nav")?(s.zoomOut(),!1):s.zoomedIn?void(s.zoomedIn&&!s.dragging&&s.zoomOut()):s.zoomIn()}),!1),this.img.setZoomEvents=!0}return n(e,[{key:"zoomIn",value:function(){var e=this.widowWidth();if(!(this.zoomedIn||e<=768)){var t=this.img;if(t.setAttribute("data-style",t.getAttribute("style")),t.style.maxWidth=t.naturalWidth+"px",t.style.maxHeight=t.naturalHeight+"px",t.naturalWidth>e){var i=e/2-t.naturalWidth/2;this.setTranslate(this.img.parentNode,i,0)}this.slide.classList.add("zoomed"),this.zoomedIn=!0}}},{key:"zoomOut",value:function(){this.img.parentNode.setAttribute("style",""),this.img.setAttribute("style",this.img.getAttribute("data-style")),this.slide.classList.remove("zoomed"),this.zoomedIn=!1,this.currentX=null,this.currentY=null,this.initialX=null,this.initialY=null,this.xOffset=0,this.yOffset=0,this.onclose&&"function"==typeof this.onclose&&this.onclose()}},{key:"dragStart",value:function(e){e.preventDefault(),this.zoomedIn?("touchstart"===e.type?(this.initialX=e.touches[0].clientX-this.xOffset,this.initialY=e.touches[0].clientY-this.yOffset):(this.initialX=e.clientX-this.xOffset,this.initialY=e.clientY-this.yOffset),e.target===this.img&&(this.active=!0,this.img.classList.add("dragging"))):this.active=!1}},{key:"dragEnd",value:function(e){var t=this;e.preventDefault(),this.initialX=this.currentX,this.initialY=this.currentY,this.active=!1,setTimeout((function(){t.dragging=!1,t.img.isDragging=!1,t.img.classList.remove("dragging")}),100)}},{key:"drag",value:function(e){this.active&&(e.preventDefault(),"touchmove"===e.type?(this.currentX=e.touches[0].clientX-this.initialX,this.currentY=e.touches[0].clientY-this.initialY):(this.currentX=e.clientX-this.initialX,this.currentY=e.clientY-this.initialY),this.xOffset=this.currentX,this.yOffset=this.currentY,this.img.isDragging=!0,this.dragging=!0,this.setTranslate(this.img,this.currentX,this.currentY))}},{key:"onMove",value:function(e){if(this.zoomedIn){var t=e.clientX-this.img.naturalWidth/2,i=e.clientY-this.img.naturalHeight/2;this.setTranslate(this.img,t,i)}}},{key:"setTranslate",value:function(e,t,i){e.style.transform="translate3d("+t+"px, "+i+"px, 0)"}},{key:"widowWidth",value:function(){return window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth}}]),e}(),V=function(){function e(){var i=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};t(this,e);var s=n.dragEl,l=n.toleranceX,o=void 0===l?40:l,r=n.toleranceY,a=void 0===r?65:r,h=n.slide,d=void 0===h?null:h,c=n.instance,u=void 0===c?null:c;this.el=s,this.active=!1,this.dragging=!1,this.currentX=null,this.currentY=null,this.initialX=null,this.initialY=null,this.xOffset=0,this.yOffset=0,this.direction=null,this.lastDirection=null,this.toleranceX=o,this.toleranceY=a,this.toleranceReached=!1,this.dragContainer=this.el,this.slide=d,this.instance=u,this.el.addEventListener("mousedown",(function(e){return i.dragStart(e)}),!1),this.el.addEventListener("mouseup",(function(e){return i.dragEnd(e)}),!1),this.el.addEventListener("mousemove",(function(e){return i.drag(e)}),!1)}return n(e,[{key:"dragStart",value:function(e){if(this.slide.classList.contains("zoomed"))this.active=!1;else{"touchstart"===e.type?(this.initialX=e.touches[0].clientX-this.xOffset,this.initialY=e.touches[0].clientY-this.yOffset):(this.initialX=e.clientX-this.xOffset,this.initialY=e.clientY-this.yOffset);var t=e.target.nodeName.toLowerCase();e.target.classList.contains("nodrag")||u(e.target,".nodrag")||-1!==["input","select","textarea","button","a"].indexOf(t)?this.active=!1:(e.preventDefault(),(e.target===this.el||"img"!==t&&u(e.target,".gslide-inline"))&&(this.active=!0,this.el.classList.add("dragging"),this.dragContainer=u(e.target,".ginner-container")))}}},{key:"dragEnd",value:function(e){var t=this;e&&e.preventDefault(),this.initialX=0,this.initialY=0,this.currentX=null,this.currentY=null,this.initialX=null,this.initialY=null,this.xOffset=0,this.yOffset=0,this.active=!1,this.doSlideChange&&(this.instance.preventOutsideClick=!0,"right"==this.doSlideChange&&this.instance.prevSlide(),"left"==this.doSlideChange&&this.instance.nextSlide()),this.doSlideClose&&this.instance.close(),this.toleranceReached||this.setTranslate(this.dragContainer,0,0,!0),setTimeout((function(){t.instance.preventOutsideClick=!1,t.toleranceReached=!1,t.lastDirection=null,t.dragging=!1,t.el.isDragging=!1,t.el.classList.remove("dragging"),t.slide.classList.remove("dragging-nav"),t.dragContainer.style.transform="",t.dragContainer.style.transition=""}),100)}},{key:"drag",value:function(e){if(this.active){e.preventDefault(),this.slide.classList.add("dragging-nav"),"touchmove"===e.type?(this.currentX=e.touches[0].clientX-this.initialX,this.currentY=e.touches[0].clientY-this.initialY):(this.currentX=e.clientX-this.initialX,this.currentY=e.clientY-this.initialY),this.xOffset=this.currentX,this.yOffset=this.currentY,this.el.isDragging=!0,this.dragging=!0,this.doSlideChange=!1,this.doSlideClose=!1;var t=Math.abs(this.currentX),i=Math.abs(this.currentY);if(t>0&&t>=Math.abs(this.currentY)&&(!this.lastDirection||"x"==this.lastDirection)){this.yOffset=0,this.lastDirection="x",this.setTranslate(this.dragContainer,this.currentX,0);var n=this.shouldChange();if(!this.instance.settings.dragAutoSnap&&n&&(this.doSlideChange=n),this.instance.settings.dragAutoSnap&&n)return this.instance.preventOutsideClick=!0,this.toleranceReached=!0,this.active=!1,this.instance.preventOutsideClick=!0,this.dragEnd(null),"right"==n&&this.instance.prevSlide(),void("left"==n&&this.instance.nextSlide())}if(this.toleranceY>0&&i>0&&i>=t&&(!this.lastDirection||"y"==this.lastDirection)){this.xOffset=0,this.lastDirection="y",this.setTranslate(this.dragContainer,0,this.currentY);var s=this.shouldClose();return!this.instance.settings.dragAutoSnap&&s&&(this.doSlideClose=!0),void(this.instance.settings.dragAutoSnap&&s&&this.instance.close())}}}},{key:"shouldChange",value:function(){var e=!1;if(Math.abs(this.currentX)>=this.toleranceX){var t=this.currentX>0?"right":"left";("left"==t&&this.slide!==this.slide.parentNode.lastChild||"right"==t&&this.slide!==this.slide.parentNode.firstChild)&&(e=t)}return e}},{key:"shouldClose",value:function(){var e=!1;return Math.abs(this.currentY)>=this.toleranceY&&(e=!0),e}},{key:"setTranslate",value:function(e,t,i){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];e.style.transition=n?"all .2s ease":"",e.style.transform="translate3d(".concat(t,"px, ").concat(i,"px, 0)")}}]),e}();function j(e,t,i,n){var s=e.querySelector(".gslide-media"),l=new Image,o="gSlideTitle_"+i,r="gSlideDesc_"+i;l.addEventListener("load",(function(){T(n)&&n()}),!1),l.src=t.href,""!=t.sizes&&""!=t.srcset&&(l.sizes=t.sizes,l.srcset=t.srcset),l.alt="",I(t.alt)||""===t.alt||(l.alt=t.alt),""!==t.title&&l.setAttribute("aria-labelledby",o),""!==t.description&&l.setAttribute("aria-describedby",r),t.hasOwnProperty("_hasCustomWidth")&&t._hasCustomWidth&&(l.style.width=t.width),t.hasOwnProperty("_hasCustomHeight")&&t._hasCustomHeight&&(l.style.height=t.height),s.insertBefore(l,s.firstChild)}function F(e,t,i,n){var s=this,l=e.querySelector(".ginner-container"),o="gvideo"+i,r=e.querySelector(".gslide-media"),a=this.getAllPlayers();h(l,"gvideo-container"),r.insertBefore(m('
'),r.firstChild);var d=e.querySelector(".gvideo-wrapper");S(this.settings.plyr.css,"Plyr");var c=t.href,u=location.protocol.replace(":",""),g="",v="",f=!1;"file"==u&&(u="http"),r.style.maxWidth=t.width,S(this.settings.plyr.js,"Plyr",(function(){if(c.match(/vimeo\.com\/([0-9]*)/)){var l=/vimeo.*\/(\d+)/i.exec(c);g="vimeo",v=l[1]}if(c.match(/(youtube\.com|youtube-nocookie\.com)\/watch\?v=([a-zA-Z0-9\-_]+)/)||c.match(/youtu\.be\/([a-zA-Z0-9\-_]+)/)||c.match(/(youtube\.com|youtube-nocookie\.com)\/embed\/([a-zA-Z0-9\-_]+)/)){var r=function(e){var t="";t=void 0!==(e=e.replace(/(>|<)/gi,"").split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/))[2]?(t=e[2].split(/[^0-9a-z_\-]/i))[0]:e;return t}(c);g="youtube",v=r}if(null!==c.match(/\.(mp4|ogg|webm|mov)$/)){g="local";var u='")}var w=f||m('
'));h(d,"".concat(g,"-video gvideo")),d.appendChild(w),d.setAttribute("data-id",o),d.setAttribute("data-index",i);var C=O(s.settings.plyr,"config")?s.settings.plyr.config:{},k=new Plyr("#"+o,C);k.on("ready",(function(e){var t=e.detail.plyr;a[o]=t,T(n)&&n()})),b((function(){return e.querySelector("iframe")&&"true"==e.querySelector("iframe").dataset.ready}),(function(){s.resize(e)})),k.on("enterfullscreen",R),k.on("exitfullscreen",R)}))}function R(e){var t=u(e.target,".gslide-media");"enterfullscreen"==e.type&&h(t,"fullscreen"),"exitfullscreen"==e.type&&d(t,"fullscreen")}function G(e,t,i,n){var s,l=this,o=e.querySelector(".gslide-media"),r=!(!O(t,"href")||!t.href)&&t.href.split("#").pop().trim(),d=!(!O(t,"content")||!t.content)&&t.content;if(d&&(C(d)&&(s=m('
'.concat(d,"
"))),k(d))){"none"==d.style.display&&(d.style.display="block");var c=document.createElement("div");c.className="ginlined-content",c.appendChild(d),s=c}if(r){var u=document.getElementById(r);if(!u)return!1;var g=u.cloneNode(!0);g.style.height=t.height,g.style.maxWidth=t.width,h(g,"ginlined-content"),s=g}if(!s)return console.error("Unable to append inline slide content",t),!1;o.style.height=t.height,o.style.width=t.width,o.appendChild(s),this.events["inlineclose"+r]=a("click",{onElement:o.querySelectorAll(".gtrigger-close"),withCallback:function(e){e.preventDefault(),l.close()}}),T(n)&&n()}function Z(e,t,i,n){var s=e.querySelector(".gslide-media"),l=function(e){var t=e.url,i=e.allow,n=e.callback,s=e.appendTo,l=document.createElement("iframe");return l.className="vimeo-video gvideo",l.src=t,l.style.width="100%",l.style.height="100%",i&&l.setAttribute("allow",i),l.onload=function(){h(l,"node-ready"),T(n)&&n()},s&&s.appendChild(l),l}({url:t.href,callback:n});s.parentNode.style.maxWidth=t.width,s.parentNode.style.height=t.height,s.appendChild(l)}var $=function(){function e(){var i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};t(this,e),this.defaults={href:"",sizes:"",srcset:"",title:"",type:"",description:"",alt:"",descPosition:"bottom",effect:"",width:"",height:"",content:!1,zoomable:!0,draggable:!0},L(i)&&(this.defaults=l(this.defaults,i))}return n(e,[{key:"sourceType",value:function(e){var t=e;if(null!==(e=e.toLowerCase()).match(/\.(jpeg|jpg|jpe|gif|png|apn|webp|avif|svg)/))return"image";if(e.match(/(youtube\.com|youtube-nocookie\.com)\/watch\?v=([a-zA-Z0-9\-_]+)/)||e.match(/youtu\.be\/([a-zA-Z0-9\-_]+)/)||e.match(/(youtube\.com|youtube-nocookie\.com)\/embed\/([a-zA-Z0-9\-_]+)/))return"video";if(e.match(/vimeo\.com\/([0-9]*)/))return"video";if(null!==e.match(/\.(mp4|ogg|webm|mov)/))return"video";if(null!==e.match(/\.(mp3|wav|wma|aac|ogg)/))return"audio";if(e.indexOf("#")>-1&&""!==t.split("#").pop().trim())return"inline";return e.indexOf("goajax=true")>-1?"ajax":"external"}},{key:"parseConfig",value:function(e,t){var i=this,n=l({descPosition:t.descPosition},this.defaults);if(L(e)&&!k(e)){O(e,"type")||(O(e,"content")&&e.content?e.type="inline":O(e,"href")&&(e.type=this.sourceType(e.href)));var s=l(n,e);return this.setSize(s,t),s}var r="",a=e.getAttribute("data-glightbox"),h=e.nodeName.toLowerCase();if("a"===h&&(r=e.href),"img"===h&&(r=e.src,n.alt=e.alt),n.href=r,o(n,(function(s,l){O(t,l)&&"width"!==l&&(n[l]=t[l]);var o=e.dataset[l];I(o)||(n[l]=i.sanitizeValue(o))})),n.content&&(n.type="inline"),!n.type&&r&&(n.type=this.sourceType(r)),I(a)){if(!n.title&&"a"==h){var d=e.title;I(d)||""===d||(n.title=d)}if(!n.title&&"img"==h){var c=e.alt;I(c)||""===c||(n.title=c)}}else{var u=[];o(n,(function(e,t){u.push(";\\s?"+t)})),u=u.join("\\s?:|"),""!==a.trim()&&o(n,(function(e,t){var s=a,l=new RegExp("s?"+t+"s?:s?(.*?)("+u+"s?:|$)"),o=s.match(l);if(o&&o.length&&o[1]){var r=o[1].trim().replace(/;\s*$/,"");n[t]=i.sanitizeValue(r)}}))}if(n.description&&"."===n.description.substring(0,1)){var g;try{g=document.querySelector(n.description).innerHTML}catch(e){if(!(e instanceof DOMException))throw e}g&&(n.description=g)}if(!n.description){var v=e.querySelector(".glightbox-desc");v&&(n.description=v.innerHTML)}return this.setSize(n,t,e),this.slideConfig=n,n}},{key:"setSize",value:function(e,t){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,n="video"==e.type?this.checkSize(t.videosWidth):this.checkSize(t.width),s=this.checkSize(t.height);return e.width=O(e,"width")&&""!==e.width?this.checkSize(e.width):n,e.height=O(e,"height")&&""!==e.height?this.checkSize(e.height):s,i&&"image"==e.type&&(e._hasCustomWidth=!!i.dataset.width,e._hasCustomHeight=!!i.dataset.height),e}},{key:"checkSize",value:function(e){return M(e)?"".concat(e,"px"):e}},{key:"sanitizeValue",value:function(e){return"true"!==e&&"false"!==e?e:"true"===e}}]),e}(),U=function(){function e(i,n,s){t(this,e),this.element=i,this.instance=n,this.index=s}return n(e,[{key:"setContent",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(c(t,"loaded"))return!1;var n=this.instance.settings,s=this.slideConfig,l=w();T(n.beforeSlideLoad)&&n.beforeSlideLoad({index:this.index,slide:t,player:!1});var o=s.type,r=s.descPosition,a=t.querySelector(".gslide-media"),d=t.querySelector(".gslide-title"),u=t.querySelector(".gslide-desc"),g=t.querySelector(".gdesc-inner"),v=i,f="gSlideTitle_"+this.index,p="gSlideDesc_"+this.index;if(T(n.afterSlideLoad)&&(v=function(){T(i)&&i(),n.afterSlideLoad({index:e.index,slide:t,player:e.instance.getSlidePlayerInstance(e.index)})}),""==s.title&&""==s.description?g&&g.parentNode.parentNode.removeChild(g.parentNode):(d&&""!==s.title?(d.id=f,d.innerHTML=s.title):d.parentNode.removeChild(d),u&&""!==s.description?(u.id=p,l&&n.moreLength>0?(s.smallDescription=this.slideShortDesc(s.description,n.moreLength,n.moreText),u.innerHTML=s.smallDescription,this.descriptionEvents(u,s)):u.innerHTML=s.description):u.parentNode.removeChild(u),h(a.parentNode,"desc-".concat(r)),h(g.parentNode,"description-".concat(r))),h(a,"gslide-".concat(o)),h(t,"loaded"),"video"!==o){if("external"!==o)return"inline"===o?(G.apply(this.instance,[t,s,this.index,v]),void(s.draggable&&new V({dragEl:t.querySelector(".gslide-inline"),toleranceX:n.dragToleranceX,toleranceY:n.dragToleranceY,slide:t,instance:this.instance}))):void("image"!==o?T(v)&&v():j(t,s,this.index,(function(){var i=t.querySelector("img");s.draggable&&new V({dragEl:i,toleranceX:n.dragToleranceX,toleranceY:n.dragToleranceY,slide:t,instance:e.instance}),s.zoomable&&i.naturalWidth>i.offsetWidth&&(h(i,"zoomable"),new H(i,t,(function(){e.instance.resize()}))),T(v)&&v()})));Z.apply(this,[t,s,this.index,v])}else F.apply(this.instance,[t,s,this.index,v])}},{key:"slideShortDesc",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:50,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=document.createElement("div");n.innerHTML=e;var s=n.innerText,l=i;if((e=s.trim()).length<=t)return e;var o=e.substr(0,t-1);return l?(n=null,o+'... '+i+""):o}},{key:"descriptionEvents",value:function(e,t){var i=this,n=e.querySelector(".desc-more");if(!n)return!1;a("click",{onElement:n,withCallback:function(e,n){e.preventDefault();var s=document.body,l=u(n,".gslide-desc");if(!l)return!1;l.innerHTML=t.description,h(s,"gdesc-open");var o=a("click",{onElement:[s,u(l,".gslide-description")],withCallback:function(e,n){"a"!==e.target.nodeName.toLowerCase()&&(d(s,"gdesc-open"),h(s,"gdesc-closed"),l.innerHTML=t.smallDescription,i.descriptionEvents(l,t),setTimeout((function(){d(s,"gdesc-closed")}),400),o.destroy())}})}})}},{key:"create",value:function(){return m(this.instance.settings.slideHTML)}},{key:"getConfig",value:function(){k(this.element)||this.element.hasOwnProperty("draggable")||(this.element.draggable=this.instance.settings.draggable);var e=new $(this.instance.settings.slideExtraAttributes);return this.slideConfig=e.parseConfig(this.element,this.instance.settings),this.slideConfig}}]),e}(),J=w(),K=null!==w()||void 0!==document.createTouch||"ontouchstart"in window||"onmsgesturechange"in window||navigator.msMaxTouchPoints,Q=document.getElementsByTagName("html")[0],ee={selector:".glightbox",elements:null,skin:"clean",theme:"clean",closeButton:!0,startAt:null,autoplayVideos:!0,autofocusVideos:!0,descPosition:"bottom",width:"900px",height:"506px",videosWidth:"960px",beforeSlideChange:null,afterSlideChange:null,beforeSlideLoad:null,afterSlideLoad:null,slideInserted:null,slideRemoved:null,slideExtraAttributes:null,onOpen:null,onClose:null,loop:!1,zoomable:!0,draggable:!0,dragAutoSnap:!1,dragToleranceX:40,dragToleranceY:65,preload:!0,oneSlidePerOpen:!1,touchNavigation:!0,touchFollowAxis:!0,keyboardNavigation:!0,closeOnOutsideClick:!0,plugins:!1,plyr:{css:"https://cdn.plyr.io/3.6.8/plyr.css",js:"https://cdn.plyr.io/3.6.8/plyr.js",config:{ratio:"16:9",fullscreen:{enabled:!0,iosNative:!0},youtube:{noCookie:!0,rel:0,showinfo:0,iv_load_policy:3},vimeo:{byline:!1,portrait:!1,title:!1,transparent:!1}}},openEffect:"zoom",closeEffect:"zoom",slideEffect:"slide",moreText:"See more",moreLength:60,cssEfects:{fade:{in:"fadeIn",out:"fadeOut"},zoom:{in:"zoomIn",out:"zoomOut"},slide:{in:"slideInRight",out:"slideOutLeft"},slideBack:{in:"slideInLeft",out:"slideOutRight"},none:{in:"none",out:"none"}},svg:{close:'',next:' ',prev:''},slideHTML:'
\n
\n
\n
\n
\n
\n
\n

\n
\n
\n
\n
\n
\n
',lightboxHTML:''},te=function(){function e(){var i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};t(this,e),this.customOptions=i,this.settings=l(ee,i),this.effectsClasses=this.getAnimationClasses(),this.videoPlayers={},this.apiEvents=[],this.fullElementsList=!1}return n(e,[{key:"init",value:function(){var e=this,t=this.getSelector();t&&(this.baseEvents=a("click",{onElement:t,withCallback:function(t,i){t.preventDefault(),e.open(i)}})),this.elements=this.getElements()}},{key:"open",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(0==this.elements.length)return!1;this.activeSlide=null,this.prevActiveSlideIndex=null,this.prevActiveSlide=null;var i=M(t)?t:this.settings.startAt;if(k(e)){var n=e.getAttribute("data-gallery");n&&(this.fullElementsList=this.elements,this.elements=this.getGalleryElements(this.elements,n)),I(i)&&(i=this.getElementIndex(e))<0&&(i=0)}M(i)||(i=0),this.build(),g(this.overlay,"none"==this.settings.openEffect?"none":this.settings.cssEfects.fade.in);var s=document.body,l=window.innerWidth-document.documentElement.clientWidth;if(l>0){var o=document.createElement("style");o.type="text/css",o.className="gcss-styles",o.innerText=".gscrollbar-fixer {margin-right: ".concat(l,"px}"),document.head.appendChild(o),h(s,"gscrollbar-fixer")}h(s,"glightbox-open"),h(Q,"glightbox-open"),J&&(h(document.body,"glightbox-mobile"),this.settings.slideEffect="slide"),this.showSlide(i,!0),1==this.elements.length?(h(this.prevButton,"glightbox-button-hidden"),h(this.nextButton,"glightbox-button-hidden")):(d(this.prevButton,"glightbox-button-hidden"),d(this.nextButton,"glightbox-button-hidden")),this.lightboxOpen=!0,this.trigger("open"),T(this.settings.onOpen)&&this.settings.onOpen(),K&&this.settings.touchNavigation&&B(this),this.settings.keyboardNavigation&&X(this)}},{key:"openAt",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;this.open(null,e)}},{key:"showSlide",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];f(this.loader),this.index=parseInt(t);var n=this.slidesContainer.querySelector(".current");n&&d(n,"current"),this.slideAnimateOut();var s=this.slidesContainer.querySelectorAll(".gslide")[t];if(c(s,"loaded"))this.slideAnimateIn(s,i),p(this.loader);else{f(this.loader);var l=this.elements[t],o={index:this.index,slide:s,slideNode:s,slideConfig:l.slideConfig,slideIndex:this.index,trigger:l.node,player:null};this.trigger("slide_before_load",o),l.instance.setContent(s,(function(){p(e.loader),e.resize(),e.slideAnimateIn(s,i),e.trigger("slide_after_load",o)}))}this.slideDescription=s.querySelector(".gslide-description"),this.slideDescriptionContained=this.slideDescription&&c(this.slideDescription.parentNode,"gslide-media"),this.settings.preload&&(this.preloadSlide(t+1),this.preloadSlide(t-1)),this.updateNavigationClasses(),this.activeSlide=s}},{key:"preloadSlide",value:function(e){var t=this;if(e<0||e>this.elements.length-1)return!1;if(I(this.elements[e]))return!1;var i=this.slidesContainer.querySelectorAll(".gslide")[e];if(c(i,"loaded"))return!1;var n=this.elements[e],s=n.type,l={index:e,slide:i,slideNode:i,slideConfig:n.slideConfig,slideIndex:e,trigger:n.node,player:null};this.trigger("slide_before_load",l),"video"==s||"external"==s?setTimeout((function(){n.instance.setContent(i,(function(){t.trigger("slide_after_load",l)}))}),200):n.instance.setContent(i,(function(){t.trigger("slide_after_load",l)}))}},{key:"prevSlide",value:function(){this.goToSlide(this.index-1)}},{key:"nextSlide",value:function(){this.goToSlide(this.index+1)}},{key:"goToSlide",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(this.prevActiveSlide=this.activeSlide,this.prevActiveSlideIndex=this.index,!this.loop()&&(e<0||e>this.elements.length-1))return!1;e<0?e=this.elements.length-1:e>=this.elements.length&&(e=0),this.showSlide(e)}},{key:"insertSlide",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;t<0&&(t=this.elements.length);var i=new U(e,this,t),n=i.getConfig(),s=l({},n),o=i.create(),r=this.elements.length-1;s.index=t,s.node=!1,s.instance=i,s.slideConfig=n,this.elements.splice(t,0,s);var a=null,h=null;if(this.slidesContainer){if(t>r)this.slidesContainer.appendChild(o);else{var d=this.slidesContainer.querySelectorAll(".gslide")[t];this.slidesContainer.insertBefore(o,d)}(this.settings.preload&&0==this.index&&0==t||this.index-1==t||this.index+1==t)&&this.preloadSlide(t),0==this.index&&0==t&&(this.index=1),this.updateNavigationClasses(),a=this.slidesContainer.querySelectorAll(".gslide")[t],h=this.getSlidePlayerInstance(t),s.slideNode=a}this.trigger("slide_inserted",{index:t,slide:a,slideNode:a,slideConfig:n,slideIndex:t,trigger:null,player:h}),T(this.settings.slideInserted)&&this.settings.slideInserted({index:t,slide:a,player:h})}},{key:"removeSlide",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:-1;if(e<0||e>this.elements.length-1)return!1;var t=this.slidesContainer&&this.slidesContainer.querySelectorAll(".gslide")[e];t&&(this.getActiveSlideIndex()==e&&(e==this.elements.length-1?this.prevSlide():this.nextSlide()),t.parentNode.removeChild(t)),this.elements.splice(e,1),this.trigger("slide_removed",e),T(this.settings.slideRemoved)&&this.settings.slideRemoved(e)}},{key:"slideAnimateIn",value:function(e,t){var i=this,n=e.querySelector(".gslide-media"),s=e.querySelector(".gslide-description"),l={index:this.prevActiveSlideIndex,slide:this.prevActiveSlide,slideNode:this.prevActiveSlide,slideIndex:this.prevActiveSlide,slideConfig:I(this.prevActiveSlideIndex)?null:this.elements[this.prevActiveSlideIndex].slideConfig,trigger:I(this.prevActiveSlideIndex)?null:this.elements[this.prevActiveSlideIndex].node,player:this.getSlidePlayerInstance(this.prevActiveSlideIndex)},o={index:this.index,slide:this.activeSlide,slideNode:this.activeSlide,slideConfig:this.elements[this.index].slideConfig,slideIndex:this.index,trigger:this.elements[this.index].node,player:this.getSlidePlayerInstance(this.index)};if(n.offsetWidth>0&&s&&(p(s),s.style.display=""),d(e,this.effectsClasses),t)g(e,this.settings.cssEfects[this.settings.openEffect].in,(function(){i.settings.autoplayVideos&&i.slidePlayerPlay(e),i.trigger("slide_changed",{prev:l,current:o}),T(i.settings.afterSlideChange)&&i.settings.afterSlideChange.apply(i,[l,o])}));else{var r=this.settings.slideEffect,a="none"!==r?this.settings.cssEfects[r].in:r;this.prevActiveSlideIndex>this.index&&"slide"==this.settings.slideEffect&&(a=this.settings.cssEfects.slideBack.in),g(e,a,(function(){i.settings.autoplayVideos&&i.slidePlayerPlay(e),i.trigger("slide_changed",{prev:l,current:o}),T(i.settings.afterSlideChange)&&i.settings.afterSlideChange.apply(i,[l,o])}))}setTimeout((function(){i.resize(e)}),100),h(e,"current")}},{key:"slideAnimateOut",value:function(){if(!this.prevActiveSlide)return!1;var e=this.prevActiveSlide;d(e,this.effectsClasses),h(e,"prev");var t=this.settings.slideEffect,i="none"!==t?this.settings.cssEfects[t].out:t;this.slidePlayerPause(e),this.trigger("slide_before_change",{prev:{index:this.prevActiveSlideIndex,slide:this.prevActiveSlide,slideNode:this.prevActiveSlide,slideIndex:this.prevActiveSlideIndex,slideConfig:I(this.prevActiveSlideIndex)?null:this.elements[this.prevActiveSlideIndex].slideConfig,trigger:I(this.prevActiveSlideIndex)?null:this.elements[this.prevActiveSlideIndex].node,player:this.getSlidePlayerInstance(this.prevActiveSlideIndex)},current:{index:this.index,slide:this.activeSlide,slideNode:this.activeSlide,slideIndex:this.index,slideConfig:this.elements[this.index].slideConfig,trigger:this.elements[this.index].node,player:this.getSlidePlayerInstance(this.index)}}),T(this.settings.beforeSlideChange)&&this.settings.beforeSlideChange.apply(this,[{index:this.prevActiveSlideIndex,slide:this.prevActiveSlide,player:this.getSlidePlayerInstance(this.prevActiveSlideIndex)},{index:this.index,slide:this.activeSlide,player:this.getSlidePlayerInstance(this.index)}]),this.prevActiveSlideIndex>this.index&&"slide"==this.settings.slideEffect&&(i=this.settings.cssEfects.slideBack.out),g(e,i,(function(){var t=e.querySelector(".ginner-container"),i=e.querySelector(".gslide-media"),n=e.querySelector(".gslide-description");t.style.transform="",i.style.transform="",d(i,"greset"),i.style.opacity="",n&&(n.style.opacity=""),d(e,"prev")}))}},{key:"getAllPlayers",value:function(){return this.videoPlayers}},{key:"getSlidePlayerInstance",value:function(e){var t="gvideo"+e,i=this.getAllPlayers();return!(!O(i,t)||!i[t])&&i[t]}},{key:"stopSlideVideo",value:function(e){if(k(e)){var t=e.querySelector(".gvideo-wrapper");t&&(e=t.getAttribute("data-index"))}console.log("stopSlideVideo is deprecated, use slidePlayerPause");var i=this.getSlidePlayerInstance(e);i&&i.playing&&i.pause()}},{key:"slidePlayerPause",value:function(e){if(k(e)){var t=e.querySelector(".gvideo-wrapper");t&&(e=t.getAttribute("data-index"))}var i=this.getSlidePlayerInstance(e);i&&i.playing&&i.pause()}},{key:"playSlideVideo",value:function(e){if(k(e)){var t=e.querySelector(".gvideo-wrapper");t&&(e=t.getAttribute("data-index"))}console.log("playSlideVideo is deprecated, use slidePlayerPlay");var i=this.getSlidePlayerInstance(e);i&&!i.playing&&i.play()}},{key:"slidePlayerPlay",value:function(e){if(k(e)){var t=e.querySelector(".gvideo-wrapper");t&&(e=t.getAttribute("data-index"))}var i=this.getSlidePlayerInstance(e);i&&!i.playing&&(i.play(),this.settings.autofocusVideos&&i.elements.container.focus())}},{key:"setElements",value:function(e){var t=this;this.settings.elements=!1;var i=[];e&&e.length&&o(e,(function(e,n){var s=new U(e,t,n),o=s.getConfig(),r=l({},o);r.slideConfig=o,r.instance=s,r.index=n,i.push(r)})),this.elements=i,this.lightboxOpen&&(this.slidesContainer.innerHTML="",this.elements.length&&(o(this.elements,(function(){var e=m(t.settings.slideHTML);t.slidesContainer.appendChild(e)})),this.showSlide(0,!0)))}},{key:"getElementIndex",value:function(e){var t=!1;return o(this.elements,(function(i,n){if(O(i,"node")&&i.node==e)return t=n,!0})),t}},{key:"getElements",value:function(){var e=this,t=[];this.elements=this.elements?this.elements:[],!I(this.settings.elements)&&E(this.settings.elements)&&this.settings.elements.length&&o(this.settings.elements,(function(i,n){var s=new U(i,e,n),o=s.getConfig(),r=l({},o);r.node=!1,r.index=n,r.instance=s,r.slideConfig=o,t.push(r)}));var i=!1;return this.getSelector()&&(i=document.querySelectorAll(this.getSelector())),i?(o(i,(function(i,n){var s=new U(i,e,n),o=s.getConfig(),r=l({},o);r.node=i,r.index=n,r.instance=s,r.slideConfig=o,r.gallery=i.getAttribute("data-gallery"),t.push(r)})),t):t}},{key:"getGalleryElements",value:function(e,t){return e.filter((function(e){return e.gallery==t}))}},{key:"getSelector",value:function(){return!this.settings.elements&&(this.settings.selector&&"data-"==this.settings.selector.substring(0,5)?"*[".concat(this.settings.selector,"]"):this.settings.selector)}},{key:"getActiveSlide",value:function(){return this.slidesContainer.querySelectorAll(".gslide")[this.index]}},{key:"getActiveSlideIndex",value:function(){return this.index}},{key:"getAnimationClasses",value:function(){var e=[];for(var t in this.settings.cssEfects)if(this.settings.cssEfects.hasOwnProperty(t)){var i=this.settings.cssEfects[t];e.push("g".concat(i.in)),e.push("g".concat(i.out))}return e.join(" ")}},{key:"build",value:function(){var e=this;if(this.built)return!1;var t=document.body.childNodes,i=[];o(t,(function(e){e.parentNode==document.body&&"#"!==e.nodeName.charAt(0)&&e.hasAttribute&&!e.hasAttribute("aria-hidden")&&(i.push(e),e.setAttribute("aria-hidden","true"))}));var n=O(this.settings.svg,"next")?this.settings.svg.next:"",s=O(this.settings.svg,"prev")?this.settings.svg.prev:"",l=O(this.settings.svg,"close")?this.settings.svg.close:"",r=this.settings.lightboxHTML;r=m(r=(r=(r=r.replace(/{nextSVG}/g,n)).replace(/{prevSVG}/g,s)).replace(/{closeSVG}/g,l)),document.body.appendChild(r);var d=document.getElementById("glightbox-body");this.modal=d;var g=d.querySelector(".gclose");this.prevButton=d.querySelector(".gprev"),this.nextButton=d.querySelector(".gnext"),this.overlay=d.querySelector(".goverlay"),this.loader=d.querySelector(".gloader"),this.slidesContainer=document.getElementById("glightbox-slider"),this.bodyHiddenChildElms=i,this.events={},h(this.modal,"glightbox-"+this.settings.skin),this.settings.closeButton&&g&&(this.events.close=a("click",{onElement:g,withCallback:function(t,i){t.preventDefault(),e.close()}})),g&&!this.settings.closeButton&&g.parentNode.removeChild(g),this.nextButton&&(this.events.next=a("click",{onElement:this.nextButton,withCallback:function(t,i){t.preventDefault(),e.nextSlide()}})),this.prevButton&&(this.events.prev=a("click",{onElement:this.prevButton,withCallback:function(t,i){t.preventDefault(),e.prevSlide()}})),this.settings.closeOnOutsideClick&&(this.events.outClose=a("click",{onElement:d,withCallback:function(t,i){e.preventOutsideClick||c(document.body,"glightbox-mobile")||u(t.target,".ginner-container")||u(t.target,".gbtn")||c(t.target,"gnext")||c(t.target,"gprev")||e.close()}})),o(this.elements,(function(t,i){e.slidesContainer.appendChild(t.instance.create()),t.slideNode=e.slidesContainer.querySelectorAll(".gslide")[i]})),K&&h(document.body,"glightbox-touch"),this.events.resize=a("resize",{onElement:window,withCallback:function(){e.resize()}}),this.built=!0}},{key:"resize",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;if((e=e||this.activeSlide)&&!c(e,"zoomed")){var t=y(),i=e.querySelector(".gvideo-wrapper"),n=e.querySelector(".gslide-image"),s=this.slideDescription,l=t.width,o=t.height;if(l<=768?h(document.body,"glightbox-mobile"):d(document.body,"glightbox-mobile"),i||n){var r=!1;if(s&&(c(s,"description-bottom")||c(s,"description-top"))&&!c(s,"gabsolute")&&(r=!0),n)if(l<=768)n.querySelector("img");else if(r){var a=s.offsetHeight,u=n.querySelector("img");u.setAttribute("style","max-height: calc(100vh - ".concat(a,"px)")),s.setAttribute("style","max-width: ".concat(u.offsetWidth,"px;"))}if(i){var g=O(this.settings.plyr.config,"ratio")?this.settings.plyr.config.ratio:"";if(!g){var v=i.clientWidth,f=i.clientHeight,p=v/f;g="".concat(v/p,":").concat(f/p)}var m=g.split(":"),x=this.settings.videosWidth,b=this.settings.videosWidth,S=(b=M(x)||-1!==x.indexOf("px")?parseInt(x):-1!==x.indexOf("vw")?l*parseInt(x)/100:-1!==x.indexOf("vh")?o*parseInt(x)/100:-1!==x.indexOf("%")?l*parseInt(x)/100:parseInt(i.clientWidth))/(parseInt(m[0])/parseInt(m[1]));if(S=Math.floor(S),r&&(o-=s.offsetHeight),b>l||S>o||ob){var w=i.offsetWidth,T=i.offsetHeight,C=o/T,k={width:w*C,height:T*C};i.parentNode.setAttribute("style","max-width: ".concat(k.width,"px")),r&&s.setAttribute("style","max-width: ".concat(k.width,"px;"))}else i.parentNode.style.maxWidth="".concat(x),r&&s.setAttribute("style","max-width: ".concat(x,";"))}}}}},{key:"reload",value:function(){this.init()}},{key:"updateNavigationClasses",value:function(){var e=this.loop();d(this.nextButton,"disabled"),d(this.prevButton,"disabled"),0==this.index&&this.elements.length-1==0?(h(this.prevButton,"disabled"),h(this.nextButton,"disabled")):0!==this.index||e?this.index!==this.elements.length-1||e||h(this.nextButton,"disabled"):h(this.prevButton,"disabled")}},{key:"loop",value:function(){var e=O(this.settings,"loopAtEnd")?this.settings.loopAtEnd:null;return e=O(this.settings,"loop")?this.settings.loop:e,e}},{key:"close",value:function(){var e=this;if(!this.lightboxOpen){if(this.events){for(var t in this.events)this.events.hasOwnProperty(t)&&this.events[t].destroy();this.events=null}return!1}if(this.closing)return!1;this.closing=!0,this.slidePlayerPause(this.activeSlide),this.fullElementsList&&(this.elements=this.fullElementsList),this.bodyHiddenChildElms.length&&o(this.bodyHiddenChildElms,(function(e){e.removeAttribute("aria-hidden")})),h(this.modal,"glightbox-closing"),g(this.overlay,"none"==this.settings.openEffect?"none":this.settings.cssEfects.fade.out),g(this.activeSlide,this.settings.cssEfects[this.settings.closeEffect].out,(function(){if(e.activeSlide=null,e.prevActiveSlideIndex=null,e.prevActiveSlide=null,e.built=!1,e.events){for(var t in e.events)e.events.hasOwnProperty(t)&&e.events[t].destroy();e.events=null}var i=document.body;d(Q,"glightbox-open"),d(i,"glightbox-open touching gdesc-open glightbox-touch glightbox-mobile gscrollbar-fixer"),e.modal.parentNode.removeChild(e.modal),e.trigger("close"),T(e.settings.onClose)&&e.settings.onClose();var n=document.querySelector(".gcss-styles");n&&n.parentNode.removeChild(n),e.lightboxOpen=!1,e.closing=null}))}},{key:"destroy",value:function(){this.close(),this.clearAllEvents(),this.baseEvents&&this.baseEvents.destroy()}},{key:"on",value:function(e,t){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!e||!T(t))throw new TypeError("Event name and callback must be defined");this.apiEvents.push({evt:e,once:i,callback:t})}},{key:"once",value:function(e,t){this.on(e,t,!0)}},{key:"trigger",value:function(e){var t=this,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=[];o(this.apiEvents,(function(t,s){var l=t.evt,o=t.once,r=t.callback;l==e&&(r(i),o&&n.push(s))})),n.length&&o(n,(function(e){return t.apiEvents.splice(e,1)}))}},{key:"clearAllEvents",value:function(){this.apiEvents.splice(0,this.apiEvents.length)}},{key:"version",value:function(){return"3.1.1"}}]),e}();return function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=new te(e);return t.init(),t}})); diff --git a/1.13/assets/javascripts/lunr/min/lunr.ar.min.js b/1.13/assets/javascripts/lunr/min/lunr.ar.min.js new file mode 100644 index 000000000..9b06c26c1 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.ar.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ar=function(){this.pipeline.reset(),this.pipeline.add(e.ar.trimmer,e.ar.stopWordFilter,e.ar.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ar.stemmer))},e.ar.wordCharacters="ء-ٛٱـ",e.ar.trimmer=e.trimmerSupport.generateTrimmer(e.ar.wordCharacters),e.Pipeline.registerFunction(e.ar.trimmer,"trimmer-ar"),e.ar.stemmer=function(){var e=this;return e.result=!1,e.preRemoved=!1,e.sufRemoved=!1,e.pre={pre1:"ف ك ب و س ل ن ا ي ت",pre2:"ال لل",pre3:"بال وال فال تال كال ولل",pre4:"فبال كبال وبال وكال"},e.suf={suf1:"ه ك ت ن ا ي",suf2:"نك نه ها وك يا اه ون ين تن تم نا وا ان كم كن ني نن ما هم هن تك ته ات يه",suf3:"تين كهم نيه نهم ونه وها يهم ونا ونك وني وهم تكم تنا تها تني تهم كما كها ناه نكم هنا تان يها",suf4:"كموه ناها ونني ونهم تكما تموه تكاه كماه ناكم ناهم نيها وننا"},e.patterns=JSON.parse('{"pt43":[{"pt":[{"c":"ا","l":1}]},{"pt":[{"c":"ا,ت,ن,ي","l":0}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"و","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ي","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ا","l":2},{"c":"ل","l":3,"m":3}]},{"pt":[{"c":"م","l":0}]}],"pt53":[{"pt":[{"c":"ت","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":3},{"c":"ل","l":3,"m":4},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":3}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ن","l":4}]},{"pt":[{"c":"ت","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"م","l":0},{"c":"و","l":3}]},{"pt":[{"c":"ا","l":1},{"c":"و","l":3}]},{"pt":[{"c":"و","l":1},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"ا","l":2},{"c":"ن","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":1},{"c":"ا","l":3}]},{"pt":[{"c":"ي,ت,ا,ن","l":0},{"c":"ت","l":1}],"mPt":[{"c":"ف","l":0,"m":2},{"c":"ع","l":1,"m":3},{"c":"ا","l":2},{"c":"ل","l":3,"m":4}]},{"pt":[{"c":"ت,ي,ا,ن","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":2},{"c":"ي","l":3}]},{"pt":[{"c":"ا,ي,ت,ن","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ء","l":4}]}],"pt63":[{"pt":[{"c":"ا","l":0},{"c":"ت","l":2},{"c":"ا","l":4}]},{"pt":[{"c":"ا,ت,ن,ي","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"و","l":3}]},{"pt":[{"c":"م","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ي","l":1},{"c":"ي","l":3},{"c":"ا","l":4},{"c":"ء","l":5}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ا","l":4}]}],"pt54":[{"pt":[{"c":"ت","l":0}]},{"pt":[{"c":"ا,ي,ت,ن","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"م","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":2}]}],"pt64":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":1}]}],"pt73":[{"pt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ا","l":5}]}],"pt75":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":5}]}]}'),e.execArray=["cleanWord","removeDiacritics","cleanAlef","removeStopWords","normalizeHamzaAndAlef","removeStartWaw","removePre432","removeEndTaa","wordCheck"],e.stem=function(){var r=0;for(e.result=!1,e.preRemoved=!1,e.sufRemoved=!1;r=0)return!0},e.normalizeHamzaAndAlef=function(){return e.word=e.word.replace("ؤ","ء"),e.word=e.word.replace("ئ","ء"),e.word=e.word.replace(/([\u0627])\1+/gi,"ا"),!1},e.removeEndTaa=function(){return!(e.word.length>2)||(e.word=e.word.replace(/[\u0627]$/,""),e.word=e.word.replace("ة",""),!1)},e.removeStartWaw=function(){return e.word.length>3&&"و"==e.word[0]&&"و"==e.word[1]&&(e.word=e.word.slice(1)),!1},e.removePre432=function(){var r=e.word;if(e.word.length>=7){var t=new RegExp("^("+e.pre.pre4.split(" ").join("|")+")");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=6){var c=new RegExp("^("+e.pre.pre3.split(" ").join("|")+")");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=5){var l=new RegExp("^("+e.pre.pre2.split(" ").join("|")+")");e.word=e.word.replace(l,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.patternCheck=function(r){for(var t=0;t3){var t=new RegExp("^("+e.pre.pre1.split(" ").join("|")+")");e.word=e.word.replace(t,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.removeSuf1=function(){var r=e.word;if(0==e.sufRemoved&&e.word.length>3){var t=new RegExp("("+e.suf.suf1.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.removeSuf432=function(){var r=e.word;if(e.word.length>=6){var t=new RegExp("("+e.suf.suf4.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=5){var c=new RegExp("("+e.suf.suf3.split(" ").join("|")+")$");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=4){var l=new RegExp("("+e.suf.suf2.split(" ").join("|")+")$");e.word=e.word.replace(l,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.wordCheck=function(){for(var r=(e.word,[e.removeSuf432,e.removeSuf1,e.removePre1]),t=0,c=!1;e.word.length>=7&&!e.result&&t=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.de.min.js b/1.13/assets/javascripts/lunr/min/lunr.de.min.js new file mode 100644 index 000000000..f3b5c108c --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.de.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `German` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.de=function(){this.pipeline.reset(),this.pipeline.add(e.de.trimmer,e.de.stopWordFilter,e.de.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.de.stemmer))},e.de.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.de.trimmer=e.trimmerSupport.generateTrimmer(e.de.wordCharacters),e.Pipeline.registerFunction(e.de.trimmer,"trimmer-de"),e.de.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!v.eq_s(1,e)||(v.ket=v.cursor,!v.in_grouping(p,97,252)))&&(v.slice_from(r),v.cursor=n,!0)}function i(){for(var r,n,i,s,t=v.cursor;;)if(r=v.cursor,v.bra=r,v.eq_s(1,"ß"))v.ket=v.cursor,v.slice_from("ss");else{if(r>=v.limit)break;v.cursor=r+1}for(v.cursor=t;;)for(n=v.cursor;;){if(i=v.cursor,v.in_grouping(p,97,252)){if(s=v.cursor,v.bra=s,e("u","U",i))break;if(v.cursor=s,e("y","Y",i))break}if(i>=v.limit)return void(v.cursor=n);v.cursor=i+1}}function s(){for(;!v.in_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}for(;!v.out_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}return!1}function t(){m=v.limit,l=m;var e=v.cursor+3;0<=e&&e<=v.limit&&(d=e,s()||(m=v.cursor,m=v.limit)return;v.cursor++}}}function c(){return m<=v.cursor}function u(){return l<=v.cursor}function a(){var e,r,n,i,s=v.limit-v.cursor;if(v.ket=v.cursor,(e=v.find_among_b(w,7))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:v.slice_del(),v.ket=v.cursor,v.eq_s_b(1,"s")&&(v.bra=v.cursor,v.eq_s_b(3,"nis")&&v.slice_del());break;case 3:v.in_grouping_b(g,98,116)&&v.slice_del()}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(f,4))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:if(v.in_grouping_b(k,98,116)){var t=v.cursor-3;v.limit_backward<=t&&t<=v.limit&&(v.cursor=t,v.slice_del())}}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(_,8))&&(v.bra=v.cursor,u()))switch(e){case 1:v.slice_del(),v.ket=v.cursor,v.eq_s_b(2,"ig")&&(v.bra=v.cursor,r=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-r,u()&&v.slice_del()));break;case 2:n=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-n,v.slice_del());break;case 3:if(v.slice_del(),v.ket=v.cursor,i=v.limit-v.cursor,!v.eq_s_b(2,"er")&&(v.cursor=v.limit-i,!v.eq_s_b(2,"en")))break;v.bra=v.cursor,c()&&v.slice_del();break;case 4:v.slice_del(),v.ket=v.cursor,e=v.find_among_b(b,2),e&&(v.bra=v.cursor,u()&&1==e&&v.slice_del())}}var d,l,m,h=[new r("",-1,6),new r("U",0,2),new r("Y",0,1),new r("ä",0,3),new r("ö",0,4),new r("ü",0,5)],w=[new r("e",-1,2),new r("em",-1,1),new r("en",-1,2),new r("ern",-1,1),new r("er",-1,1),new r("s",-1,3),new r("es",5,2)],f=[new r("en",-1,1),new r("er",-1,1),new r("st",-1,2),new r("est",2,1)],b=[new r("ig",-1,1),new r("lich",-1,1)],_=[new r("end",-1,1),new r("ig",-1,2),new r("ung",-1,1),new r("lich",-1,3),new r("isch",-1,2),new r("ik",-1,2),new r("heit",-1,3),new r("keit",-1,4)],p=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8],g=[117,30,5],k=[117,30,4],v=new n;this.setCurrent=function(e){v.setCurrent(e)},this.getCurrent=function(){return v.getCurrent()},this.stem=function(){var e=v.cursor;return i(),v.cursor=e,t(),v.limit_backward=e,v.cursor=v.limit,a(),v.cursor=v.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.de.stemmer,"stemmer-de"),e.de.stopWordFilter=e.generateStopWordFilter("aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über".split(" ")),e.Pipeline.registerFunction(e.de.stopWordFilter,"stopWordFilter-de")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.du.min.js b/1.13/assets/javascripts/lunr/min/lunr.du.min.js new file mode 100644 index 000000000..49a0f3f0a --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.du.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Dutch` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");console.warn('[Lunr Languages] Please use the "nl" instead of the "du". The "nl" code is the standard code for Dutch language, and "du" will be removed in the next major versions.'),e.du=function(){this.pipeline.reset(),this.pipeline.add(e.du.trimmer,e.du.stopWordFilter,e.du.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.du.stemmer))},e.du.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.du.trimmer=e.trimmerSupport.generateTrimmer(e.du.wordCharacters),e.Pipeline.registerFunction(e.du.trimmer,"trimmer-du"),e.du.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e,r,i,o=C.cursor;;){if(C.bra=C.cursor,e=C.find_among(b,11))switch(C.ket=C.cursor,e){case 1:C.slice_from("a");continue;case 2:C.slice_from("e");continue;case 3:C.slice_from("i");continue;case 4:C.slice_from("o");continue;case 5:C.slice_from("u");continue;case 6:if(C.cursor>=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(r=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=r);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=r;else if(n(r))break}else if(n(r))break}function n(e){return C.cursor=e,e>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,f=_,t()||(_=C.cursor,_<3&&(_=3),t()||(f=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var e;;)if(C.bra=C.cursor,e=C.find_among(p,3))switch(C.ket=C.cursor,e){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return f<=C.cursor}function a(){var e=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-e,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var e;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.slice_del(),w=!0,a())))}function m(){var e;u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.eq_s_b(3,"gem")||(C.cursor=C.limit-e,C.slice_del(),a())))}function d(){var e,r,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,e=C.find_among_b(h,5))switch(C.bra=C.cursor,e){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(z,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(r=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-r,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,e=C.find_among_b(k,6))switch(C.bra=C.cursor,e){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(j,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var f,_,w,b=[new r("",-1,6),new r("á",0,1),new r("ä",0,1),new r("é",0,2),new r("ë",0,2),new r("í",0,3),new r("ï",0,3),new r("ó",0,4),new r("ö",0,4),new r("ú",0,5),new r("ü",0,5)],p=[new r("",-1,3),new r("I",0,2),new r("Y",0,1)],g=[new r("dd",-1,-1),new r("kk",-1,-1),new r("tt",-1,-1)],h=[new r("ene",-1,2),new r("se",-1,3),new r("en",-1,2),new r("heden",2,1),new r("s",-1,3)],k=[new r("end",-1,1),new r("ig",-1,2),new r("ing",-1,1),new r("lijk",-1,3),new r("baar",-1,4),new r("bar",-1,5)],v=[new r("aa",-1,-1),new r("ee",-1,-1),new r("oo",-1,-1),new r("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(e){C.setCurrent(e)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var r=C.cursor;return e(),C.cursor=r,o(),C.limit_backward=r,C.cursor=C.limit,d(),C.cursor=C.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.du.stemmer,"stemmer-du"),e.du.stopWordFilter=e.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),e.Pipeline.registerFunction(e.du.stopWordFilter,"stopWordFilter-du")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.el.min.js b/1.13/assets/javascripts/lunr/min/lunr.el.min.js new file mode 100644 index 000000000..ace017bd6 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.el.min.js @@ -0,0 +1 @@ +!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.el=function(){this.pipeline.reset(),void 0===this.searchPipeline&&this.pipeline.add(e.el.trimmer,e.el.normilizer),this.pipeline.add(e.el.stopWordFilter,e.el.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.el.stemmer))},e.el.wordCharacters="A-Za-zΑαΒβΓγΔδΕεΖζΗηΘθΙιΚκΛλΜμΝνΞξΟοΠπΡρΣσςΤτΥυΦφΧχΨψΩωΆάΈέΉήΊίΌόΎύΏώΪΐΫΰΐΰ",e.el.trimmer=e.trimmerSupport.generateTrimmer(e.el.wordCharacters),e.Pipeline.registerFunction(e.el.trimmer,"trimmer-el"),e.el.stemmer=function(){function e(e){return s.test(e)}function t(e){return/[ΑΕΗΙΟΥΩ]$/.test(e)}function r(e){return/[ΑΕΗΙΟΩ]$/.test(e)}function n(n){var s=n;if(n.length<3)return s;if(!e(n))return s;if(i.indexOf(n)>=0)return s;var u=new RegExp("(.*)("+Object.keys(l).join("|")+")$"),o=u.exec(s);return null!==o&&(s=o[1]+l[o[2]]),null!==(o=/^(.+?)(ΑΔΕΣ|ΑΔΩΝ)$/.exec(s))&&(s=o[1],/(ΟΚ|ΜΑΜ|ΜΑΝ|ΜΠΑΜΠ|ΠΑΤΕΡ|ΓΙΑΓΙ|ΝΤΑΝΤ|ΚΥΡ|ΘΕΙ|ΠΕΘΕΡ|ΜΟΥΣΑΜ|ΚΑΠΛΑΜ|ΠΑΡ|ΨΑΡ|ΤΖΟΥΡ|ΤΑΜΠΟΥΡ|ΓΑΛΑΤ|ΦΑΦΛΑΤ)$/.test(o[1])||(s+="ΑΔ")),null!==(o=/^(.+?)(ΕΔΕΣ|ΕΔΩΝ)$/.exec(s))&&(s=o[1],/(ΟΠ|ΙΠ|ΕΜΠ|ΥΠ|ΓΗΠ|ΔΑΠ|ΚΡΑΣΠ|ΜΙΛ)$/.test(o[1])&&(s+="ΕΔ")),null!==(o=/^(.+?)(ΟΥΔΕΣ|ΟΥΔΩΝ)$/.exec(s))&&(s=o[1],/(ΑΡΚ|ΚΑΛΙΑΚ|ΠΕΤΑΛ|ΛΙΧ|ΠΛΕΞ|ΣΚ|Σ|ΦΛ|ΦΡ|ΒΕΛ|ΛΟΥΛ|ΧΝ|ΣΠ|ΤΡΑΓ|ΦΕ)$/.test(o[1])&&(s+="ΟΥΔ")),null!==(o=/^(.+?)(ΕΩΣ|ΕΩΝ|ΕΑΣ|ΕΑ)$/.exec(s))&&(s=o[1],/^(Θ|Δ|ΕΛ|ΓΑΛ|Ν|Π|ΙΔ|ΠΑΡ|ΣΤΕΡ|ΟΡΦ|ΑΝΔΡ|ΑΝΤΡ)$/.test(o[1])&&(s+="Ε")),null!==(o=/^(.+?)(ΕΙΟ|ΕΙΟΣ|ΕΙΟΙ|ΕΙΑ|ΕΙΑΣ|ΕΙΕΣ|ΕΙΟΥ|ΕΙΟΥΣ|ΕΙΩΝ)$/.exec(s))&&o[1].length>4&&(s=o[1]),null!==(o=/^(.+?)(ΙΟΥΣ|ΙΑΣ|ΙΕΣ|ΙΟΣ|ΙΟΥ|ΙΟΙ|ΙΩΝ|ΙΟΝ|ΙΑ|ΙΟ)$/.exec(s))&&(s=o[1],(t(s)||s.length<2||/^(ΑΓ|ΑΓΓΕΛ|ΑΓΡ|ΑΕΡ|ΑΘΛ|ΑΚΟΥΣ|ΑΞ|ΑΣ|Β|ΒΙΒΛ|ΒΥΤ|Γ|ΓΙΑΓ|ΓΩΝ|Δ|ΔΑΝ|ΔΗΛ|ΔΗΜ|ΔΟΚΙΜ|ΕΛ|ΖΑΧΑΡ|ΗΛ|ΗΠ|ΙΔ|ΙΣΚ|ΙΣΤ|ΙΟΝ|ΙΩΝ|ΚΙΜΩΛ|ΚΟΛΟΝ|ΚΟΡ|ΚΤΗΡ|ΚΥΡ|ΛΑΓ|ΛΟΓ|ΜΑΓ|ΜΠΑΝ|ΜΠΡ|ΝΑΥΤ|ΝΟΤ|ΟΠΑΛ|ΟΞ|ΟΡ|ΟΣ|ΠΑΝΑΓ|ΠΑΤΡ|ΠΗΛ|ΠΗΝ|ΠΛΑΙΣ|ΠΟΝΤ|ΡΑΔ|ΡΟΔ|ΣΚ|ΣΚΟΡΠ|ΣΟΥΝ|ΣΠΑΝ|ΣΤΑΔ|ΣΥΡ|ΤΗΛ|ΤΙΜ|ΤΟΚ|ΤΟΠ|ΤΡΟΧ|ΦΙΛ|ΦΩΤ|Χ|ΧΙΛ|ΧΡΩΜ|ΧΩΡ)$/.test(o[1]))&&(s+="Ι"),/^(ΠΑΛ)$/.test(o[1])&&(s+="ΑΙ")),null!==(o=/^(.+?)(ΙΚΟΣ|ΙΚΟΝ|ΙΚΕΙΣ|ΙΚΟΙ|ΙΚΕΣ|ΙΚΟΥΣ|ΙΚΗ|ΙΚΗΣ|ΙΚΟ|ΙΚΑ|ΙΚΟΥ|ΙΚΩΝ|ΙΚΩΣ)$/.exec(s))&&(s=o[1],(t(s)||/^(ΑΔ|ΑΛ|ΑΜΑΝ|ΑΜΕΡ|ΑΜΜΟΧΑΛ|ΑΝΗΘ|ΑΝΤΙΔ|ΑΠΛ|ΑΤΤ|ΑΦΡ|ΒΑΣ|ΒΡΩΜ|ΓΕΝ|ΓΕΡ|Δ|ΔΙΚΑΝ|ΔΥΤ|ΕΙΔ|ΕΝΔ|ΕΞΩΔ|ΗΘ|ΘΕΤ|ΚΑΛΛΙΝ|ΚΑΛΠ|ΚΑΤΑΔ|ΚΟΥΖΙΝ|ΚΡ|ΚΩΔ|ΛΟΓ|Μ|ΜΕΡ|ΜΟΝΑΔ|ΜΟΥΛ|ΜΟΥΣ|ΜΠΑΓΙΑΤ|ΜΠΑΝ|ΜΠΟΛ|ΜΠΟΣ|ΜΥΣΤ|Ν|ΝΙΤ|ΞΙΚ|ΟΠΤ|ΠΑΝ|ΠΕΤΣ|ΠΙΚΑΝΤ|ΠΙΤΣ|ΠΛΑΣΤ|ΠΛΙΑΤΣ|ΠΟΝΤ|ΠΟΣΤΕΛΝ|ΠΡΩΤΟΔ|ΣΕΡΤ|ΣΗΜΑΝΤ|ΣΤΑΤ|ΣΥΝΑΔ|ΣΥΝΟΜΗΛ|ΤΕΛ|ΤΕΧΝ|ΤΡΟΠ|ΤΣΑΜ|ΥΠΟΔ|Φ|ΦΙΛΟΝ|ΦΥΛΟΔ|ΦΥΣ|ΧΑΣ)$/.test(o[1])||/(ΦΟΙΝ)$/.test(o[1]))&&(s+="ΙΚ")),"ΑΓΑΜΕ"===s&&(s="ΑΓΑΜ"),null!==(o=/^(.+?)(ΑΓΑΜΕ|ΗΣΑΜΕ|ΟΥΣΑΜΕ|ΗΚΑΜΕ|ΗΘΗΚΑΜΕ)$/.exec(s))&&(s=o[1]),null!==(o=/^(.+?)(ΑΜΕ)$/.exec(s))&&(s=o[1],/^(ΑΝΑΠ|ΑΠΟΘ|ΑΠΟΚ|ΑΠΟΣΤ|ΒΟΥΒ|ΞΕΘ|ΟΥΛ|ΠΕΘ|ΠΙΚΡ|ΠΟΤ|ΣΙΧ|Χ)$/.test(o[1])&&(s+="ΑΜ")),null!==(o=/^(.+?)(ΑΓΑΝΕ|ΗΣΑΝΕ|ΟΥΣΑΝΕ|ΙΟΝΤΑΝΕ|ΙΟΤΑΝΕ|ΙΟΥΝΤΑΝΕ|ΟΝΤΑΝΕ|ΟΤΑΝΕ|ΟΥΝΤΑΝΕ|ΗΚΑΝΕ|ΗΘΗΚΑΝΕ)$/.exec(s))&&(s=o[1],/^(ΤΡ|ΤΣ)$/.test(o[1])&&(s+="ΑΓΑΝ")),null!==(o=/^(.+?)(ΑΝΕ)$/.exec(s))&&(s=o[1],(r(s)||/^(ΒΕΤΕΡ|ΒΟΥΛΚ|ΒΡΑΧΜ|Γ|ΔΡΑΔΟΥΜ|Θ|ΚΑΛΠΟΥΖ|ΚΑΣΤΕΛ|ΚΟΡΜΟΡ|ΛΑΟΠΛ|ΜΩΑΜΕΘ|Μ|ΜΟΥΣΟΥΛΜΑΝ|ΟΥΛ|Π|ΠΕΛΕΚ|ΠΛ|ΠΟΛΙΣ|ΠΟΡΤΟΛ|ΣΑΡΑΚΑΤΣ|ΣΟΥΛΤ|ΤΣΑΡΛΑΤ|ΟΡΦ|ΤΣΙΓΓ|ΤΣΟΠ|ΦΩΤΟΣΤΕΦ|Χ|ΨΥΧΟΠΛ|ΑΓ|ΟΡΦ|ΓΑΛ|ΓΕΡ|ΔΕΚ|ΔΙΠΛ|ΑΜΕΡΙΚΑΝ|ΟΥΡ|ΠΙΘ|ΠΟΥΡΙΤ|Σ|ΖΩΝΤ|ΙΚ|ΚΑΣΤ|ΚΟΠ|ΛΙΧ|ΛΟΥΘΗΡ|ΜΑΙΝΤ|ΜΕΛ|ΣΙΓ|ΣΠ|ΣΤΕΓ|ΤΡΑΓ|ΤΣΑΓ|Φ|ΕΡ|ΑΔΑΠ|ΑΘΙΓΓ|ΑΜΗΧ|ΑΝΙΚ|ΑΝΟΡΓ|ΑΠΗΓ|ΑΠΙΘ|ΑΤΣΙΓΓ|ΒΑΣ|ΒΑΣΚ|ΒΑΘΥΓΑΛ|ΒΙΟΜΗΧ|ΒΡΑΧΥΚ|ΔΙΑΤ|ΔΙΑΦ|ΕΝΟΡΓ|ΘΥΣ|ΚΑΠΝΟΒΙΟΜΗΧ|ΚΑΤΑΓΑΛ|ΚΛΙΒ|ΚΟΙΛΑΡΦ|ΛΙΒ|ΜΕΓΛΟΒΙΟΜΗΧ|ΜΙΚΡΟΒΙΟΜΗΧ|ΝΤΑΒ|ΞΗΡΟΚΛΙΒ|ΟΛΙΓΟΔΑΜ|ΟΛΟΓΑΛ|ΠΕΝΤΑΡΦ|ΠΕΡΗΦ|ΠΕΡΙΤΡ|ΠΛΑΤ|ΠΟΛΥΔΑΠ|ΠΟΛΥΜΗΧ|ΣΤΕΦ|ΤΑΒ|ΤΕΤ|ΥΠΕΡΗΦ|ΥΠΟΚΟΠ|ΧΑΜΗΛΟΔΑΠ|ΨΗΛΟΤΑΒ)$/.test(o[1]))&&(s+="ΑΝ")),null!==(o=/^(.+?)(ΗΣΕΤΕ)$/.exec(s))&&(s=o[1]),null!==(o=/^(.+?)(ΕΤΕ)$/.exec(s))&&(s=o[1],(r(s)||/(ΟΔ|ΑΙΡ|ΦΟΡ|ΤΑΘ|ΔΙΑΘ|ΣΧ|ΕΝΔ|ΕΥΡ|ΤΙΘ|ΥΠΕΡΘ|ΡΑΘ|ΕΝΘ|ΡΟΘ|ΣΘ|ΠΥΡ|ΑΙΝ|ΣΥΝΔ|ΣΥΝ|ΣΥΝΘ|ΧΩΡ|ΠΟΝ|ΒΡ|ΚΑΘ|ΕΥΘ|ΕΚΘ|ΝΕΤ|ΡΟΝ|ΑΡΚ|ΒΑΡ|ΒΟΛ|ΩΦΕΛ)$/.test(o[1])||/^(ΑΒΑΡ|ΒΕΝ|ΕΝΑΡ|ΑΒΡ|ΑΔ|ΑΘ|ΑΝ|ΑΠΛ|ΒΑΡΟΝ|ΝΤΡ|ΣΚ|ΚΟΠ|ΜΠΟΡ|ΝΙΦ|ΠΑΓ|ΠΑΡΑΚΑΛ|ΣΕΡΠ|ΣΚΕΛ|ΣΥΡΦ|ΤΟΚ|Υ|Δ|ΕΜ|ΘΑΡΡ|Θ)$/.test(o[1]))&&(s+="ΕΤ")),null!==(o=/^(.+?)(ΟΝΤΑΣ|ΩΝΤΑΣ)$/.exec(s))&&(s=o[1],/^ΑΡΧ$/.test(o[1])&&(s+="ΟΝΤ"),/ΚΡΕ$/.test(o[1])&&(s+="ΩΝΤ")),null!==(o=/^(.+?)(ΟΜΑΣΤΕ|ΙΟΜΑΣΤΕ)$/.exec(s))&&(s=o[1],/^ΟΝ$/.test(o[1])&&(s+="ΟΜΑΣΤ")),null!==(o=/^(.+?)(ΙΕΣΤΕ)$/.exec(s))&&(s=o[1],/^(Π|ΑΠ|ΣΥΜΠ|ΑΣΥΜΠ|ΑΚΑΤΑΠ|ΑΜΕΤΑΜΦ)$/.test(o[1])&&(s+="ΙΕΣΤ")),null!==(o=/^(.+?)(ΕΣΤΕ)$/.exec(s))&&(s=o[1],/^(ΑΛ|ΑΡ|ΕΚΤΕΛ|Ζ|Μ|Ξ|ΠΑΡΑΚΑΛ|ΠΡΟ|ΝΙΣ)$/.test(o[1])&&(s+="ΕΣΤ")),null!==(o=/^(.+?)(ΗΘΗΚΑ|ΗΘΗΚΕΣ|ΗΘΗΚΕ)$/.exec(s))&&(s=o[1]),null!==(o=/^(.+?)(ΗΚΑ|ΗΚΕΣ|ΗΚΕ)$/.exec(s))&&(s=o[1],(/(ΣΚΩΛ|ΣΚΟΥΛ|ΝΑΡΘ|ΣΦ|ΟΘ|ΠΙΘ)$/.test(o[1])||/^(ΔΙΑΘ|Θ|ΠΑΡΑΚΑΤΑΘ|ΠΡΟΣΘ|ΣΥΝΘ)$/.test(o[1]))&&(s+="ΗΚ")),null!==(o=/^(.+?)(ΟΥΣΑ|ΟΥΣΕΣ|ΟΥΣΕ)$/.exec(s))&&(s=o[1],(t(s)||/^(ΦΑΡΜΑΚ|ΧΑΔ|ΑΓΚ|ΑΝΑΡΡ|ΒΡΟΜ|ΕΚΛΙΠ|ΛΑΜΠΙΔ|ΛΕΧ|Μ|ΠΑΤ|Ρ|Λ|ΜΕΔ|ΜΕΣΑΖ|ΥΠΟΤΕΙΝ|ΑΜ|ΑΙΘ|ΑΝΗΚ|ΔΕΣΠΟΖ|ΕΝΔΙΑΦΕΡ)$/.test(o[1])||/(ΠΟΔΑΡ|ΒΛΕΠ|ΠΑΝΤΑΧ|ΦΡΥΔ|ΜΑΝΤΙΛ|ΜΑΛΛ|ΚΥΜΑΤ|ΛΑΧ|ΛΗΓ|ΦΑΓ|ΟΜ|ΠΡΩΤ)$/.test(o[1]))&&(s+="ΟΥΣ")),null!==(o=/^(.+?)(ΑΓΑ|ΑΓΕΣ|ΑΓΕ)$/.exec(s))&&(s=o[1],(/^(ΑΒΑΣΤ|ΠΟΛΥΦ|ΑΔΗΦ|ΠΑΜΦ|Ρ|ΑΣΠ|ΑΦ|ΑΜΑΛ|ΑΜΑΛΛΙ|ΑΝΥΣΤ|ΑΠΕΡ|ΑΣΠΑΡ|ΑΧΑΡ|ΔΕΡΒΕΝ|ΔΡΟΣΟΠ|ΞΕΦ|ΝΕΟΠ|ΝΟΜΟΤ|ΟΛΟΠ|ΟΜΟΤ|ΠΡΟΣΤ|ΠΡΟΣΩΠΟΠ|ΣΥΜΠ|ΣΥΝΤ|Τ|ΥΠΟΤ|ΧΑΡ|ΑΕΙΠ|ΑΙΜΟΣΤ|ΑΝΥΠ|ΑΠΟΤ|ΑΡΤΙΠ|ΔΙΑΤ|ΕΝ|ΕΠΙΤ|ΚΡΟΚΑΛΟΠ|ΣΙΔΗΡΟΠ|Λ|ΝΑΥ|ΟΥΛΑΜ|ΟΥΡ|Π|ΤΡ|Μ)$/.test(o[1])||/(ΟΦ|ΠΕΛ|ΧΟΡΤ|ΛΛ|ΣΦ|ΡΠ|ΦΡ|ΠΡ|ΛΟΧ|ΣΜΗΝ)$/.test(o[1])&&!/^(ΨΟΦ|ΝΑΥΛΟΧ)$/.test(o[1])||/(ΚΟΛΛ)$/.test(o[1]))&&(s+="ΑΓ")),null!==(o=/^(.+?)(ΗΣΕ|ΗΣΟΥ|ΗΣΑ)$/.exec(s))&&(s=o[1],/^(Ν|ΧΕΡΣΟΝ|ΔΩΔΕΚΑΝ|ΕΡΗΜΟΝ|ΜΕΓΑΛΟΝ|ΕΠΤΑΝ|Ι)$/.test(o[1])&&(s+="ΗΣ")),null!==(o=/^(.+?)(ΗΣΤΕ)$/.exec(s))&&(s=o[1],/^(ΑΣΒ|ΣΒ|ΑΧΡ|ΧΡ|ΑΠΛ|ΑΕΙΜΝ|ΔΥΣΧΡ|ΕΥΧΡ|ΚΟΙΝΟΧΡ|ΠΑΛΙΜΨ)$/.test(o[1])&&(s+="ΗΣΤ")),null!==(o=/^(.+?)(ΟΥΝΕ|ΗΣΟΥΝΕ|ΗΘΟΥΝΕ)$/.exec(s))&&(s=o[1],/^(Ν|Ρ|ΣΠΙ|ΣΤΡΑΒΟΜΟΥΤΣ|ΚΑΚΟΜΟΥΤΣ|ΕΞΩΝ)$/.test(o[1])&&(s+="ΟΥΝ")),null!==(o=/^(.+?)(ΟΥΜΕ|ΗΣΟΥΜΕ|ΗΘΟΥΜΕ)$/.exec(s))&&(s=o[1],/^(ΠΑΡΑΣΟΥΣ|Φ|Χ|ΩΡΙΟΠΛ|ΑΖ|ΑΛΛΟΣΟΥΣ|ΑΣΟΥΣ)$/.test(o[1])&&(s+="ΟΥΜ")),null!=(o=/^(.+?)(ΜΑΤΟΙ|ΜΑΤΟΥΣ|ΜΑΤΟ|ΜΑΤΑ|ΜΑΤΩΣ|ΜΑΤΩΝ|ΜΑΤΟΣ|ΜΑΤΕΣ|ΜΑΤΗ|ΜΑΤΗΣ|ΜΑΤΟΥ)$/.exec(s))&&(s=o[1]+"Μ",/^(ΓΡΑΜ)$/.test(o[1])?s+="Α":/^(ΓΕ|ΣΤΑ)$/.test(o[1])&&(s+="ΑΤ")),null!==(o=/^(.+?)(ΟΥΑ)$/.exec(s))&&(s=o[1]+"ΟΥ"),n.length===s.length&&null!==(o=/^(.+?)(Α|ΑΓΑΤΕ|ΑΓΑΝ|ΑΕΙ|ΑΜΑΙ|ΑΝ|ΑΣ|ΑΣΑΙ|ΑΤΑΙ|ΑΩ|Ε|ΕΙ|ΕΙΣ|ΕΙΤΕ|ΕΣΑΙ|ΕΣ|ΕΤΑΙ|Ι|ΙΕΜΑΙ|ΙΕΜΑΣΤΕ|ΙΕΤΑΙ|ΙΕΣΑΙ|ΙΕΣΑΣΤΕ|ΙΟΜΑΣΤΑΝ|ΙΟΜΟΥΝ|ΙΟΜΟΥΝΑ|ΙΟΝΤΑΝ|ΙΟΝΤΟΥΣΑΝ|ΙΟΣΑΣΤΑΝ|ΙΟΣΑΣΤΕ|ΙΟΣΟΥΝ|ΙΟΣΟΥΝΑ|ΙΟΤΑΝ|ΙΟΥΜΑ|ΙΟΥΜΑΣΤΕ|ΙΟΥΝΤΑΙ|ΙΟΥΝΤΑΝ|Η|ΗΔΕΣ|ΗΔΩΝ|ΗΘΕΙ|ΗΘΕΙΣ|ΗΘΕΙΤΕ|ΗΘΗΚΑΤΕ|ΗΘΗΚΑΝ|ΗΘΟΥΝ|ΗΘΩ|ΗΚΑΤΕ|ΗΚΑΝ|ΗΣ|ΗΣΑΝ|ΗΣΑΤΕ|ΗΣΕΙ|ΗΣΕΣ|ΗΣΟΥΝ|ΗΣΩ|Ο|ΟΙ|ΟΜΑΙ|ΟΜΑΣΤΑΝ|ΟΜΟΥΝ|ΟΜΟΥΝΑ|ΟΝΤΑΙ|ΟΝΤΑΝ|ΟΝΤΟΥΣΑΝ|ΟΣ|ΟΣΑΣΤΑΝ|ΟΣΑΣΤΕ|ΟΣΟΥΝ|ΟΣΟΥΝΑ|ΟΤΑΝ|ΟΥ|ΟΥΜΑΙ|ΟΥΜΑΣΤΕ|ΟΥΝ|ΟΥΝΤΑΙ|ΟΥΝΤΑΝ|ΟΥΣ|ΟΥΣΑΝ|ΟΥΣΑΤΕ|Υ||ΥΑ|ΥΣ|Ω|ΩΝ|ΟΙΣ)$/.exec(s))&&(s=o[1]),null!=(o=/^(.+?)(ΕΣΤΕΡ|ΕΣΤΑΤ|ΟΤΕΡ|ΟΤΑΤ|ΥΤΕΡ|ΥΤΑΤ|ΩΤΕΡ|ΩΤΑΤ)$/.exec(s))&&(/^(ΕΞ|ΕΣ|ΑΝ|ΚΑΤ|Κ|ΠΡ)$/.test(o[1])||(s=o[1]),/^(ΚΑ|Μ|ΕΛΕ|ΛΕ|ΔΕ)$/.test(o[1])&&(s+="ΥΤ")),s}var l={"ΦΑΓΙΑ":"ΦΑ","ΦΑΓΙΟΥ":"ΦΑ","ΦΑΓΙΩΝ":"ΦΑ","ΣΚΑΓΙΑ":"ΣΚΑ","ΣΚΑΓΙΟΥ":"ΣΚΑ","ΣΚΑΓΙΩΝ":"ΣΚΑ","ΣΟΓΙΟΥ":"ΣΟ","ΣΟΓΙΑ":"ΣΟ","ΣΟΓΙΩΝ":"ΣΟ","ΤΑΤΟΓΙΑ":"ΤΑΤΟ","ΤΑΤΟΓΙΟΥ":"ΤΑΤΟ","ΤΑΤΟΓΙΩΝ":"ΤΑΤΟ","ΚΡΕΑΣ":"ΚΡΕ","ΚΡΕΑΤΟΣ":"ΚΡΕ","ΚΡΕΑΤΑ":"ΚΡΕ","ΚΡΕΑΤΩΝ":"ΚΡΕ","ΠΕΡΑΣ":"ΠΕΡ","ΠΕΡΑΤΟΣ":"ΠΕΡ","ΠΕΡΑΤΑ":"ΠΕΡ","ΠΕΡΑΤΩΝ":"ΠΕΡ","ΤΕΡΑΣ":"ΤΕΡ","ΤΕΡΑΤΟΣ":"ΤΕΡ","ΤΕΡΑΤΑ":"ΤΕΡ","ΤΕΡΑΤΩΝ":"ΤΕΡ","ΦΩΣ":"ΦΩ","ΦΩΤΟΣ":"ΦΩ","ΦΩΤΑ":"ΦΩ","ΦΩΤΩΝ":"ΦΩ","ΚΑΘΕΣΤΩΣ":"ΚΑΘΕΣΤ","ΚΑΘΕΣΤΩΤΟΣ":"ΚΑΘΕΣΤ","ΚΑΘΕΣΤΩΤΑ":"ΚΑΘΕΣΤ","ΚΑΘΕΣΤΩΤΩΝ":"ΚΑΘΕΣΤ","ΓΕΓΟΝΟΣ":"ΓΕΓΟΝ","ΓΕΓΟΝΟΤΟΣ":"ΓΕΓΟΝ","ΓΕΓΟΝΟΤΑ":"ΓΕΓΟΝ","ΓΕΓΟΝΟΤΩΝ":"ΓΕΓΟΝ","ΕΥΑ":"ΕΥ"},i=["ΑΚΡΙΒΩΣ","ΑΛΑ","ΑΛΛΑ","ΑΛΛΙΩΣ","ΑΛΛΟΤΕ","ΑΜΑ","ΑΝΩ","ΑΝΑ","ΑΝΑΜΕΣΑ","ΑΝΑΜΕΤΑΞΥ","ΑΝΕΥ","ΑΝΤΙ","ΑΝΤΙΠΕΡΑ","ΑΝΤΙΟ","ΑΞΑΦΝΑ","ΑΠΟ","ΑΠΟΨΕ","ΑΡΑ","ΑΡΑΓΕ","ΑΥΡΙΟ","ΑΦΟΙ","ΑΦΟΥ","ΑΦΟΤΟΥ","ΒΡΕ","ΓΕΙΑ","ΓΙΑ","ΓΙΑΤΙ","ΓΡΑΜΜΑ","ΔΕΗ","ΔΕΝ","ΔΗΛΑΔΗ","ΔΙΧΩΣ","ΔΥΟ","ΕΑΝ","ΕΓΩ","ΕΔΩ","ΕΔΑ","ΕΙΘΕ","ΕΙΜΑΙ","ΕΙΜΑΣΤΕ","ΕΙΣΑΙ","ΕΙΣΑΣΤΕ","ΕΙΝΑΙ","ΕΙΣΤΕ","ΕΙΤΕ","ΕΚΕΙ","ΕΚΟ","ΕΛΑ","ΕΜΑΣ","ΕΜΕΙΣ","ΕΝΤΕΛΩΣ","ΕΝΤΟΣ","ΕΝΤΩΜΕΤΑΞΥ","ΕΝΩ","ΕΞΙ","ΕΞΙΣΟΥ","ΕΞΗΣ","ΕΞΩ","ΕΟΚ","ΕΠΑΝΩ","ΕΠΕΙΔΗ","ΕΠΕΙΤΑ","ΕΠΙ","ΕΠΙΣΗΣ","ΕΠΟΜΕΝΩΣ","ΕΠΤΑ","ΕΣΑΣ","ΕΣΕΙΣ","ΕΣΤΩ","ΕΣΥ","ΕΣΩ","ΕΤΣΙ","ΕΥΓΕ","ΕΦΕ","ΕΦΕΞΗΣ","ΕΧΤΕΣ","ΕΩΣ","ΗΔΗ","ΗΜΙ","ΗΠΑ","ΗΤΟΙ","ΘΕΣ","ΙΔΙΩΣ","ΙΔΗ","ΙΚΑ","ΙΣΩΣ","ΚΑΘΕ","ΚΑΘΕΤΙ","ΚΑΘΟΛΟΥ","ΚΑΘΩΣ","ΚΑΙ","ΚΑΝ","ΚΑΠΟΤΕ","ΚΑΠΟΥ","ΚΑΤΑ","ΚΑΤΙ","ΚΑΤΟΠΙΝ","ΚΑΤΩ","ΚΕΙ","ΚΙΧ","ΚΚΕ","ΚΟΛΑΝ","ΚΥΡΙΩΣ","ΚΩΣ","ΜΑΚΑΡΙ","ΜΑΛΙΣΤΑ","ΜΑΛΛΟΝ","ΜΑΙ","ΜΑΟ","ΜΑΟΥΣ","ΜΑΣ","ΜΕΘΑΥΡΙΟ","ΜΕΣ","ΜΕΣΑ","ΜΕΤΑ","ΜΕΤΑΞΥ","ΜΕΧΡΙ","ΜΗΔΕ","ΜΗΝ","ΜΗΠΩΣ","ΜΗΤΕ","ΜΙΑ","ΜΙΑΣ","ΜΙΣ","ΜΜΕ","ΜΟΛΟΝΟΤΙ","ΜΟΥ","ΜΠΑ","ΜΠΑΣ","ΜΠΟΥΦΑΝ","ΜΠΡΟΣ","ΝΑΙ","ΝΕΣ","ΝΤΑ","ΝΤΕ","ΞΑΝΑ","ΟΗΕ","ΟΚΤΩ","ΟΜΩΣ","ΟΝΕ","ΟΠΑ","ΟΠΟΥ","ΟΠΩΣ","ΟΣΟ","ΟΤΑΝ","ΟΤΕ","ΟΤΙ","ΟΥΤΕ","ΟΧΙ","ΠΑΛΙ","ΠΑΝ","ΠΑΝΟ","ΠΑΝΤΟΤΕ","ΠΑΝΤΟΥ","ΠΑΝΤΩΣ","ΠΑΝΩ","ΠΑΡΑ","ΠΕΡΑ","ΠΕΡΙ","ΠΕΡΙΠΟΥ","ΠΙΑ","ΠΙΟ","ΠΙΣΩ","ΠΛΑΙ","ΠΛΕΟΝ","ΠΛΗΝ","ΠΟΤΕ","ΠΟΥ","ΠΡΟ","ΠΡΟΣ","ΠΡΟΧΤΕΣ","ΠΡΟΧΘΕΣ","ΡΟΔΙ","ΠΩΣ","ΣΑΙ","ΣΑΣ","ΣΑΝ","ΣΕΙΣ","ΣΙΑ","ΣΚΙ","ΣΟΙ","ΣΟΥ","ΣΡΙ","ΣΥΝ","ΣΥΝΑΜΑ","ΣΧΕΔΟΝ","ΤΑΔΕ","ΤΑΞΙ","ΤΑΧΑ","ΤΕΙ","ΤΗΝ","ΤΗΣ","ΤΙΠΟΤΑ","ΤΙΠΟΤΕ","ΤΙΣ","ΤΟΝ","ΤΟΤΕ","ΤΟΥ","ΤΟΥΣ","ΤΣΑ","ΤΣΕ","ΤΣΙ","ΤΣΟΥ","ΤΩΝ","ΥΠΟ","ΥΠΟΨΗ","ΥΠΟΨΙΝ","ΥΣΤΕΡΑ","ΦΕΤΟΣ","ΦΙΣ","ΦΠΑ","ΧΑΦ","ΧΘΕΣ","ΧΤΕΣ","ΧΩΡΙΣ","ΩΣ","ΩΣΑΝ","ΩΣΟΤΟΥ","ΩΣΠΟΥ","ΩΣΤΕ","ΩΣΤΟΣΟ"],s=new RegExp("^[ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ]+$");return function(e){return"function"==typeof e.update?e.update(function(e){return n(e.toUpperCase()).toLowerCase()}):n(e.toUpperCase()).toLowerCase()}}(),e.Pipeline.registerFunction(e.el.stemmer,"stemmer-el"),e.el.stopWordFilter=e.generateStopWordFilter("αλλα αν αντι απο αυτα αυτεσ αυτη αυτο αυτοι αυτοσ αυτουσ αυτων για δε δεν εαν ειμαι ειμαστε ειναι εισαι ειστε εκεινα εκεινεσ εκεινη εκεινο εκεινοι εκεινοσ εκεινουσ εκεινων ενω επι η θα ισωσ κ και κατα κι μα με μετα μη μην να ο οι ομωσ οπωσ οσο οτι παρα ποια ποιεσ ποιο ποιοι ποιοσ ποιουσ ποιων που προσ πωσ σε στη στην στο στον τα την τησ το τον τοτε του των ωσ".split(" ")),e.Pipeline.registerFunction(e.el.stopWordFilter,"stopWordFilter-el"),e.el.normilizer=function(){var e={"Ά":"Α","ά":"α","Έ":"Ε","έ":"ε","Ή":"Η","ή":"η","Ί":"Ι","ί":"ι","Ό":"Ο","ο":"ο","Ύ":"Υ","ύ":"υ","Ώ":"Ω","ώ":"ω","Ϊ":"Ι","ϊ":"ι","Ϋ":"Υ","ϋ":"υ","ΐ":"ι","ΰ":"υ"};return function(t){if("function"==typeof t.update)return t.update(function(t){for(var r="",n=0;n=A.limit)return!0;A.cursor++}return!1}return!0}function n(){if(A.in_grouping(x,97,252)){var s=A.cursor;if(e()){if(A.cursor=s,!A.in_grouping(x,97,252))return!0;for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}}return!1}return!0}function i(){var s,r=A.cursor;if(n()){if(A.cursor=r,!A.out_grouping(x,97,252))return;if(s=A.cursor,e()){if(A.cursor=s,!A.in_grouping(x,97,252)||A.cursor>=A.limit)return;A.cursor++}}g=A.cursor}function a(){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}return!0}function t(){var e=A.cursor;g=A.limit,p=g,v=g,i(),A.cursor=e,a()&&(p=A.cursor,a()&&(v=A.cursor))}function o(){for(var e;;){if(A.bra=A.cursor,e=A.find_among(k,6))switch(A.ket=A.cursor,e){case 1:A.slice_from("a");continue;case 2:A.slice_from("e");continue;case 3:A.slice_from("i");continue;case 4:A.slice_from("o");continue;case 5:A.slice_from("u");continue;case 6:if(A.cursor>=A.limit)break;A.cursor++;continue}break}}function u(){return g<=A.cursor}function w(){return p<=A.cursor}function c(){return v<=A.cursor}function m(){var e;if(A.ket=A.cursor,A.find_among_b(y,13)&&(A.bra=A.cursor,(e=A.find_among_b(q,11))&&u()))switch(e){case 1:A.bra=A.cursor,A.slice_from("iendo");break;case 2:A.bra=A.cursor,A.slice_from("ando");break;case 3:A.bra=A.cursor,A.slice_from("ar");break;case 4:A.bra=A.cursor,A.slice_from("er");break;case 5:A.bra=A.cursor,A.slice_from("ir");break;case 6:A.slice_del();break;case 7:A.eq_s_b(1,"u")&&A.slice_del()}}function l(e,s){if(!c())return!0;A.slice_del(),A.ket=A.cursor;var r=A.find_among_b(e,s);return r&&(A.bra=A.cursor,1==r&&c()&&A.slice_del()),!1}function d(e){return!c()||(A.slice_del(),A.ket=A.cursor,A.eq_s_b(2,e)&&(A.bra=A.cursor,c()&&A.slice_del()),!1)}function b(){var e;if(A.ket=A.cursor,e=A.find_among_b(S,46)){switch(A.bra=A.cursor,e){case 1:if(!c())return!1;A.slice_del();break;case 2:if(d("ic"))return!1;break;case 3:if(!c())return!1;A.slice_from("log");break;case 4:if(!c())return!1;A.slice_from("u");break;case 5:if(!c())return!1;A.slice_from("ente");break;case 6:if(!w())return!1;A.slice_del(),A.ket=A.cursor,e=A.find_among_b(C,4),e&&(A.bra=A.cursor,c()&&(A.slice_del(),1==e&&(A.ket=A.cursor,A.eq_s_b(2,"at")&&(A.bra=A.cursor,c()&&A.slice_del()))));break;case 7:if(l(P,3))return!1;break;case 8:if(l(F,3))return!1;break;case 9:if(d("at"))return!1}return!0}return!1}function f(){var e,s;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(W,12),A.limit_backward=s,e)){if(A.bra=A.cursor,1==e){if(!A.eq_s_b(1,"u"))return!1;A.slice_del()}return!0}return!1}function _(){var e,s,r,n;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(L,96),A.limit_backward=s,e))switch(A.bra=A.cursor,e){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"u")?(n=A.limit-A.cursor,A.eq_s_b(1,"g")?A.cursor=A.limit-n:A.cursor=A.limit-r):A.cursor=A.limit-r,A.bra=A.cursor;case 2:A.slice_del()}}function h(){var e,s;if(A.ket=A.cursor,e=A.find_among_b(z,8))switch(A.bra=A.cursor,e){case 1:u()&&A.slice_del();break;case 2:u()&&(A.slice_del(),A.ket=A.cursor,A.eq_s_b(1,"u")&&(A.bra=A.cursor,s=A.limit-A.cursor,A.eq_s_b(1,"g")&&(A.cursor=A.limit-s,u()&&A.slice_del())))}}var v,p,g,k=[new s("",-1,6),new s("á",0,1),new s("é",0,2),new s("í",0,3),new s("ó",0,4),new s("ú",0,5)],y=[new s("la",-1,-1),new s("sela",0,-1),new s("le",-1,-1),new s("me",-1,-1),new s("se",-1,-1),new s("lo",-1,-1),new s("selo",5,-1),new s("las",-1,-1),new s("selas",7,-1),new s("les",-1,-1),new s("los",-1,-1),new s("selos",10,-1),new s("nos",-1,-1)],q=[new s("ando",-1,6),new s("iendo",-1,6),new s("yendo",-1,7),new s("ándo",-1,2),new s("iéndo",-1,1),new s("ar",-1,6),new s("er",-1,6),new s("ir",-1,6),new s("ár",-1,3),new s("ér",-1,4),new s("ír",-1,5)],C=[new s("ic",-1,-1),new s("ad",-1,-1),new s("os",-1,-1),new s("iv",-1,1)],P=[new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,1)],F=[new s("ic",-1,1),new s("abil",-1,1),new s("iv",-1,1)],S=[new s("ica",-1,1),new s("ancia",-1,2),new s("encia",-1,5),new s("adora",-1,2),new s("osa",-1,1),new s("ista",-1,1),new s("iva",-1,9),new s("anza",-1,1),new s("logía",-1,3),new s("idad",-1,8),new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,2),new s("mente",-1,7),new s("amente",13,6),new s("ación",-1,2),new s("ución",-1,4),new s("ico",-1,1),new s("ismo",-1,1),new s("oso",-1,1),new s("amiento",-1,1),new s("imiento",-1,1),new s("ivo",-1,9),new s("ador",-1,2),new s("icas",-1,1),new s("ancias",-1,2),new s("encias",-1,5),new s("adoras",-1,2),new s("osas",-1,1),new s("istas",-1,1),new s("ivas",-1,9),new s("anzas",-1,1),new s("logías",-1,3),new s("idades",-1,8),new s("ables",-1,1),new s("ibles",-1,1),new s("aciones",-1,2),new s("uciones",-1,4),new s("adores",-1,2),new s("antes",-1,2),new s("icos",-1,1),new s("ismos",-1,1),new s("osos",-1,1),new s("amientos",-1,1),new s("imientos",-1,1),new s("ivos",-1,9)],W=[new s("ya",-1,1),new s("ye",-1,1),new s("yan",-1,1),new s("yen",-1,1),new s("yeron",-1,1),new s("yendo",-1,1),new s("yo",-1,1),new s("yas",-1,1),new s("yes",-1,1),new s("yais",-1,1),new s("yamos",-1,1),new s("yó",-1,1)],L=[new s("aba",-1,2),new s("ada",-1,2),new s("ida",-1,2),new s("ara",-1,2),new s("iera",-1,2),new s("ía",-1,2),new s("aría",5,2),new s("ería",5,2),new s("iría",5,2),new s("ad",-1,2),new s("ed",-1,2),new s("id",-1,2),new s("ase",-1,2),new s("iese",-1,2),new s("aste",-1,2),new s("iste",-1,2),new s("an",-1,2),new s("aban",16,2),new s("aran",16,2),new s("ieran",16,2),new s("ían",16,2),new s("arían",20,2),new s("erían",20,2),new s("irían",20,2),new s("en",-1,1),new s("asen",24,2),new s("iesen",24,2),new s("aron",-1,2),new s("ieron",-1,2),new s("arán",-1,2),new s("erán",-1,2),new s("irán",-1,2),new s("ado",-1,2),new s("ido",-1,2),new s("ando",-1,2),new s("iendo",-1,2),new s("ar",-1,2),new s("er",-1,2),new s("ir",-1,2),new s("as",-1,2),new s("abas",39,2),new s("adas",39,2),new s("idas",39,2),new s("aras",39,2),new s("ieras",39,2),new s("ías",39,2),new s("arías",45,2),new s("erías",45,2),new s("irías",45,2),new s("es",-1,1),new s("ases",49,2),new s("ieses",49,2),new s("abais",-1,2),new s("arais",-1,2),new s("ierais",-1,2),new s("íais",-1,2),new s("aríais",55,2),new s("eríais",55,2),new s("iríais",55,2),new s("aseis",-1,2),new s("ieseis",-1,2),new s("asteis",-1,2),new s("isteis",-1,2),new s("áis",-1,2),new s("éis",-1,1),new s("aréis",64,2),new s("eréis",64,2),new s("iréis",64,2),new s("ados",-1,2),new s("idos",-1,2),new s("amos",-1,2),new s("ábamos",70,2),new s("áramos",70,2),new s("iéramos",70,2),new s("íamos",70,2),new s("aríamos",74,2),new s("eríamos",74,2),new s("iríamos",74,2),new s("emos",-1,1),new s("aremos",78,2),new s("eremos",78,2),new s("iremos",78,2),new s("ásemos",78,2),new s("iésemos",78,2),new s("imos",-1,2),new s("arás",-1,2),new s("erás",-1,2),new s("irás",-1,2),new s("ís",-1,2),new s("ará",-1,2),new s("erá",-1,2),new s("irá",-1,2),new s("aré",-1,2),new s("eré",-1,2),new s("iré",-1,2),new s("ió",-1,2)],z=[new s("a",-1,1),new s("e",-1,2),new s("o",-1,1),new s("os",-1,1),new s("á",-1,1),new s("é",-1,2),new s("í",-1,1),new s("ó",-1,1)],x=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,4,10],A=new r;this.setCurrent=function(e){A.setCurrent(e)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return t(),A.limit_backward=e,A.cursor=A.limit,m(),A.cursor=A.limit,b()||(A.cursor=A.limit,f()||(A.cursor=A.limit,_())),A.cursor=A.limit,h(),A.cursor=A.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.es.stemmer,"stemmer-es"),e.es.stopWordFilter=e.generateStopWordFilter("a al algo algunas algunos ante antes como con contra cual cuando de del desde donde durante e el ella ellas ellos en entre era erais eran eras eres es esa esas ese eso esos esta estaba estabais estaban estabas estad estada estadas estado estados estamos estando estar estaremos estará estarán estarás estaré estaréis estaría estaríais estaríamos estarían estarías estas este estemos esto estos estoy estuve estuviera estuvierais estuvieran estuvieras estuvieron estuviese estuvieseis estuviesen estuvieses estuvimos estuviste estuvisteis estuviéramos estuviésemos estuvo está estábamos estáis están estás esté estéis estén estés fue fuera fuerais fueran fueras fueron fuese fueseis fuesen fueses fui fuimos fuiste fuisteis fuéramos fuésemos ha habida habidas habido habidos habiendo habremos habrá habrán habrás habré habréis habría habríais habríamos habrían habrías habéis había habíais habíamos habían habías han has hasta hay haya hayamos hayan hayas hayáis he hemos hube hubiera hubierais hubieran hubieras hubieron hubiese hubieseis hubiesen hubieses hubimos hubiste hubisteis hubiéramos hubiésemos hubo la las le les lo los me mi mis mucho muchos muy más mí mía mías mío míos nada ni no nos nosotras nosotros nuestra nuestras nuestro nuestros o os otra otras otro otros para pero poco por porque que quien quienes qué se sea seamos sean seas seremos será serán serás seré seréis sería seríais seríamos serían serías seáis sido siendo sin sobre sois somos son soy su sus suya suyas suyo suyos sí también tanto te tendremos tendrá tendrán tendrás tendré tendréis tendría tendríais tendríamos tendrían tendrías tened tenemos tenga tengamos tengan tengas tengo tengáis tenida tenidas tenido tenidos teniendo tenéis tenía teníais teníamos tenían tenías ti tiene tienen tienes todo todos tu tus tuve tuviera tuvierais tuvieran tuvieras tuvieron tuviese tuvieseis tuviesen tuvieses tuvimos tuviste tuvisteis tuviéramos tuviésemos tuvo tuya tuyas tuyo tuyos tú un una uno unos vosotras vosotros vuestra vuestras vuestro vuestros y ya yo él éramos".split(" ")),e.Pipeline.registerFunction(e.es.stopWordFilter,"stopWordFilter-es")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.fi.min.js b/1.13/assets/javascripts/lunr/min/lunr.fi.min.js new file mode 100644 index 000000000..29f5dfcea --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.fi.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Finnish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(i,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e():e()(i.lunr)}(this,function(){return function(i){if(void 0===i)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===i.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");i.fi=function(){this.pipeline.reset(),this.pipeline.add(i.fi.trimmer,i.fi.stopWordFilter,i.fi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(i.fi.stemmer))},i.fi.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",i.fi.trimmer=i.trimmerSupport.generateTrimmer(i.fi.wordCharacters),i.Pipeline.registerFunction(i.fi.trimmer,"trimmer-fi"),i.fi.stemmer=function(){var e=i.stemmerSupport.Among,r=i.stemmerSupport.SnowballProgram,n=new function(){function i(){f=A.limit,d=f,n()||(f=A.cursor,n()||(d=A.cursor))}function n(){for(var i;;){if(i=A.cursor,A.in_grouping(W,97,246))break;if(A.cursor=i,i>=A.limit)return!0;A.cursor++}for(A.cursor=i;!A.out_grouping(W,97,246);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}function t(){return d<=A.cursor}function s(){var i,e;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(h,10)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.in_grouping_b(x,97,246))return;break;case 2:if(!t())return}A.slice_del()}else A.limit_backward=e}function o(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(v,9))switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"k")||(A.cursor=A.limit-r,A.slice_del());break;case 2:A.slice_del(),A.ket=A.cursor,A.eq_s_b(3,"kse")&&(A.bra=A.cursor,A.slice_from("ksi"));break;case 3:A.slice_del();break;case 4:A.find_among_b(p,6)&&A.slice_del();break;case 5:A.find_among_b(g,6)&&A.slice_del();break;case 6:A.find_among_b(j,2)&&A.slice_del()}else A.limit_backward=e}function l(){return A.find_among_b(q,7)}function a(){return A.eq_s_b(1,"i")&&A.in_grouping_b(L,97,246)}function u(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(C,30)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.eq_s_b(1,"a"))return;break;case 2:case 9:if(!A.eq_s_b(1,"e"))return;break;case 3:if(!A.eq_s_b(1,"i"))return;break;case 4:if(!A.eq_s_b(1,"o"))return;break;case 5:if(!A.eq_s_b(1,"ä"))return;break;case 6:if(!A.eq_s_b(1,"ö"))return;break;case 7:if(r=A.limit-A.cursor,!l()&&(A.cursor=A.limit-r,!A.eq_s_b(2,"ie"))){A.cursor=A.limit-r;break}if(A.cursor=A.limit-r,A.cursor<=A.limit_backward){A.cursor=A.limit-r;break}A.cursor--,A.bra=A.cursor;break;case 8:if(!A.in_grouping_b(W,97,246)||!A.out_grouping_b(W,97,246))return}A.slice_del(),k=!0}else A.limit_backward=e}function c(){var i,e,r;if(A.cursor>=d)if(e=A.limit_backward,A.limit_backward=d,A.ket=A.cursor,i=A.find_among_b(P,14)){if(A.bra=A.cursor,A.limit_backward=e,1==i){if(r=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-r}A.slice_del()}else A.limit_backward=e}function m(){var i;A.cursor>=f&&(i=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.find_among_b(F,2)?(A.bra=A.cursor,A.limit_backward=i,A.slice_del()):A.limit_backward=i)}function w(){var i,e,r,n,t,s;if(A.cursor>=f){if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.eq_s_b(1,"t")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.in_grouping_b(W,97,246)&&(A.cursor=A.limit-r,A.slice_del(),A.limit_backward=e,n=A.limit-A.cursor,A.cursor>=d&&(A.cursor=d,t=A.limit_backward,A.limit_backward=A.cursor,A.cursor=A.limit-n,A.ket=A.cursor,i=A.find_among_b(S,2))))){if(A.bra=A.cursor,A.limit_backward=t,1==i){if(s=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-s}return void A.slice_del()}A.limit_backward=e}}function _(){var i,e,r,n;if(A.cursor>=f){for(i=A.limit_backward,A.limit_backward=f,e=A.limit-A.cursor,l()&&(A.cursor=A.limit-e,A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.in_grouping_b(y,97,228)&&(A.bra=A.cursor,A.out_grouping_b(W,97,246)&&A.slice_del()),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"j")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.eq_s_b(1,"o")?A.slice_del():(A.cursor=A.limit-r,A.eq_s_b(1,"u")&&A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"o")&&(A.bra=A.cursor,A.eq_s_b(1,"j")&&A.slice_del()),A.cursor=A.limit-e,A.limit_backward=i;;){if(n=A.limit-A.cursor,A.out_grouping_b(W,97,246)){A.cursor=A.limit-n;break}if(A.cursor=A.limit-n,A.cursor<=A.limit_backward)return;A.cursor--}A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,b=A.slice_to(),A.eq_v_b(b)&&A.slice_del())}}var k,b,d,f,h=[new e("pa",-1,1),new e("sti",-1,2),new e("kaan",-1,1),new e("han",-1,1),new e("kin",-1,1),new e("hän",-1,1),new e("kään",-1,1),new e("ko",-1,1),new e("pä",-1,1),new e("kö",-1,1)],p=[new e("lla",-1,-1),new e("na",-1,-1),new e("ssa",-1,-1),new e("ta",-1,-1),new e("lta",3,-1),new e("sta",3,-1)],g=[new e("llä",-1,-1),new e("nä",-1,-1),new e("ssä",-1,-1),new e("tä",-1,-1),new e("ltä",3,-1),new e("stä",3,-1)],j=[new e("lle",-1,-1),new e("ine",-1,-1)],v=[new e("nsa",-1,3),new e("mme",-1,3),new e("nne",-1,3),new e("ni",-1,2),new e("si",-1,1),new e("an",-1,4),new e("en",-1,6),new e("än",-1,5),new e("nsä",-1,3)],q=[new e("aa",-1,-1),new e("ee",-1,-1),new e("ii",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1),new e("ää",-1,-1),new e("öö",-1,-1)],C=[new e("a",-1,8),new e("lla",0,-1),new e("na",0,-1),new e("ssa",0,-1),new e("ta",0,-1),new e("lta",4,-1),new e("sta",4,-1),new e("tta",4,9),new e("lle",-1,-1),new e("ine",-1,-1),new e("ksi",-1,-1),new e("n",-1,7),new e("han",11,1),new e("den",11,-1,a),new e("seen",11,-1,l),new e("hen",11,2),new e("tten",11,-1,a),new e("hin",11,3),new e("siin",11,-1,a),new e("hon",11,4),new e("hän",11,5),new e("hön",11,6),new e("ä",-1,8),new e("llä",22,-1),new e("nä",22,-1),new e("ssä",22,-1),new e("tä",22,-1),new e("ltä",26,-1),new e("stä",26,-1),new e("ttä",26,9)],P=[new e("eja",-1,-1),new e("mma",-1,1),new e("imma",1,-1),new e("mpa",-1,1),new e("impa",3,-1),new e("mmi",-1,1),new e("immi",5,-1),new e("mpi",-1,1),new e("impi",7,-1),new e("ejä",-1,-1),new e("mmä",-1,1),new e("immä",10,-1),new e("mpä",-1,1),new e("impä",12,-1)],F=[new e("i",-1,-1),new e("j",-1,-1)],S=[new e("mma",-1,1),new e("imma",0,-1)],y=[17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8],W=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],x=[17,97,24,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],A=new r;this.setCurrent=function(i){A.setCurrent(i)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return i(),k=!1,A.limit_backward=e,A.cursor=A.limit,s(),A.cursor=A.limit,o(),A.cursor=A.limit,u(),A.cursor=A.limit,c(),A.cursor=A.limit,k?(m(),A.cursor=A.limit):(A.cursor=A.limit,w(),A.cursor=A.limit),_(),!0}};return function(i){return"function"==typeof i.update?i.update(function(i){return n.setCurrent(i),n.stem(),n.getCurrent()}):(n.setCurrent(i),n.stem(),n.getCurrent())}}(),i.Pipeline.registerFunction(i.fi.stemmer,"stemmer-fi"),i.fi.stopWordFilter=i.generateStopWordFilter("ei eivät emme en et ette että he heidän heidät heihin heille heillä heiltä heissä heistä heitä hän häneen hänelle hänellä häneltä hänen hänessä hänestä hänet häntä itse ja johon joiden joihin joiksi joilla joille joilta joina joissa joista joita joka joksi jolla jolle jolta jona jonka jos jossa josta jota jotka kanssa keiden keihin keiksi keille keillä keiltä keinä keissä keistä keitä keneen keneksi kenelle kenellä keneltä kenen kenenä kenessä kenestä kenet ketkä ketkä ketä koska kuin kuka kun me meidän meidät meihin meille meillä meiltä meissä meistä meitä mihin miksi mikä mille millä miltä minkä minkä minua minulla minulle minulta minun minussa minusta minut minuun minä minä missä mistä mitkä mitä mukaan mutta ne niiden niihin niiksi niille niillä niiltä niin niin niinä niissä niistä niitä noiden noihin noiksi noilla noille noilta noin noina noissa noista noita nuo nyt näiden näihin näiksi näille näillä näiltä näinä näissä näistä näitä nämä ole olemme olen olet olette oli olimme olin olisi olisimme olisin olisit olisitte olisivat olit olitte olivat olla olleet ollut on ovat poikki se sekä sen siihen siinä siitä siksi sille sillä sillä siltä sinua sinulla sinulle sinulta sinun sinussa sinusta sinut sinuun sinä sinä sitä tai te teidän teidät teihin teille teillä teiltä teissä teistä teitä tuo tuohon tuoksi tuolla tuolle tuolta tuon tuona tuossa tuosta tuota tähän täksi tälle tällä tältä tämä tämän tänä tässä tästä tätä vaan vai vaikka yli".split(" ")),i.Pipeline.registerFunction(i.fi.stopWordFilter,"stopWordFilter-fi")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.fr.min.js b/1.13/assets/javascripts/lunr/min/lunr.fr.min.js new file mode 100644 index 000000000..68cd0094a --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.fr.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `French` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.fr=function(){this.pipeline.reset(),this.pipeline.add(e.fr.trimmer,e.fr.stopWordFilter,e.fr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.fr.stemmer))},e.fr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.fr.trimmer=e.trimmerSupport.generateTrimmer(e.fr.wordCharacters),e.Pipeline.registerFunction(e.fr.trimmer,"trimmer-fr"),e.fr.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,s){return!(!W.eq_s(1,e)||(W.ket=W.cursor,!W.in_grouping(F,97,251)))&&(W.slice_from(r),W.cursor=s,!0)}function i(e,r,s){return!!W.eq_s(1,e)&&(W.ket=W.cursor,W.slice_from(r),W.cursor=s,!0)}function n(){for(var r,s;;){if(r=W.cursor,W.in_grouping(F,97,251)){if(W.bra=W.cursor,s=W.cursor,e("u","U",r))continue;if(W.cursor=s,e("i","I",r))continue;if(W.cursor=s,i("y","Y",r))continue}if(W.cursor=r,W.bra=r,!e("y","Y",r)){if(W.cursor=r,W.eq_s(1,"q")&&(W.bra=W.cursor,i("u","U",r)))continue;if(W.cursor=r,r>=W.limit)return;W.cursor++}}}function t(){for(;!W.in_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}for(;!W.out_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}return!1}function u(){var e=W.cursor;if(q=W.limit,g=q,p=q,W.in_grouping(F,97,251)&&W.in_grouping(F,97,251)&&W.cursor=W.limit){W.cursor=q;break}W.cursor++}while(!W.in_grouping(F,97,251))}q=W.cursor,W.cursor=e,t()||(g=W.cursor,t()||(p=W.cursor))}function o(){for(var e,r;;){if(r=W.cursor,W.bra=r,!(e=W.find_among(h,4)))break;switch(W.ket=W.cursor,e){case 1:W.slice_from("i");break;case 2:W.slice_from("u");break;case 3:W.slice_from("y");break;case 4:if(W.cursor>=W.limit)return;W.cursor++}}}function c(){return q<=W.cursor}function a(){return g<=W.cursor}function l(){return p<=W.cursor}function w(){var e,r;if(W.ket=W.cursor,e=W.find_among_b(C,43)){switch(W.bra=W.cursor,e){case 1:if(!l())return!1;W.slice_del();break;case 2:if(!l())return!1;W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")&&(W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU"));break;case 3:if(!l())return!1;W.slice_from("log");break;case 4:if(!l())return!1;W.slice_from("u");break;case 5:if(!l())return!1;W.slice_from("ent");break;case 6:if(!c())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(z,6))switch(W.bra=W.cursor,e){case 1:l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&W.slice_del()));break;case 2:l()?W.slice_del():a()&&W.slice_from("eux");break;case 3:l()&&W.slice_del();break;case 4:c()&&W.slice_from("i")}break;case 7:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(y,3))switch(W.bra=W.cursor,e){case 1:l()?W.slice_del():W.slice_from("abl");break;case 2:l()?W.slice_del():W.slice_from("iqU");break;case 3:l()&&W.slice_del()}break;case 8:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")))){W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU");break}break;case 9:W.slice_from("eau");break;case 10:if(!a())return!1;W.slice_from("al");break;case 11:if(l())W.slice_del();else{if(!a())return!1;W.slice_from("eux")}break;case 12:if(!a()||!W.out_grouping_b(F,97,251))return!1;W.slice_del();break;case 13:return c()&&W.slice_from("ant"),!1;case 14:return c()&&W.slice_from("ent"),!1;case 15:return r=W.limit-W.cursor,W.in_grouping_b(F,97,251)&&c()&&(W.cursor=W.limit-r,W.slice_del()),!1}return!0}return!1}function f(){var e,r;if(W.cursor=q){if(s=W.limit_backward,W.limit_backward=q,W.ket=W.cursor,e=W.find_among_b(P,7))switch(W.bra=W.cursor,e){case 1:if(l()){if(i=W.limit-W.cursor,!W.eq_s_b(1,"s")&&(W.cursor=W.limit-i,!W.eq_s_b(1,"t")))break;W.slice_del()}break;case 2:W.slice_from("i");break;case 3:W.slice_del();break;case 4:W.eq_s_b(2,"gu")&&W.slice_del()}W.limit_backward=s}}function b(){var e=W.limit-W.cursor;W.find_among_b(U,5)&&(W.cursor=W.limit-e,W.ket=W.cursor,W.cursor>W.limit_backward&&(W.cursor--,W.bra=W.cursor,W.slice_del()))}function d(){for(var e,r=1;W.out_grouping_b(F,97,251);)r--;if(r<=0){if(W.ket=W.cursor,e=W.limit-W.cursor,!W.eq_s_b(1,"é")&&(W.cursor=W.limit-e,!W.eq_s_b(1,"è")))return;W.bra=W.cursor,W.slice_from("e")}}function k(){if(!w()&&(W.cursor=W.limit,!f()&&(W.cursor=W.limit,!m())))return W.cursor=W.limit,void _();W.cursor=W.limit,W.ket=W.cursor,W.eq_s_b(1,"Y")?(W.bra=W.cursor,W.slice_from("i")):(W.cursor=W.limit,W.eq_s_b(1,"ç")&&(W.bra=W.cursor,W.slice_from("c")))}var p,g,q,v=[new r("col",-1,-1),new r("par",-1,-1),new r("tap",-1,-1)],h=[new r("",-1,4),new r("I",0,1),new r("U",0,2),new r("Y",0,3)],z=[new r("iqU",-1,3),new r("abl",-1,3),new r("Ièr",-1,4),new r("ièr",-1,4),new r("eus",-1,2),new r("iv",-1,1)],y=[new r("ic",-1,2),new r("abil",-1,1),new r("iv",-1,3)],C=[new r("iqUe",-1,1),new r("atrice",-1,2),new r("ance",-1,1),new r("ence",-1,5),new r("logie",-1,3),new r("able",-1,1),new r("isme",-1,1),new r("euse",-1,11),new r("iste",-1,1),new r("ive",-1,8),new r("if",-1,8),new r("usion",-1,4),new r("ation",-1,2),new r("ution",-1,4),new r("ateur",-1,2),new r("iqUes",-1,1),new r("atrices",-1,2),new r("ances",-1,1),new r("ences",-1,5),new r("logies",-1,3),new r("ables",-1,1),new r("ismes",-1,1),new r("euses",-1,11),new r("istes",-1,1),new r("ives",-1,8),new r("ifs",-1,8),new r("usions",-1,4),new r("ations",-1,2),new r("utions",-1,4),new r("ateurs",-1,2),new r("ments",-1,15),new r("ements",30,6),new r("issements",31,12),new r("ités",-1,7),new r("ment",-1,15),new r("ement",34,6),new r("issement",35,12),new r("amment",34,13),new r("emment",34,14),new r("aux",-1,10),new r("eaux",39,9),new r("eux",-1,1),new r("ité",-1,7)],x=[new r("ira",-1,1),new r("ie",-1,1),new r("isse",-1,1),new r("issante",-1,1),new r("i",-1,1),new r("irai",4,1),new r("ir",-1,1),new r("iras",-1,1),new r("ies",-1,1),new r("îmes",-1,1),new r("isses",-1,1),new r("issantes",-1,1),new r("îtes",-1,1),new r("is",-1,1),new r("irais",13,1),new r("issais",13,1),new r("irions",-1,1),new r("issions",-1,1),new r("irons",-1,1),new r("issons",-1,1),new r("issants",-1,1),new r("it",-1,1),new r("irait",21,1),new r("issait",21,1),new r("issant",-1,1),new r("iraIent",-1,1),new r("issaIent",-1,1),new r("irent",-1,1),new r("issent",-1,1),new r("iront",-1,1),new r("ît",-1,1),new r("iriez",-1,1),new r("issiez",-1,1),new r("irez",-1,1),new r("issez",-1,1)],I=[new r("a",-1,3),new r("era",0,2),new r("asse",-1,3),new r("ante",-1,3),new r("ée",-1,2),new r("ai",-1,3),new r("erai",5,2),new r("er",-1,2),new r("as",-1,3),new r("eras",8,2),new r("âmes",-1,3),new r("asses",-1,3),new r("antes",-1,3),new r("âtes",-1,3),new r("ées",-1,2),new r("ais",-1,3),new r("erais",15,2),new r("ions",-1,1),new r("erions",17,2),new r("assions",17,3),new r("erons",-1,2),new r("ants",-1,3),new r("és",-1,2),new r("ait",-1,3),new r("erait",23,2),new r("ant",-1,3),new r("aIent",-1,3),new r("eraIent",26,2),new r("èrent",-1,2),new r("assent",-1,3),new r("eront",-1,2),new r("ât",-1,3),new r("ez",-1,2),new r("iez",32,2),new r("eriez",33,2),new r("assiez",33,3),new r("erez",32,2),new r("é",-1,2)],P=[new r("e",-1,3),new r("Ière",0,2),new r("ière",0,2),new r("ion",-1,1),new r("Ier",-1,2),new r("ier",-1,2),new r("ë",-1,4)],U=[new r("ell",-1,-1),new r("eill",-1,-1),new r("enn",-1,-1),new r("onn",-1,-1),new r("ett",-1,-1)],F=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,128,130,103,8,5],S=[1,65,20,0,0,0,0,0,0,0,0,0,0,0,0,0,128],W=new s;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){var e=W.cursor;return n(),W.cursor=e,u(),W.limit_backward=e,W.cursor=W.limit,k(),W.cursor=W.limit,b(),W.cursor=W.limit,d(),W.cursor=W.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.fr.stemmer,"stemmer-fr"),e.fr.stopWordFilter=e.generateStopWordFilter("ai aie aient aies ait as au aura aurai auraient aurais aurait auras aurez auriez aurions aurons auront aux avaient avais avait avec avez aviez avions avons ayant ayez ayons c ce ceci celà ces cet cette d dans de des du elle en es est et eu eue eues eurent eus eusse eussent eusses eussiez eussions eut eux eûmes eût eûtes furent fus fusse fussent fusses fussiez fussions fut fûmes fût fûtes ici il ils j je l la le les leur leurs lui m ma mais me mes moi mon même n ne nos notre nous on ont ou par pas pour qu que quel quelle quelles quels qui s sa sans se sera serai seraient serais serait seras serez seriez serions serons seront ses soi soient sois soit sommes son sont soyez soyons suis sur t ta te tes toi ton tu un une vos votre vous y à étaient étais était étant étiez étions été étée étées étés êtes".split(" ")),e.Pipeline.registerFunction(e.fr.stopWordFilter,"stopWordFilter-fr")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.he.min.js b/1.13/assets/javascripts/lunr/min/lunr.he.min.js new file mode 100644 index 000000000..b863d3eae --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.he.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.he=function(){this.pipeline.reset(),this.pipeline.add(e.he.trimmer,e.he.stopWordFilter,e.he.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.he.stemmer))},e.he.wordCharacters="֑-״א-תa-zA-Za-zA-Z0-90-9",e.he.trimmer=e.trimmerSupport.generateTrimmer(e.he.wordCharacters),e.Pipeline.registerFunction(e.he.trimmer,"trimmer-he"),e.he.stemmer=function(){var e=this;return e.result=!1,e.preRemoved=!1,e.sufRemoved=!1,e.pre={pre1:"ה ו י ת",pre2:"ב כ ל מ ש כש",pre3:"הב הכ הל המ הש בש לכ",pre4:"וב וכ ול ומ וש",pre5:"מה שה כל",pre6:"מב מכ מל ממ מש",pre7:"בה בו בי בת כה כו כי כת לה לו לי לת",pre8:"ובה ובו ובי ובת וכה וכו וכי וכת ולה ולו ולי ולת"},e.suf={suf1:"ך כ ם ן נ",suf2:"ים ות וך וכ ום ון ונ הם הן יכ יך ינ ים",suf3:"תי תך תכ תם תן תנ",suf4:"ותי ותך ותכ ותם ותן ותנ",suf5:"נו כם כן הם הן",suf6:"ונו וכם וכן והם והן",suf7:"תכם תכן תנו תהם תהן",suf8:"הוא היא הם הן אני אתה את אנו אתם אתן",suf9:"ני נו כי כו כם כן תי תך תכ תם תן",suf10:"י ך כ ם ן נ ת"},e.patterns=JSON.parse('{"hebrewPatterns": [{"pt1": [{"c": "ה", "l": 0}]}, {"pt2": [{"c": "ו", "l": 0}]}, {"pt3": [{"c": "י", "l": 0}]}, {"pt4": [{"c": "ת", "l": 0}]}, {"pt5": [{"c": "מ", "l": 0}]}, {"pt6": [{"c": "ל", "l": 0}]}, {"pt7": [{"c": "ב", "l": 0}]}, {"pt8": [{"c": "כ", "l": 0}]}, {"pt9": [{"c": "ש", "l": 0}]}, {"pt10": [{"c": "כש", "l": 0}]}, {"pt11": [{"c": "בה", "l": 0}]}, {"pt12": [{"c": "וב", "l": 0}]}, {"pt13": [{"c": "וכ", "l": 0}]}, {"pt14": [{"c": "ול", "l": 0}]}, {"pt15": [{"c": "ומ", "l": 0}]}, {"pt16": [{"c": "וש", "l": 0}]}, {"pt17": [{"c": "הב", "l": 0}]}, {"pt18": [{"c": "הכ", "l": 0}]}, {"pt19": [{"c": "הל", "l": 0}]}, {"pt20": [{"c": "המ", "l": 0}]}, {"pt21": [{"c": "הש", "l": 0}]}, {"pt22": [{"c": "מה", "l": 0}]}, {"pt23": [{"c": "שה", "l": 0}]}, {"pt24": [{"c": "כל", "l": 0}]}]}'),e.execArray=["cleanWord","removeDiacritics","removeStopWords","normalizeHebrewCharacters"],e.stem=function(){var r=0;for(e.result=!1,e.preRemoved=!1,e.sufRemoved=!1;r=0)return!0},e.normalizeHebrewCharacters=function(){return e.word=e.word.replace("ך","כ"),e.word=e.word.replace("ם","מ"),e.word=e.word.replace("ן","נ"),e.word=e.word.replace("ף","פ"),e.word=e.word.replace("ץ","צ"),!1},function(r){return"function"==typeof r.update?r.update(function(r){return e.setCurrent(r),e.stem(),e.getCurrent()}):(e.setCurrent(r),e.stem(),e.getCurrent())}}(),e.Pipeline.registerFunction(e.he.stemmer,"stemmer-he"),e.he.stopWordFilter=e.generateStopWordFilter("אבל או אולי אותו אותי אותך אותם אותן אותנו אז אחר אחרות אחרי אחריכן אחרים אחרת אי איזה איך אין איפה אל אלה אלו אם אנחנו אני אף אפשר את אתה אתכם אתכן אתם אתן באיזה באיזו בגלל בין בלבד בעבור בעזרת בכל בכן בלי במידה במקום שבו ברוב בשביל בשעה ש בתוך גם דרך הוא היא היה היי היכן היתה היתי הם הן הנה הסיבה שבגללה הרי ואילו ואת זאת זה זות יהיה יוכל יוכלו יותר מדי יכול יכולה יכולות יכולים יכל יכלה יכלו יש כאן כאשר כולם כולן כזה כי כיצד כך כל כלל כמו כן כפי כש לא לאו לאיזותך לאן לבין לה להיות להם להן לו לזה לזות לי לך לכם לכן למה למעלה למעלה מ למטה למטה מ למעט למקום שבו למרות לנו לעבר לעיכן לפיכך לפני מאד מאחורי מאיזו סיבה מאין מאיפה מבלי מבעד מדוע מה מהיכן מול מחוץ מי מידע מכאן מכל מכן מלבד מן מנין מסוגל מעט מעטים מעל מצד מקום בו מתחת מתי נגד נגר נו עד עז על עלי עליו עליה עליהם עליך עלינו עם עצמה עצמהם עצמהן עצמו עצמי עצמם עצמן עצמנו פה רק שוב של שלה שלהם שלהן שלו שלי שלך שלכה שלכם שלכן שלנו שם תהיה תחת".split(" ")),e.Pipeline.registerFunction(e.he.stopWordFilter,"stopWordFilter-he")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.hi.min.js b/1.13/assets/javascripts/lunr/min/lunr.hi.min.js new file mode 100644 index 000000000..7dbc41402 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.hi.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hi=function(){this.pipeline.reset(),this.pipeline.add(e.hi.trimmer,e.hi.stopWordFilter,e.hi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hi.stemmer))},e.hi.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿa-zA-Za-zA-Z0-90-9",e.hi.trimmer=e.trimmerSupport.generateTrimmer(e.hi.wordCharacters),e.Pipeline.registerFunction(e.hi.trimmer,"trimmer-hi"),e.hi.stopWordFilter=e.generateStopWordFilter("अत अपना अपनी अपने अभी अंदर आदि आप इत्यादि इन इनका इन्हीं इन्हें इन्हों इस इसका इसकी इसके इसमें इसी इसे उन उनका उनकी उनके उनको उन्हीं उन्हें उन्हों उस उसके उसी उसे एक एवं एस ऐसे और कई कर करता करते करना करने करें कहते कहा का काफ़ी कि कितना किन्हें किन्हों किया किर किस किसी किसे की कुछ कुल के को कोई कौन कौनसा गया घर जब जहाँ जा जितना जिन जिन्हें जिन्हों जिस जिसे जीधर जैसा जैसे जो तक तब तरह तिन तिन्हें तिन्हों तिस तिसे तो था थी थे दबारा दिया दुसरा दूसरे दो द्वारा न नके नहीं ना निहायत नीचे ने पर पहले पूरा पे फिर बनी बही बहुत बाद बाला बिलकुल भी भीतर मगर मानो मे में यदि यह यहाँ यही या यिह ये रखें रहा रहे ऱ्वासा लिए लिये लेकिन व वग़ैरह वर्ग वह वहाँ वहीं वाले वुह वे वो सकता सकते सबसे सभी साथ साबुत साभ सारा से सो संग ही हुआ हुई हुए है हैं हो होता होती होते होना होने".split(" ")),e.hi.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.hi.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var t=i.toString().toLowerCase().replace(/^\s+/,"");return r.cut(t).split("|")},e.Pipeline.registerFunction(e.hi.stemmer,"stemmer-hi"),e.Pipeline.registerFunction(e.hi.stopWordFilter,"stopWordFilter-hi")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.hu.min.js b/1.13/assets/javascripts/lunr/min/lunr.hu.min.js new file mode 100644 index 000000000..ed9d909f7 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.hu.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Hungarian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hu=function(){this.pipeline.reset(),this.pipeline.add(e.hu.trimmer,e.hu.stopWordFilter,e.hu.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hu.stemmer))},e.hu.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.hu.trimmer=e.trimmerSupport.generateTrimmer(e.hu.wordCharacters),e.Pipeline.registerFunction(e.hu.trimmer,"trimmer-hu"),e.hu.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,n=L.cursor;if(d=L.limit,L.in_grouping(W,97,252))for(;;){if(e=L.cursor,L.out_grouping(W,97,252))return L.cursor=e,L.find_among(g,8)||(L.cursor=e,e=L.limit)return void(d=e);L.cursor++}if(L.cursor=n,L.out_grouping(W,97,252)){for(;!L.in_grouping(W,97,252);){if(L.cursor>=L.limit)return;L.cursor++}d=L.cursor}}function i(){return d<=L.cursor}function a(){var e;if(L.ket=L.cursor,(e=L.find_among_b(h,2))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e")}}function t(){var e=L.limit-L.cursor;return!!L.find_among_b(p,23)&&(L.cursor=L.limit-e,!0)}function s(){if(L.cursor>L.limit_backward){L.cursor--,L.ket=L.cursor;var e=L.cursor-1;L.limit_backward<=e&&e<=L.limit&&(L.cursor=e,L.bra=e,L.slice_del())}}function c(){var e;if(L.ket=L.cursor,(e=L.find_among_b(_,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function o(){L.ket=L.cursor,L.find_among_b(v,44)&&(L.bra=L.cursor,i()&&(L.slice_del(),a()))}function w(){var e;if(L.ket=L.cursor,(e=L.find_among_b(z,3))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("e");break;case 2:case 3:L.slice_from("a")}}function l(){var e;if(L.ket=L.cursor,(e=L.find_among_b(y,6))&&(L.bra=L.cursor,i()))switch(e){case 1:case 2:L.slice_del();break;case 3:L.slice_from("a");break;case 4:L.slice_from("e")}}function u(){var e;if(L.ket=L.cursor,(e=L.find_among_b(j,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function m(){var e;if(L.ket=L.cursor,(e=L.find_among_b(C,7))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e");break;case 3:case 4:case 5:case 6:case 7:L.slice_del()}}function k(){var e;if(L.ket=L.cursor,(e=L.find_among_b(P,12))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 9:L.slice_del();break;case 2:case 5:case 8:L.slice_from("e");break;case 3:case 6:L.slice_from("a")}}function f(){var e;if(L.ket=L.cursor,(e=L.find_among_b(F,31))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 8:case 9:case 12:case 13:case 16:case 17:case 18:L.slice_del();break;case 2:case 5:case 10:case 14:case 19:L.slice_from("a");break;case 3:case 6:case 11:case 15:case 20:L.slice_from("e")}}function b(){var e;if(L.ket=L.cursor,(e=L.find_among_b(S,42))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 5:case 6:case 9:case 10:case 11:case 14:case 15:case 16:case 17:case 20:case 21:case 24:case 25:case 26:case 29:L.slice_del();break;case 2:case 7:case 12:case 18:case 22:case 27:L.slice_from("a");break;case 3:case 8:case 13:case 19:case 23:case 28:L.slice_from("e")}}var d,g=[new n("cs",-1,-1),new n("dzs",-1,-1),new n("gy",-1,-1),new n("ly",-1,-1),new n("ny",-1,-1),new n("sz",-1,-1),new n("ty",-1,-1),new n("zs",-1,-1)],h=[new n("á",-1,1),new n("é",-1,2)],p=[new n("bb",-1,-1),new n("cc",-1,-1),new n("dd",-1,-1),new n("ff",-1,-1),new n("gg",-1,-1),new n("jj",-1,-1),new n("kk",-1,-1),new n("ll",-1,-1),new n("mm",-1,-1),new n("nn",-1,-1),new n("pp",-1,-1),new n("rr",-1,-1),new n("ccs",-1,-1),new n("ss",-1,-1),new n("zzs",-1,-1),new n("tt",-1,-1),new n("vv",-1,-1),new n("ggy",-1,-1),new n("lly",-1,-1),new n("nny",-1,-1),new n("tty",-1,-1),new n("ssz",-1,-1),new n("zz",-1,-1)],_=[new n("al",-1,1),new n("el",-1,2)],v=[new n("ba",-1,-1),new n("ra",-1,-1),new n("be",-1,-1),new n("re",-1,-1),new n("ig",-1,-1),new n("nak",-1,-1),new n("nek",-1,-1),new n("val",-1,-1),new n("vel",-1,-1),new n("ul",-1,-1),new n("nál",-1,-1),new n("nél",-1,-1),new n("ból",-1,-1),new n("ról",-1,-1),new n("tól",-1,-1),new n("bõl",-1,-1),new n("rõl",-1,-1),new n("tõl",-1,-1),new n("ül",-1,-1),new n("n",-1,-1),new n("an",19,-1),new n("ban",20,-1),new n("en",19,-1),new n("ben",22,-1),new n("képpen",22,-1),new n("on",19,-1),new n("ön",19,-1),new n("képp",-1,-1),new n("kor",-1,-1),new n("t",-1,-1),new n("at",29,-1),new n("et",29,-1),new n("ként",29,-1),new n("anként",32,-1),new n("enként",32,-1),new n("onként",32,-1),new n("ot",29,-1),new n("ért",29,-1),new n("öt",29,-1),new n("hez",-1,-1),new n("hoz",-1,-1),new n("höz",-1,-1),new n("vá",-1,-1),new n("vé",-1,-1)],z=[new n("án",-1,2),new n("én",-1,1),new n("ánként",-1,3)],y=[new n("stul",-1,2),new n("astul",0,1),new n("ástul",0,3),new n("stül",-1,2),new n("estül",3,1),new n("éstül",3,4)],j=[new n("á",-1,1),new n("é",-1,2)],C=[new n("k",-1,7),new n("ak",0,4),new n("ek",0,6),new n("ok",0,5),new n("ák",0,1),new n("ék",0,2),new n("ök",0,3)],P=[new n("éi",-1,7),new n("áéi",0,6),new n("ééi",0,5),new n("é",-1,9),new n("ké",3,4),new n("aké",4,1),new n("eké",4,1),new n("oké",4,1),new n("áké",4,3),new n("éké",4,2),new n("öké",4,1),new n("éé",3,8)],F=[new n("a",-1,18),new n("ja",0,17),new n("d",-1,16),new n("ad",2,13),new n("ed",2,13),new n("od",2,13),new n("ád",2,14),new n("éd",2,15),new n("öd",2,13),new n("e",-1,18),new n("je",9,17),new n("nk",-1,4),new n("unk",11,1),new n("ánk",11,2),new n("énk",11,3),new n("ünk",11,1),new n("uk",-1,8),new n("juk",16,7),new n("ájuk",17,5),new n("ük",-1,8),new n("jük",19,7),new n("éjük",20,6),new n("m",-1,12),new n("am",22,9),new n("em",22,9),new n("om",22,9),new n("ám",22,10),new n("ém",22,11),new n("o",-1,18),new n("á",-1,19),new n("é",-1,20)],S=[new n("id",-1,10),new n("aid",0,9),new n("jaid",1,6),new n("eid",0,9),new n("jeid",3,6),new n("áid",0,7),new n("éid",0,8),new n("i",-1,15),new n("ai",7,14),new n("jai",8,11),new n("ei",7,14),new n("jei",10,11),new n("ái",7,12),new n("éi",7,13),new n("itek",-1,24),new n("eitek",14,21),new n("jeitek",15,20),new n("éitek",14,23),new n("ik",-1,29),new n("aik",18,26),new n("jaik",19,25),new n("eik",18,26),new n("jeik",21,25),new n("áik",18,27),new n("éik",18,28),new n("ink",-1,20),new n("aink",25,17),new n("jaink",26,16),new n("eink",25,17),new n("jeink",28,16),new n("áink",25,18),new n("éink",25,19),new n("aitok",-1,21),new n("jaitok",32,20),new n("áitok",-1,22),new n("im",-1,5),new n("aim",35,4),new n("jaim",36,1),new n("eim",35,4),new n("jeim",38,1),new n("áim",35,2),new n("éim",35,3)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,52,14],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var n=L.cursor;return e(),L.limit_backward=n,L.cursor=L.limit,c(),L.cursor=L.limit,o(),L.cursor=L.limit,w(),L.cursor=L.limit,l(),L.cursor=L.limit,u(),L.cursor=L.limit,k(),L.cursor=L.limit,f(),L.cursor=L.limit,b(),L.cursor=L.limit,m(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.hu.stemmer,"stemmer-hu"),e.hu.stopWordFilter=e.generateStopWordFilter("a abban ahhoz ahogy ahol aki akik akkor alatt amely amelyek amelyekben amelyeket amelyet amelynek ami amikor amit amolyan amíg annak arra arról az azok azon azonban azt aztán azután azzal azért be belül benne bár cikk cikkek cikkeket csak de e ebben eddig egy egyes egyetlen egyik egyre egyéb egész ehhez ekkor el ellen elsõ elég elõ elõször elõtt emilyen ennek erre ez ezek ezen ezt ezzel ezért fel felé hanem hiszen hogy hogyan igen ill ill. illetve ilyen ilyenkor ismét ison itt jobban jó jól kell kellett keressünk keresztül ki kívül között közül legalább legyen lehet lehetett lenne lenni lesz lett maga magát majd majd meg mellett mely melyek mert mi mikor milyen minden mindenki mindent mindig mint mintha mit mivel miért most már más másik még míg nagy nagyobb nagyon ne nekem neki nem nincs néha néhány nélkül olyan ott pedig persze rá s saját sem semmi sok sokat sokkal szemben szerint szinte számára talán tehát teljes tovább továbbá több ugyanis utolsó után utána vagy vagyis vagyok valaki valami valamint való van vannak vele vissza viszont volna volt voltak voltam voltunk által általában át én éppen és így õ õk õket össze úgy új újabb újra".split(" ")),e.Pipeline.registerFunction(e.hu.stopWordFilter,"stopWordFilter-hu")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.hy.min.js b/1.13/assets/javascripts/lunr/min/lunr.hy.min.js new file mode 100644 index 000000000..b37f79298 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.hy.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hy=function(){this.pipeline.reset(),this.pipeline.add(e.hy.trimmer,e.hy.stopWordFilter)},e.hy.wordCharacters="[A-Za-z԰-֏ff-ﭏ]",e.hy.trimmer=e.trimmerSupport.generateTrimmer(e.hy.wordCharacters),e.Pipeline.registerFunction(e.hy.trimmer,"trimmer-hy"),e.hy.stopWordFilter=e.generateStopWordFilter("դու և եք էիր էիք հետո նաև նրանք որը վրա է որ պիտի են այս մեջ ն իր ու ի այդ որոնք այն կամ էր մի ես համար այլ իսկ էին ենք հետ ին թ էինք մենք նրա նա դուք եմ էի ըստ որպես ում".split(" ")),e.Pipeline.registerFunction(e.hy.stopWordFilter,"stopWordFilter-hy"),e.hy.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}(),e.Pipeline.registerFunction(e.hy.stemmer,"stemmer-hy")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.it.min.js b/1.13/assets/javascripts/lunr/min/lunr.it.min.js new file mode 100644 index 000000000..344b6a3c0 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.it.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Italian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.it=function(){this.pipeline.reset(),this.pipeline.add(e.it.trimmer,e.it.stopWordFilter,e.it.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.it.stemmer))},e.it.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.it.trimmer=e.trimmerSupport.generateTrimmer(e.it.wordCharacters),e.Pipeline.registerFunction(e.it.trimmer,"trimmer-it"),e.it.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!x.eq_s(1,e)||(x.ket=x.cursor,!x.in_grouping(L,97,249)))&&(x.slice_from(r),x.cursor=n,!0)}function i(){for(var r,n,i,o,t=x.cursor;;){if(x.bra=x.cursor,r=x.find_among(h,7))switch(x.ket=x.cursor,r){case 1:x.slice_from("à");continue;case 2:x.slice_from("è");continue;case 3:x.slice_from("ì");continue;case 4:x.slice_from("ò");continue;case 5:x.slice_from("ù");continue;case 6:x.slice_from("qU");continue;case 7:if(x.cursor>=x.limit)break;x.cursor++;continue}break}for(x.cursor=t;;)for(n=x.cursor;;){if(i=x.cursor,x.in_grouping(L,97,249)){if(x.bra=x.cursor,o=x.cursor,e("u","U",i))break;if(x.cursor=o,e("i","I",i))break}if(x.cursor=i,x.cursor>=x.limit)return void(x.cursor=n);x.cursor++}}function o(e){if(x.cursor=e,!x.in_grouping(L,97,249))return!1;for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function t(){if(x.in_grouping(L,97,249)){var e=x.cursor;if(x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return o(e);x.cursor++}return!0}return o(e)}return!1}function s(){var e,r=x.cursor;if(!t()){if(x.cursor=r,!x.out_grouping(L,97,249))return;if(e=x.cursor,x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return x.cursor=e,void(x.in_grouping(L,97,249)&&x.cursor=x.limit)return;x.cursor++}k=x.cursor}function a(){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function u(){var e=x.cursor;k=x.limit,p=k,g=k,s(),x.cursor=e,a()&&(p=x.cursor,a()&&(g=x.cursor))}function c(){for(var e;;){if(x.bra=x.cursor,!(e=x.find_among(q,3)))break;switch(x.ket=x.cursor,e){case 1:x.slice_from("i");break;case 2:x.slice_from("u");break;case 3:if(x.cursor>=x.limit)return;x.cursor++}}}function w(){return k<=x.cursor}function l(){return p<=x.cursor}function m(){return g<=x.cursor}function f(){var e;if(x.ket=x.cursor,x.find_among_b(C,37)&&(x.bra=x.cursor,(e=x.find_among_b(z,5))&&w()))switch(e){case 1:x.slice_del();break;case 2:x.slice_from("e")}}function v(){var e;if(x.ket=x.cursor,!(e=x.find_among_b(S,51)))return!1;switch(x.bra=x.cursor,e){case 1:if(!m())return!1;x.slice_del();break;case 2:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del());break;case 3:if(!m())return!1;x.slice_from("log");break;case 4:if(!m())return!1;x.slice_from("u");break;case 5:if(!m())return!1;x.slice_from("ente");break;case 6:if(!w())return!1;x.slice_del();break;case 7:if(!l())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(P,4),e&&(x.bra=x.cursor,m()&&(x.slice_del(),1==e&&(x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&x.slice_del()))));break;case 8:if(!m())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(F,3),e&&(x.bra=x.cursor,1==e&&m()&&x.slice_del());break;case 9:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del())))}return!0}function b(){var e,r;x.cursor>=k&&(r=x.limit_backward,x.limit_backward=k,x.ket=x.cursor,e=x.find_among_b(W,87),e&&(x.bra=x.cursor,1==e&&x.slice_del()),x.limit_backward=r)}function d(){var e=x.limit-x.cursor;if(x.ket=x.cursor,x.in_grouping_b(y,97,242)&&(x.bra=x.cursor,w()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(1,"i")&&(x.bra=x.cursor,w()))))return void x.slice_del();x.cursor=x.limit-e}function _(){d(),x.ket=x.cursor,x.eq_s_b(1,"h")&&(x.bra=x.cursor,x.in_grouping_b(U,99,103)&&w()&&x.slice_del())}var g,p,k,h=[new r("",-1,7),new r("qu",0,6),new r("á",0,1),new r("é",0,2),new r("í",0,3),new r("ó",0,4),new r("ú",0,5)],q=[new r("",-1,3),new r("I",0,1),new r("U",0,2)],C=[new r("la",-1,-1),new r("cela",0,-1),new r("gliela",0,-1),new r("mela",0,-1),new r("tela",0,-1),new r("vela",0,-1),new r("le",-1,-1),new r("cele",6,-1),new r("gliele",6,-1),new r("mele",6,-1),new r("tele",6,-1),new r("vele",6,-1),new r("ne",-1,-1),new r("cene",12,-1),new r("gliene",12,-1),new r("mene",12,-1),new r("sene",12,-1),new r("tene",12,-1),new r("vene",12,-1),new r("ci",-1,-1),new r("li",-1,-1),new r("celi",20,-1),new r("glieli",20,-1),new r("meli",20,-1),new r("teli",20,-1),new r("veli",20,-1),new r("gli",20,-1),new r("mi",-1,-1),new r("si",-1,-1),new r("ti",-1,-1),new r("vi",-1,-1),new r("lo",-1,-1),new r("celo",31,-1),new r("glielo",31,-1),new r("melo",31,-1),new r("telo",31,-1),new r("velo",31,-1)],z=[new r("ando",-1,1),new r("endo",-1,1),new r("ar",-1,2),new r("er",-1,2),new r("ir",-1,2)],P=[new r("ic",-1,-1),new r("abil",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],F=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],S=[new r("ica",-1,1),new r("logia",-1,3),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,9),new r("anza",-1,1),new r("enza",-1,5),new r("ice",-1,1),new r("atrice",7,1),new r("iche",-1,1),new r("logie",-1,3),new r("abile",-1,1),new r("ibile",-1,1),new r("usione",-1,4),new r("azione",-1,2),new r("uzione",-1,4),new r("atore",-1,2),new r("ose",-1,1),new r("ante",-1,1),new r("mente",-1,1),new r("amente",19,7),new r("iste",-1,1),new r("ive",-1,9),new r("anze",-1,1),new r("enze",-1,5),new r("ici",-1,1),new r("atrici",25,1),new r("ichi",-1,1),new r("abili",-1,1),new r("ibili",-1,1),new r("ismi",-1,1),new r("usioni",-1,4),new r("azioni",-1,2),new r("uzioni",-1,4),new r("atori",-1,2),new r("osi",-1,1),new r("anti",-1,1),new r("amenti",-1,6),new r("imenti",-1,6),new r("isti",-1,1),new r("ivi",-1,9),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,6),new r("imento",-1,6),new r("ivo",-1,9),new r("ità",-1,8),new r("istà",-1,1),new r("istè",-1,1),new r("istì",-1,1)],W=[new r("isca",-1,1),new r("enda",-1,1),new r("ata",-1,1),new r("ita",-1,1),new r("uta",-1,1),new r("ava",-1,1),new r("eva",-1,1),new r("iva",-1,1),new r("erebbe",-1,1),new r("irebbe",-1,1),new r("isce",-1,1),new r("ende",-1,1),new r("are",-1,1),new r("ere",-1,1),new r("ire",-1,1),new r("asse",-1,1),new r("ate",-1,1),new r("avate",16,1),new r("evate",16,1),new r("ivate",16,1),new r("ete",-1,1),new r("erete",20,1),new r("irete",20,1),new r("ite",-1,1),new r("ereste",-1,1),new r("ireste",-1,1),new r("ute",-1,1),new r("erai",-1,1),new r("irai",-1,1),new r("isci",-1,1),new r("endi",-1,1),new r("erei",-1,1),new r("irei",-1,1),new r("assi",-1,1),new r("ati",-1,1),new r("iti",-1,1),new r("eresti",-1,1),new r("iresti",-1,1),new r("uti",-1,1),new r("avi",-1,1),new r("evi",-1,1),new r("ivi",-1,1),new r("isco",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("Yamo",-1,1),new r("iamo",-1,1),new r("avamo",-1,1),new r("evamo",-1,1),new r("ivamo",-1,1),new r("eremo",-1,1),new r("iremo",-1,1),new r("assimo",-1,1),new r("ammo",-1,1),new r("emmo",-1,1),new r("eremmo",54,1),new r("iremmo",54,1),new r("immo",-1,1),new r("ano",-1,1),new r("iscano",58,1),new r("avano",58,1),new r("evano",58,1),new r("ivano",58,1),new r("eranno",-1,1),new r("iranno",-1,1),new r("ono",-1,1),new r("iscono",65,1),new r("arono",65,1),new r("erono",65,1),new r("irono",65,1),new r("erebbero",-1,1),new r("irebbero",-1,1),new r("assero",-1,1),new r("essero",-1,1),new r("issero",-1,1),new r("ato",-1,1),new r("ito",-1,1),new r("uto",-1,1),new r("avo",-1,1),new r("evo",-1,1),new r("ivo",-1,1),new r("ar",-1,1),new r("ir",-1,1),new r("erà",-1,1),new r("irà",-1,1),new r("erò",-1,1),new r("irò",-1,1)],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2,1],y=[17,65,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2],U=[17],x=new n;this.setCurrent=function(e){x.setCurrent(e)},this.getCurrent=function(){return x.getCurrent()},this.stem=function(){var e=x.cursor;return i(),x.cursor=e,u(),x.limit_backward=e,x.cursor=x.limit,f(),x.cursor=x.limit,v()||(x.cursor=x.limit,b()),x.cursor=x.limit,_(),x.cursor=x.limit_backward,c(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.it.stemmer,"stemmer-it"),e.it.stopWordFilter=e.generateStopWordFilter("a abbia abbiamo abbiano abbiate ad agl agli ai al all alla alle allo anche avemmo avendo avesse avessero avessi avessimo aveste avesti avete aveva avevamo avevano avevate avevi avevo avrai avranno avrebbe avrebbero avrei avremmo avremo avreste avresti avrete avrà avrò avuta avute avuti avuto c che chi ci coi col come con contro cui da dagl dagli dai dal dall dalla dalle dallo degl degli dei del dell della delle dello di dov dove e ebbe ebbero ebbi ed era erano eravamo eravate eri ero essendo faccia facciamo facciano facciate faccio facemmo facendo facesse facessero facessi facessimo faceste facesti faceva facevamo facevano facevate facevi facevo fai fanno farai faranno farebbe farebbero farei faremmo faremo fareste faresti farete farà farò fece fecero feci fosse fossero fossi fossimo foste fosti fu fui fummo furono gli ha hai hanno ho i il in io l la le lei li lo loro lui ma mi mia mie miei mio ne negl negli nei nel nell nella nelle nello noi non nostra nostre nostri nostro o per perché più quale quanta quante quanti quanto quella quelle quelli quello questa queste questi questo sarai saranno sarebbe sarebbero sarei saremmo saremo sareste saresti sarete sarà sarò se sei si sia siamo siano siate siete sono sta stai stando stanno starai staranno starebbe starebbero starei staremmo staremo stareste staresti starete starà starò stava stavamo stavano stavate stavi stavo stemmo stesse stessero stessi stessimo steste stesti stette stettero stetti stia stiamo stiano stiate sto su sua sue sugl sugli sui sul sull sulla sulle sullo suo suoi ti tra tu tua tue tuo tuoi tutti tutto un una uno vi voi vostra vostre vostri vostro è".split(" ")),e.Pipeline.registerFunction(e.it.stopWordFilter,"stopWordFilter-it")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.ja.min.js b/1.13/assets/javascripts/lunr/min/lunr.ja.min.js new file mode 100644 index 000000000..5f254ebe9 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.ja.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(e=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=e);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=e;else if(n(e))break}else if(n(e))break}function n(r){return C.cursor=r,r>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,d=_,t()||(_=C.cursor,_<3&&(_=3),t()||(d=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var r;;)if(C.bra=C.cursor,r=C.find_among(p,3))switch(C.ket=C.cursor,r){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return d<=C.cursor}function a(){var r=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-r,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var r;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.slice_del(),w=!0,a())))}function m(){var r;u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.eq_s_b(3,"gem")||(C.cursor=C.limit-r,C.slice_del(),a())))}function f(){var r,e,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,r=C.find_among_b(h,5))switch(C.bra=C.cursor,r){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(j,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(e=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-e,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,r=C.find_among_b(k,6))switch(C.bra=C.cursor,r){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(z,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var d,_,w,b=[new e("",-1,6),new e("á",0,1),new e("ä",0,1),new e("é",0,2),new e("ë",0,2),new e("í",0,3),new e("ï",0,3),new e("ó",0,4),new e("ö",0,4),new e("ú",0,5),new e("ü",0,5)],p=[new e("",-1,3),new e("I",0,2),new e("Y",0,1)],g=[new e("dd",-1,-1),new e("kk",-1,-1),new e("tt",-1,-1)],h=[new e("ene",-1,2),new e("se",-1,3),new e("en",-1,2),new e("heden",2,1),new e("s",-1,3)],k=[new e("end",-1,1),new e("ig",-1,2),new e("ing",-1,1),new e("lijk",-1,3),new e("baar",-1,4),new e("bar",-1,5)],v=[new e("aa",-1,-1),new e("ee",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(r){C.setCurrent(r)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var e=C.cursor;return r(),C.cursor=e,o(),C.limit_backward=e,C.cursor=C.limit,f(),C.cursor=C.limit_backward,s(),!0}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.nl.stemmer,"stemmer-nl"),r.nl.stopWordFilter=r.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),r.Pipeline.registerFunction(r.nl.stopWordFilter,"stopWordFilter-nl")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.no.min.js b/1.13/assets/javascripts/lunr/min/lunr.no.min.js new file mode 100644 index 000000000..92bc7e4e8 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.no.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Norwegian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.pt.min.js b/1.13/assets/javascripts/lunr/min/lunr.pt.min.js new file mode 100644 index 000000000..6c16996d6 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.pt.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Portuguese` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.pt=function(){this.pipeline.reset(),this.pipeline.add(e.pt.trimmer,e.pt.stopWordFilter,e.pt.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.pt.stemmer))},e.pt.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.pt.trimmer=e.trimmerSupport.generateTrimmer(e.pt.wordCharacters),e.Pipeline.registerFunction(e.pt.trimmer,"trimmer-pt"),e.pt.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(k,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("a~");continue;case 2:z.slice_from("o~");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function n(){if(z.out_grouping(y,97,250)){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!0;z.cursor++}return!1}return!0}function i(){if(z.in_grouping(y,97,250))for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return g=z.cursor,!0}function o(){var e,r,s=z.cursor;if(z.in_grouping(y,97,250))if(e=z.cursor,n()){if(z.cursor=e,i())return}else g=z.cursor;if(z.cursor=s,z.out_grouping(y,97,250)){if(r=z.cursor,n()){if(z.cursor=r,!z.in_grouping(y,97,250)||z.cursor>=z.limit)return;z.cursor++}g=z.cursor}}function t(){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return!0}function a(){var e=z.cursor;g=z.limit,b=g,h=g,o(),z.cursor=e,t()&&(b=z.cursor,t()&&(h=z.cursor))}function u(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(q,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("ã");continue;case 2:z.slice_from("õ");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function w(){return g<=z.cursor}function m(){return b<=z.cursor}function c(){return h<=z.cursor}function l(){var e;if(z.ket=z.cursor,!(e=z.find_among_b(F,45)))return!1;switch(z.bra=z.cursor,e){case 1:if(!c())return!1;z.slice_del();break;case 2:if(!c())return!1;z.slice_from("log");break;case 3:if(!c())return!1;z.slice_from("u");break;case 4:if(!c())return!1;z.slice_from("ente");break;case 5:if(!m())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(j,4),e&&(z.bra=z.cursor,c()&&(z.slice_del(),1==e&&(z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del()))));break;case 6:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(C,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 7:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(P,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 8:if(!c())return!1;z.slice_del(),z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del());break;case 9:if(!w()||!z.eq_s_b(1,"e"))return!1;z.slice_from("ir")}return!0}function f(){var e,r;if(z.cursor>=g){if(r=z.limit_backward,z.limit_backward=g,z.ket=z.cursor,e=z.find_among_b(S,120))return z.bra=z.cursor,1==e&&z.slice_del(),z.limit_backward=r,!0;z.limit_backward=r}return!1}function d(){var e;z.ket=z.cursor,(e=z.find_among_b(W,7))&&(z.bra=z.cursor,1==e&&w()&&z.slice_del())}function v(e,r){if(z.eq_s_b(1,e)){z.bra=z.cursor;var s=z.limit-z.cursor;if(z.eq_s_b(1,r))return z.cursor=z.limit-s,w()&&z.slice_del(),!1}return!0}function p(){var e;if(z.ket=z.cursor,e=z.find_among_b(L,4))switch(z.bra=z.cursor,e){case 1:w()&&(z.slice_del(),z.ket=z.cursor,z.limit-z.cursor,v("u","g")&&v("i","c"));break;case 2:z.slice_from("c")}}function _(){if(!l()&&(z.cursor=z.limit,!f()))return z.cursor=z.limit,void d();z.cursor=z.limit,z.ket=z.cursor,z.eq_s_b(1,"i")&&(z.bra=z.cursor,z.eq_s_b(1,"c")&&(z.cursor=z.limit,w()&&z.slice_del()))}var h,b,g,k=[new r("",-1,3),new r("ã",0,1),new r("õ",0,2)],q=[new r("",-1,3),new r("a~",0,1),new r("o~",0,2)],j=[new r("ic",-1,-1),new r("ad",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],C=[new r("ante",-1,1),new r("avel",-1,1),new r("ível",-1,1)],P=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],F=[new r("ica",-1,1),new r("ância",-1,1),new r("ência",-1,4),new r("ira",-1,9),new r("adora",-1,1),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,8),new r("eza",-1,1),new r("logía",-1,2),new r("idade",-1,7),new r("ante",-1,1),new r("mente",-1,6),new r("amente",12,5),new r("ável",-1,1),new r("ível",-1,1),new r("ución",-1,3),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,1),new r("imento",-1,1),new r("ivo",-1,8),new r("aça~o",-1,1),new r("ador",-1,1),new r("icas",-1,1),new r("ências",-1,4),new r("iras",-1,9),new r("adoras",-1,1),new r("osas",-1,1),new r("istas",-1,1),new r("ivas",-1,8),new r("ezas",-1,1),new r("logías",-1,2),new r("idades",-1,7),new r("uciones",-1,3),new r("adores",-1,1),new r("antes",-1,1),new r("aço~es",-1,1),new r("icos",-1,1),new r("ismos",-1,1),new r("osos",-1,1),new r("amentos",-1,1),new r("imentos",-1,1),new r("ivos",-1,8)],S=[new r("ada",-1,1),new r("ida",-1,1),new r("ia",-1,1),new r("aria",2,1),new r("eria",2,1),new r("iria",2,1),new r("ara",-1,1),new r("era",-1,1),new r("ira",-1,1),new r("ava",-1,1),new r("asse",-1,1),new r("esse",-1,1),new r("isse",-1,1),new r("aste",-1,1),new r("este",-1,1),new r("iste",-1,1),new r("ei",-1,1),new r("arei",16,1),new r("erei",16,1),new r("irei",16,1),new r("am",-1,1),new r("iam",20,1),new r("ariam",21,1),new r("eriam",21,1),new r("iriam",21,1),new r("aram",20,1),new r("eram",20,1),new r("iram",20,1),new r("avam",20,1),new r("em",-1,1),new r("arem",29,1),new r("erem",29,1),new r("irem",29,1),new r("assem",29,1),new r("essem",29,1),new r("issem",29,1),new r("ado",-1,1),new r("ido",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("indo",-1,1),new r("ara~o",-1,1),new r("era~o",-1,1),new r("ira~o",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("ir",-1,1),new r("as",-1,1),new r("adas",47,1),new r("idas",47,1),new r("ias",47,1),new r("arias",50,1),new r("erias",50,1),new r("irias",50,1),new r("aras",47,1),new r("eras",47,1),new r("iras",47,1),new r("avas",47,1),new r("es",-1,1),new r("ardes",58,1),new r("erdes",58,1),new r("irdes",58,1),new r("ares",58,1),new r("eres",58,1),new r("ires",58,1),new r("asses",58,1),new r("esses",58,1),new r("isses",58,1),new r("astes",58,1),new r("estes",58,1),new r("istes",58,1),new r("is",-1,1),new r("ais",71,1),new r("eis",71,1),new r("areis",73,1),new r("ereis",73,1),new r("ireis",73,1),new r("áreis",73,1),new r("éreis",73,1),new r("íreis",73,1),new r("ásseis",73,1),new r("ésseis",73,1),new r("ísseis",73,1),new r("áveis",73,1),new r("íeis",73,1),new r("aríeis",84,1),new r("eríeis",84,1),new r("iríeis",84,1),new r("ados",-1,1),new r("idos",-1,1),new r("amos",-1,1),new r("áramos",90,1),new r("éramos",90,1),new r("íramos",90,1),new r("ávamos",90,1),new r("íamos",90,1),new r("aríamos",95,1),new r("eríamos",95,1),new r("iríamos",95,1),new r("emos",-1,1),new r("aremos",99,1),new r("eremos",99,1),new r("iremos",99,1),new r("ássemos",99,1),new r("êssemos",99,1),new r("íssemos",99,1),new r("imos",-1,1),new r("armos",-1,1),new r("ermos",-1,1),new r("irmos",-1,1),new r("ámos",-1,1),new r("arás",-1,1),new r("erás",-1,1),new r("irás",-1,1),new r("eu",-1,1),new r("iu",-1,1),new r("ou",-1,1),new r("ará",-1,1),new r("erá",-1,1),new r("irá",-1,1)],W=[new r("a",-1,1),new r("i",-1,1),new r("o",-1,1),new r("os",-1,1),new r("á",-1,1),new r("í",-1,1),new r("ó",-1,1)],L=[new r("e",-1,1),new r("ç",-1,2),new r("é",-1,1),new r("ê",-1,1)],y=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,3,19,12,2],z=new s;this.setCurrent=function(e){z.setCurrent(e)},this.getCurrent=function(){return z.getCurrent()},this.stem=function(){var r=z.cursor;return e(),z.cursor=r,a(),z.limit_backward=r,z.cursor=z.limit,_(),z.cursor=z.limit,p(),z.cursor=z.limit_backward,u(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.pt.stemmer,"stemmer-pt"),e.pt.stopWordFilter=e.generateStopWordFilter("a ao aos aquela aquelas aquele aqueles aquilo as até com como da das de dela delas dele deles depois do dos e ela elas ele eles em entre era eram essa essas esse esses esta estamos estas estava estavam este esteja estejam estejamos estes esteve estive estivemos estiver estivera estiveram estiverem estivermos estivesse estivessem estivéramos estivéssemos estou está estávamos estão eu foi fomos for fora foram forem formos fosse fossem fui fôramos fôssemos haja hajam hajamos havemos hei houve houvemos houver houvera houveram houverei houverem houveremos houveria houveriam houvermos houverá houverão houveríamos houvesse houvessem houvéramos houvéssemos há hão isso isto já lhe lhes mais mas me mesmo meu meus minha minhas muito na nas nem no nos nossa nossas nosso nossos num numa não nós o os ou para pela pelas pelo pelos por qual quando que quem se seja sejam sejamos sem serei seremos seria seriam será serão seríamos seu seus somos sou sua suas são só também te tem temos tenha tenham tenhamos tenho terei teremos teria teriam terá terão teríamos teu teus teve tinha tinham tive tivemos tiver tivera tiveram tiverem tivermos tivesse tivessem tivéramos tivéssemos tu tua tuas tém tínhamos um uma você vocês vos à às éramos".split(" ")),e.Pipeline.registerFunction(e.pt.stopWordFilter,"stopWordFilter-pt")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.ro.min.js b/1.13/assets/javascripts/lunr/min/lunr.ro.min.js new file mode 100644 index 000000000..727714018 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.ro.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Romanian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ro=function(){this.pipeline.reset(),this.pipeline.add(e.ro.trimmer,e.ro.stopWordFilter,e.ro.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ro.stemmer))},e.ro.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.ro.trimmer=e.trimmerSupport.generateTrimmer(e.ro.wordCharacters),e.Pipeline.registerFunction(e.ro.trimmer,"trimmer-ro"),e.ro.stemmer=function(){var i=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,n=new function(){function e(e,i){L.eq_s(1,e)&&(L.ket=L.cursor,L.in_grouping(W,97,259)&&L.slice_from(i))}function n(){for(var i,r;;){if(i=L.cursor,L.in_grouping(W,97,259)&&(r=L.cursor,L.bra=r,e("u","U"),L.cursor=r,e("i","I")),L.cursor=i,L.cursor>=L.limit)break;L.cursor++}}function t(){if(L.out_grouping(W,97,259)){for(;!L.in_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}return!0}function a(){if(L.in_grouping(W,97,259))for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}function o(){var e,i,r=L.cursor;if(L.in_grouping(W,97,259)){if(e=L.cursor,!t())return void(h=L.cursor);if(L.cursor=e,!a())return void(h=L.cursor)}L.cursor=r,L.out_grouping(W,97,259)&&(i=L.cursor,t()&&(L.cursor=i,L.in_grouping(W,97,259)&&L.cursor=L.limit)return!1;L.cursor++}for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!1;L.cursor++}return!0}function c(){var e=L.cursor;h=L.limit,k=h,g=h,o(),L.cursor=e,u()&&(k=L.cursor,u()&&(g=L.cursor))}function s(){for(var e;;){if(L.bra=L.cursor,e=L.find_among(z,3))switch(L.ket=L.cursor,e){case 1:L.slice_from("i");continue;case 2:L.slice_from("u");continue;case 3:if(L.cursor>=L.limit)break;L.cursor++;continue}break}}function w(){return h<=L.cursor}function m(){return k<=L.cursor}function l(){return g<=L.cursor}function f(){var e,i;if(L.ket=L.cursor,(e=L.find_among_b(C,16))&&(L.bra=L.cursor,m()))switch(e){case 1:L.slice_del();break;case 2:L.slice_from("a");break;case 3:L.slice_from("e");break;case 4:L.slice_from("i");break;case 5:i=L.limit-L.cursor,L.eq_s_b(2,"ab")||(L.cursor=L.limit-i,L.slice_from("i"));break;case 6:L.slice_from("at");break;case 7:L.slice_from("aţi")}}function p(){var e,i=L.limit-L.cursor;if(L.ket=L.cursor,(e=L.find_among_b(P,46))&&(L.bra=L.cursor,m())){switch(e){case 1:L.slice_from("abil");break;case 2:L.slice_from("ibil");break;case 3:L.slice_from("iv");break;case 4:L.slice_from("ic");break;case 5:L.slice_from("at");break;case 6:L.slice_from("it")}return _=!0,L.cursor=L.limit-i,!0}return!1}function d(){var e,i;for(_=!1;;)if(i=L.limit-L.cursor,!p()){L.cursor=L.limit-i;break}if(L.ket=L.cursor,(e=L.find_among_b(F,62))&&(L.bra=L.cursor,l())){switch(e){case 1:L.slice_del();break;case 2:L.eq_s_b(1,"ţ")&&(L.bra=L.cursor,L.slice_from("t"));break;case 3:L.slice_from("ist")}_=!0}}function b(){var e,i,r;if(L.cursor>=h){if(i=L.limit_backward,L.limit_backward=h,L.ket=L.cursor,e=L.find_among_b(q,94))switch(L.bra=L.cursor,e){case 1:if(r=L.limit-L.cursor,!L.out_grouping_b(W,97,259)&&(L.cursor=L.limit-r,!L.eq_s_b(1,"u")))break;case 2:L.slice_del()}L.limit_backward=i}}function v(){var e;L.ket=L.cursor,(e=L.find_among_b(S,5))&&(L.bra=L.cursor,w()&&1==e&&L.slice_del())}var _,g,k,h,z=[new i("",-1,3),new i("I",0,1),new i("U",0,2)],C=[new i("ea",-1,3),new i("aţia",-1,7),new i("aua",-1,2),new i("iua",-1,4),new i("aţie",-1,7),new i("ele",-1,3),new i("ile",-1,5),new i("iile",6,4),new i("iei",-1,4),new i("atei",-1,6),new i("ii",-1,4),new i("ului",-1,1),new i("ul",-1,1),new i("elor",-1,3),new i("ilor",-1,4),new i("iilor",14,4)],P=[new i("icala",-1,4),new i("iciva",-1,4),new i("ativa",-1,5),new i("itiva",-1,6),new i("icale",-1,4),new i("aţiune",-1,5),new i("iţiune",-1,6),new i("atoare",-1,5),new i("itoare",-1,6),new i("ătoare",-1,5),new i("icitate",-1,4),new i("abilitate",-1,1),new i("ibilitate",-1,2),new i("ivitate",-1,3),new i("icive",-1,4),new i("ative",-1,5),new i("itive",-1,6),new i("icali",-1,4),new i("atori",-1,5),new i("icatori",18,4),new i("itori",-1,6),new i("ători",-1,5),new i("icitati",-1,4),new i("abilitati",-1,1),new i("ivitati",-1,3),new i("icivi",-1,4),new i("ativi",-1,5),new i("itivi",-1,6),new i("icităi",-1,4),new i("abilităi",-1,1),new i("ivităi",-1,3),new i("icităţi",-1,4),new i("abilităţi",-1,1),new i("ivităţi",-1,3),new i("ical",-1,4),new i("ator",-1,5),new i("icator",35,4),new i("itor",-1,6),new i("ător",-1,5),new i("iciv",-1,4),new i("ativ",-1,5),new i("itiv",-1,6),new i("icală",-1,4),new i("icivă",-1,4),new i("ativă",-1,5),new i("itivă",-1,6)],F=[new i("ica",-1,1),new i("abila",-1,1),new i("ibila",-1,1),new i("oasa",-1,1),new i("ata",-1,1),new i("ita",-1,1),new i("anta",-1,1),new i("ista",-1,3),new i("uta",-1,1),new i("iva",-1,1),new i("ic",-1,1),new i("ice",-1,1),new i("abile",-1,1),new i("ibile",-1,1),new i("isme",-1,3),new i("iune",-1,2),new i("oase",-1,1),new i("ate",-1,1),new i("itate",17,1),new i("ite",-1,1),new i("ante",-1,1),new i("iste",-1,3),new i("ute",-1,1),new i("ive",-1,1),new i("ici",-1,1),new i("abili",-1,1),new i("ibili",-1,1),new i("iuni",-1,2),new i("atori",-1,1),new i("osi",-1,1),new i("ati",-1,1),new i("itati",30,1),new i("iti",-1,1),new i("anti",-1,1),new i("isti",-1,3),new i("uti",-1,1),new i("işti",-1,3),new i("ivi",-1,1),new i("ităi",-1,1),new i("oşi",-1,1),new i("ităţi",-1,1),new i("abil",-1,1),new i("ibil",-1,1),new i("ism",-1,3),new i("ator",-1,1),new i("os",-1,1),new i("at",-1,1),new i("it",-1,1),new i("ant",-1,1),new i("ist",-1,3),new i("ut",-1,1),new i("iv",-1,1),new i("ică",-1,1),new i("abilă",-1,1),new i("ibilă",-1,1),new i("oasă",-1,1),new i("ată",-1,1),new i("ită",-1,1),new i("antă",-1,1),new i("istă",-1,3),new i("ută",-1,1),new i("ivă",-1,1)],q=[new i("ea",-1,1),new i("ia",-1,1),new i("esc",-1,1),new i("ăsc",-1,1),new i("ind",-1,1),new i("ând",-1,1),new i("are",-1,1),new i("ere",-1,1),new i("ire",-1,1),new i("âre",-1,1),new i("se",-1,2),new i("ase",10,1),new i("sese",10,2),new i("ise",10,1),new i("use",10,1),new i("âse",10,1),new i("eşte",-1,1),new i("ăşte",-1,1),new i("eze",-1,1),new i("ai",-1,1),new i("eai",19,1),new i("iai",19,1),new i("sei",-1,2),new i("eşti",-1,1),new i("ăşti",-1,1),new i("ui",-1,1),new i("ezi",-1,1),new i("âi",-1,1),new i("aşi",-1,1),new i("seşi",-1,2),new i("aseşi",29,1),new i("seseşi",29,2),new i("iseşi",29,1),new i("useşi",29,1),new i("âseşi",29,1),new i("işi",-1,1),new i("uşi",-1,1),new i("âşi",-1,1),new i("aţi",-1,2),new i("eaţi",38,1),new i("iaţi",38,1),new i("eţi",-1,2),new i("iţi",-1,2),new i("âţi",-1,2),new i("arăţi",-1,1),new i("serăţi",-1,2),new i("aserăţi",45,1),new i("seserăţi",45,2),new i("iserăţi",45,1),new i("userăţi",45,1),new i("âserăţi",45,1),new i("irăţi",-1,1),new i("urăţi",-1,1),new i("ârăţi",-1,1),new i("am",-1,1),new i("eam",54,1),new i("iam",54,1),new i("em",-1,2),new i("asem",57,1),new i("sesem",57,2),new i("isem",57,1),new i("usem",57,1),new i("âsem",57,1),new i("im",-1,2),new i("âm",-1,2),new i("ăm",-1,2),new i("arăm",65,1),new i("serăm",65,2),new i("aserăm",67,1),new i("seserăm",67,2),new i("iserăm",67,1),new i("userăm",67,1),new i("âserăm",67,1),new i("irăm",65,1),new i("urăm",65,1),new i("ârăm",65,1),new i("au",-1,1),new i("eau",76,1),new i("iau",76,1),new i("indu",-1,1),new i("ându",-1,1),new i("ez",-1,1),new i("ească",-1,1),new i("ară",-1,1),new i("seră",-1,2),new i("aseră",84,1),new i("seseră",84,2),new i("iseră",84,1),new i("useră",84,1),new i("âseră",84,1),new i("iră",-1,1),new i("ură",-1,1),new i("âră",-1,1),new i("ează",-1,1)],S=[new i("a",-1,1),new i("e",-1,1),new i("ie",1,1),new i("i",-1,1),new i("ă",-1,1)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,2,32,0,0,4],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var e=L.cursor;return n(),L.cursor=e,c(),L.limit_backward=e,L.cursor=L.limit,f(),L.cursor=L.limit,d(),L.cursor=L.limit,_||(L.cursor=L.limit,b(),L.cursor=L.limit),v(),L.cursor=L.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.ro.stemmer,"stemmer-ro"),e.ro.stopWordFilter=e.generateStopWordFilter("acea aceasta această aceea acei aceia acel acela acele acelea acest acesta aceste acestea aceşti aceştia acolo acord acum ai aia aibă aici al ale alea altceva altcineva am ar are asemenea asta astea astăzi asupra au avea avem aveţi azi aş aşadar aţi bine bucur bună ca care caut ce cel ceva chiar cinci cine cineva contra cu cum cumva curând curînd când cât câte câtva câţi cînd cît cîte cîtva cîţi că căci cărei căror cărui către da dacă dar datorită dată dau de deci deja deoarece departe deşi din dinaintea dintr- dintre doi doilea două drept după dă ea ei el ele eram este eu eşti face fata fi fie fiecare fii fim fiu fiţi frumos fără graţie halbă iar ieri la le li lor lui lângă lîngă mai mea mei mele mereu meu mi mie mine mult multă mulţi mulţumesc mâine mîine mă ne nevoie nici nicăieri nimeni nimeri nimic nişte noastre noastră noi noroc nostru nouă noştri nu opt ori oricare orice oricine oricum oricând oricât oricînd oricît oriunde patra patru patrulea pe pentru peste pic poate pot prea prima primul prin puţin puţina puţină până pînă rog sa sale sau se spate spre sub sunt suntem sunteţi sută sînt sîntem sînteţi să săi său ta tale te timp tine toate toată tot totuşi toţi trei treia treilea tu tăi tău un una unde undeva unei uneia unele uneori unii unor unora unu unui unuia unul vi voastre voastră voi vostru vouă voştri vreme vreo vreun vă zece zero zi zice îi îl îmi împotriva în înainte înaintea încotro încât încît între întrucât întrucît îţi ăla ălea ăsta ăstea ăştia şapte şase şi ştiu ţi ţie".split(" ")),e.Pipeline.registerFunction(e.ro.stopWordFilter,"stopWordFilter-ro")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.ru.min.js b/1.13/assets/javascripts/lunr/min/lunr.ru.min.js new file mode 100644 index 000000000..186cc485c --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.ru.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Russian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ru=function(){this.pipeline.reset(),this.pipeline.add(e.ru.trimmer,e.ru.stopWordFilter,e.ru.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ru.stemmer))},e.ru.wordCharacters="Ѐ-҄҇-ԯᴫᵸⷠ-ⷿꙀ-ꚟ︮︯",e.ru.trimmer=e.trimmerSupport.generateTrimmer(e.ru.wordCharacters),e.Pipeline.registerFunction(e.ru.trimmer,"trimmer-ru"),e.ru.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,t=new function(){function e(){for(;!W.in_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function t(){for(;!W.out_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function w(){b=W.limit,_=b,e()&&(b=W.cursor,t()&&e()&&t()&&(_=W.cursor))}function i(){return _<=W.cursor}function u(e,n){var r,t;if(W.ket=W.cursor,r=W.find_among_b(e,n)){switch(W.bra=W.cursor,r){case 1:if(t=W.limit-W.cursor,!W.eq_s_b(1,"а")&&(W.cursor=W.limit-t,!W.eq_s_b(1,"я")))return!1;case 2:W.slice_del()}return!0}return!1}function o(){return u(h,9)}function s(e,n){var r;return W.ket=W.cursor,!!(r=W.find_among_b(e,n))&&(W.bra=W.cursor,1==r&&W.slice_del(),!0)}function c(){return s(g,26)}function m(){return!!c()&&(u(C,8),!0)}function f(){return s(k,2)}function l(){return u(P,46)}function a(){s(v,36)}function p(){var e;W.ket=W.cursor,(e=W.find_among_b(F,2))&&(W.bra=W.cursor,i()&&1==e&&W.slice_del())}function d(){var e;if(W.ket=W.cursor,e=W.find_among_b(q,4))switch(W.bra=W.cursor,e){case 1:if(W.slice_del(),W.ket=W.cursor,!W.eq_s_b(1,"н"))break;W.bra=W.cursor;case 2:if(!W.eq_s_b(1,"н"))break;case 3:W.slice_del()}}var _,b,h=[new n("в",-1,1),new n("ив",0,2),new n("ыв",0,2),new n("вши",-1,1),new n("ивши",3,2),new n("ывши",3,2),new n("вшись",-1,1),new n("ившись",6,2),new n("ывшись",6,2)],g=[new n("ее",-1,1),new n("ие",-1,1),new n("ое",-1,1),new n("ые",-1,1),new n("ими",-1,1),new n("ыми",-1,1),new n("ей",-1,1),new n("ий",-1,1),new n("ой",-1,1),new n("ый",-1,1),new n("ем",-1,1),new n("им",-1,1),new n("ом",-1,1),new n("ым",-1,1),new n("его",-1,1),new n("ого",-1,1),new n("ему",-1,1),new n("ому",-1,1),new n("их",-1,1),new n("ых",-1,1),new n("ею",-1,1),new n("ою",-1,1),new n("ую",-1,1),new n("юю",-1,1),new n("ая",-1,1),new n("яя",-1,1)],C=[new n("ем",-1,1),new n("нн",-1,1),new n("вш",-1,1),new n("ивш",2,2),new n("ывш",2,2),new n("щ",-1,1),new n("ющ",5,1),new n("ующ",6,2)],k=[new n("сь",-1,1),new n("ся",-1,1)],P=[new n("ла",-1,1),new n("ила",0,2),new n("ыла",0,2),new n("на",-1,1),new n("ена",3,2),new n("ете",-1,1),new n("ите",-1,2),new n("йте",-1,1),new n("ейте",7,2),new n("уйте",7,2),new n("ли",-1,1),new n("или",10,2),new n("ыли",10,2),new n("й",-1,1),new n("ей",13,2),new n("уй",13,2),new n("л",-1,1),new n("ил",16,2),new n("ыл",16,2),new n("ем",-1,1),new n("им",-1,2),new n("ым",-1,2),new n("н",-1,1),new n("ен",22,2),new n("ло",-1,1),new n("ило",24,2),new n("ыло",24,2),new n("но",-1,1),new n("ено",27,2),new n("нно",27,1),new n("ет",-1,1),new n("ует",30,2),new n("ит",-1,2),new n("ыт",-1,2),new n("ют",-1,1),new n("уют",34,2),new n("ят",-1,2),new n("ны",-1,1),new n("ены",37,2),new n("ть",-1,1),new n("ить",39,2),new n("ыть",39,2),new n("ешь",-1,1),new n("ишь",-1,2),new n("ю",-1,2),new n("ую",44,2)],v=[new n("а",-1,1),new n("ев",-1,1),new n("ов",-1,1),new n("е",-1,1),new n("ие",3,1),new n("ье",3,1),new n("и",-1,1),new n("еи",6,1),new n("ии",6,1),new n("ами",6,1),new n("ями",6,1),new n("иями",10,1),new n("й",-1,1),new n("ей",12,1),new n("ией",13,1),new n("ий",12,1),new n("ой",12,1),new n("ам",-1,1),new n("ем",-1,1),new n("ием",18,1),new n("ом",-1,1),new n("ям",-1,1),new n("иям",21,1),new n("о",-1,1),new n("у",-1,1),new n("ах",-1,1),new n("ях",-1,1),new n("иях",26,1),new n("ы",-1,1),new n("ь",-1,1),new n("ю",-1,1),new n("ию",30,1),new n("ью",30,1),new n("я",-1,1),new n("ия",33,1),new n("ья",33,1)],F=[new n("ост",-1,1),new n("ость",-1,1)],q=[new n("ейше",-1,1),new n("н",-1,2),new n("ейш",-1,1),new n("ь",-1,3)],S=[33,65,8,232],W=new r;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){return w(),W.cursor=W.limit,!(W.cursor=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursors||e>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor>1),f=0,l=o0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.sv.min.js b/1.13/assets/javascripts/lunr/min/lunr.sv.min.js new file mode 100644 index 000000000..3e5eb6400 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.sv.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Swedish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.ta.min.js b/1.13/assets/javascripts/lunr/min/lunr.ta.min.js new file mode 100644 index 000000000..a644bed22 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.ta.min.js @@ -0,0 +1 @@ +!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ta=function(){this.pipeline.reset(),this.pipeline.add(e.ta.trimmer,e.ta.stopWordFilter,e.ta.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ta.stemmer))},e.ta.wordCharacters="஀-உஊ-ஏஐ-ஙச-ட஠-னப-யர-ஹ஺-ிீ-௉ொ-௏ௐ-௙௚-௟௠-௩௪-௯௰-௹௺-௿a-zA-Za-zA-Z0-90-9",e.ta.trimmer=e.trimmerSupport.generateTrimmer(e.ta.wordCharacters),e.Pipeline.registerFunction(e.ta.trimmer,"trimmer-ta"),e.ta.stopWordFilter=e.generateStopWordFilter("அங்கு அங்கே அது அதை அந்த அவர் அவர்கள் அவள் அவன் அவை ஆக ஆகவே ஆகையால் ஆதலால் ஆதலினால் ஆனாலும் ஆனால் இங்கு இங்கே இது இதை இந்த இப்படி இவர் இவர்கள் இவள் இவன் இவை இவ்வளவு உனக்கு உனது உன் உன்னால் எங்கு எங்கே எது எதை எந்த எப்படி எவர் எவர்கள் எவள் எவன் எவை எவ்வளவு எனக்கு எனது எனவே என் என்ன என்னால் ஏது ஏன் தனது தன்னால் தானே தான் நாங்கள் நாம் நான் நீ நீங்கள்".split(" ")),e.ta.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.ta.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.ta.stemmer,"stemmer-ta"),e.Pipeline.registerFunction(e.ta.stopWordFilter,"stopWordFilter-ta")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.te.min.js b/1.13/assets/javascripts/lunr/min/lunr.te.min.js new file mode 100644 index 000000000..9fa7a93b9 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.te.min.js @@ -0,0 +1 @@ +!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.te=function(){this.pipeline.reset(),this.pipeline.add(e.te.trimmer,e.te.stopWordFilter,e.te.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.te.stemmer))},e.te.wordCharacters="ఀ-ఄఅ-ఔక-హా-ౌౕ-ౖౘ-ౚౠ-ౡౢ-ౣ౦-౯౸-౿఼ఽ్ౝ౷౤౥",e.te.trimmer=e.trimmerSupport.generateTrimmer(e.te.wordCharacters),e.Pipeline.registerFunction(e.te.trimmer,"trimmer-te"),e.te.stopWordFilter=e.generateStopWordFilter("అందరూ అందుబాటులో అడగండి అడగడం అడ్డంగా అనుగుణంగా అనుమతించు అనుమతిస్తుంది అయితే ఇప్పటికే ఉన్నారు ఎక్కడైనా ఎప్పుడు ఎవరైనా ఎవరో ఏ ఏదైనా ఏమైనప్పటికి ఒక ఒకరు కనిపిస్తాయి కాదు కూడా గా గురించి చుట్టూ చేయగలిగింది తగిన తర్వాత దాదాపు దూరంగా నిజంగా పై ప్రకారం ప్రక్కన మధ్య మరియు మరొక మళ్ళీ మాత్రమే మెచ్చుకో వద్ద వెంట వేరుగా వ్యతిరేకంగా సంబంధం".split(" ")),e.te.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.te.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.te.stemmer,"stemmer-te"),e.Pipeline.registerFunction(e.te.stopWordFilter,"stopWordFilter-te")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.th.min.js b/1.13/assets/javascripts/lunr/min/lunr.th.min.js new file mode 100644 index 000000000..dee3aac6e --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.th.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.th=function(){this.pipeline.reset(),this.pipeline.add(e.th.trimmer),r?this.tokenizer=e.th.tokenizer:(e.tokenizer&&(e.tokenizer=e.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.th.tokenizer))},e.th.wordCharacters="[฀-๿]",e.th.trimmer=e.trimmerSupport.generateTrimmer(e.th.wordCharacters),e.Pipeline.registerFunction(e.th.trimmer,"trimmer-th");var t=e.wordcut;t.init(),e.th.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t):t});var n=i.toString().replace(/^\s+/,"");return t.cut(n).split("|")}}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.tr.min.js b/1.13/assets/javascripts/lunr/min/lunr.tr.min.js new file mode 100644 index 000000000..563f6ec1f --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.tr.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Turkish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(r,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(r.lunr)}(this,function(){return function(r){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");r.tr=function(){this.pipeline.reset(),this.pipeline.add(r.tr.trimmer,r.tr.stopWordFilter,r.tr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(r.tr.stemmer))},r.tr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",r.tr.trimmer=r.trimmerSupport.generateTrimmer(r.tr.wordCharacters),r.Pipeline.registerFunction(r.tr.trimmer,"trimmer-tr"),r.tr.stemmer=function(){var i=r.stemmerSupport.Among,e=r.stemmerSupport.SnowballProgram,n=new function(){function r(r,i,e){for(;;){var n=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(r,i,e)){Dr.cursor=Dr.limit-n;break}if(Dr.cursor=Dr.limit-n,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function n(){var i,e;i=Dr.limit-Dr.cursor,r(Wr,97,305);for(var n=0;nDr.limit_backward&&(Dr.cursor--,e=Dr.limit-Dr.cursor,i()))?(Dr.cursor=Dr.limit-e,!0):(Dr.cursor=Dr.limit-n,r()?(Dr.cursor=Dr.limit-n,!1):(Dr.cursor=Dr.limit-n,!(Dr.cursor<=Dr.limit_backward)&&(Dr.cursor--,!!i()&&(Dr.cursor=Dr.limit-n,!0))))}function u(r){return t(r,function(){return Dr.in_grouping_b(Wr,97,305)})}function o(){return u(function(){return Dr.eq_s_b(1,"n")})}function s(){return u(function(){return Dr.eq_s_b(1,"s")})}function c(){return u(function(){return Dr.eq_s_b(1,"y")})}function l(){return t(function(){return Dr.in_grouping_b(Lr,105,305)},function(){return Dr.out_grouping_b(Wr,97,305)})}function a(){return Dr.find_among_b(ur,10)&&l()}function m(){return n()&&Dr.in_grouping_b(Lr,105,305)&&s()}function d(){return Dr.find_among_b(or,2)}function f(){return n()&&Dr.in_grouping_b(Lr,105,305)&&c()}function b(){return n()&&Dr.find_among_b(sr,4)}function w(){return n()&&Dr.find_among_b(cr,4)&&o()}function _(){return n()&&Dr.find_among_b(lr,2)&&c()}function k(){return n()&&Dr.find_among_b(ar,2)}function p(){return n()&&Dr.find_among_b(mr,4)}function g(){return n()&&Dr.find_among_b(dr,2)}function y(){return n()&&Dr.find_among_b(fr,4)}function z(){return n()&&Dr.find_among_b(br,2)}function v(){return n()&&Dr.find_among_b(wr,2)&&c()}function h(){return Dr.eq_s_b(2,"ki")}function q(){return n()&&Dr.find_among_b(_r,2)&&o()}function C(){return n()&&Dr.find_among_b(kr,4)&&c()}function P(){return n()&&Dr.find_among_b(pr,4)}function F(){return n()&&Dr.find_among_b(gr,4)&&c()}function S(){return Dr.find_among_b(yr,4)}function W(){return n()&&Dr.find_among_b(zr,2)}function L(){return n()&&Dr.find_among_b(vr,4)}function x(){return n()&&Dr.find_among_b(hr,8)}function A(){return Dr.find_among_b(qr,2)}function E(){return n()&&Dr.find_among_b(Cr,32)&&c()}function j(){return Dr.find_among_b(Pr,8)&&c()}function T(){return n()&&Dr.find_among_b(Fr,4)&&c()}function Z(){return Dr.eq_s_b(3,"ken")&&c()}function B(){var r=Dr.limit-Dr.cursor;return!(T()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,Z()))))}function D(){if(A()){var r=Dr.limit-Dr.cursor;if(S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T())return!1}return!0}function G(){if(W()){Dr.bra=Dr.cursor,Dr.slice_del();var r=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,x()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,T()||(Dr.cursor=Dr.limit-r)))),nr=!1,!1}return!0}function H(){if(!L())return!0;var r=Dr.limit-Dr.cursor;return!E()&&(Dr.cursor=Dr.limit-r,!j())}function I(){var r,i=Dr.limit-Dr.cursor;return!(S()||(Dr.cursor=Dr.limit-i,F()||(Dr.cursor=Dr.limit-i,P()||(Dr.cursor=Dr.limit-i,C()))))||(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,T()||(Dr.cursor=Dr.limit-r),!1)}function J(){var r,i=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,nr=!0,B()&&(Dr.cursor=Dr.limit-i,D()&&(Dr.cursor=Dr.limit-i,G()&&(Dr.cursor=Dr.limit-i,H()&&(Dr.cursor=Dr.limit-i,I()))))){if(Dr.cursor=Dr.limit-i,!x())return;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T()||(Dr.cursor=Dr.limit-r)}Dr.bra=Dr.cursor,Dr.slice_del()}function K(){var r,i,e,n;if(Dr.ket=Dr.cursor,h()){if(r=Dr.limit-Dr.cursor,p())return Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,a()&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))),!0;if(Dr.cursor=Dr.limit-r,w()){if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,e=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-e,!m()&&(Dr.cursor=Dr.limit-e,!K())))return!0;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}return!0}if(Dr.cursor=Dr.limit-r,g()){if(n=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-n,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-n,!K())return!1;return!0}}return!1}function M(r){if(Dr.ket=Dr.cursor,!g()&&(Dr.cursor=Dr.limit-r,!k()))return!1;var i=Dr.limit-Dr.cursor;if(d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-i,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-i,!K())return!1;return!0}function N(r){if(Dr.ket=Dr.cursor,!z()&&(Dr.cursor=Dr.limit-r,!b()))return!1;var i=Dr.limit-Dr.cursor;return!(!m()&&(Dr.cursor=Dr.limit-i,!d()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)}function O(){var r,i=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,!(!w()&&(Dr.cursor=Dr.limit-i,!v()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,!(!W()||(Dr.bra=Dr.cursor,Dr.slice_del(),!K()))||(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!(a()||(Dr.cursor=Dr.limit-r,m()||(Dr.cursor=Dr.limit-r,K())))||(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)))}function Q(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,!p()&&(Dr.cursor=Dr.limit-e,!f()&&(Dr.cursor=Dr.limit-e,!_())))return!1;if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,a())Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()||(Dr.cursor=Dr.limit-i);else if(Dr.cursor=Dr.limit-r,!W())return!0;return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,K(),!0}function R(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,W())return Dr.bra=Dr.cursor,Dr.slice_del(),void K();if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,q())if(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-r,!m())){if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!W())return;if(Dr.bra=Dr.cursor,Dr.slice_del(),!K())return}Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}else if(Dr.cursor=Dr.limit-e,!M(e)&&(Dr.cursor=Dr.limit-e,!N(e))){if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,y())return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,i=Dr.limit-Dr.cursor,void(a()?(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())):(Dr.cursor=Dr.limit-i,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,K())));if(Dr.cursor=Dr.limit-e,!O()){if(Dr.cursor=Dr.limit-e,d())return Dr.bra=Dr.cursor,void Dr.slice_del();Dr.cursor=Dr.limit-e,K()||(Dr.cursor=Dr.limit-e,Q()||(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,(a()||(Dr.cursor=Dr.limit-e,m()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))))}}}function U(){var r;if(Dr.ket=Dr.cursor,r=Dr.find_among_b(Sr,4))switch(Dr.bra=Dr.cursor,r){case 1:Dr.slice_from("p");break;case 2:Dr.slice_from("ç");break;case 3:Dr.slice_from("t");break;case 4:Dr.slice_from("k")}}function V(){for(;;){var r=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(Wr,97,305)){Dr.cursor=Dr.limit-r;break}if(Dr.cursor=Dr.limit-r,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function X(r,i,e){if(Dr.cursor=Dr.limit-r,V()){var n=Dr.limit-Dr.cursor;if(!Dr.eq_s_b(1,i)&&(Dr.cursor=Dr.limit-n,!Dr.eq_s_b(1,e)))return!0;Dr.cursor=Dr.limit-r;var t=Dr.cursor;return Dr.insert(Dr.cursor,Dr.cursor,e),Dr.cursor=t,!1}return!0}function Y(){var r=Dr.limit-Dr.cursor;(Dr.eq_s_b(1,"d")||(Dr.cursor=Dr.limit-r,Dr.eq_s_b(1,"g")))&&X(r,"a","ı")&&X(r,"e","i")&&X(r,"o","u")&&X(r,"ö","ü")}function $(){for(var r,i=Dr.cursor,e=2;;){for(r=Dr.cursor;!Dr.in_grouping(Wr,97,305);){if(Dr.cursor>=Dr.limit)return Dr.cursor=r,!(e>0)&&(Dr.cursor=i,!0);Dr.cursor++}e--}}function rr(r,i,e){for(;!Dr.eq_s(i,e);){if(Dr.cursor>=Dr.limit)return!0;Dr.cursor++}return(tr=i)!=Dr.limit||(Dr.cursor=r,!1)}function ir(){var r=Dr.cursor;return!rr(r,2,"ad")||(Dr.cursor=r,!rr(r,5,"soyad"))}function er(){var r=Dr.cursor;return!ir()&&(Dr.limit_backward=r,Dr.cursor=Dr.limit,Y(),Dr.cursor=Dr.limit,U(),!0)}var nr,tr,ur=[new i("m",-1,-1),new i("n",-1,-1),new i("miz",-1,-1),new i("niz",-1,-1),new i("muz",-1,-1),new i("nuz",-1,-1),new i("müz",-1,-1),new i("nüz",-1,-1),new i("mız",-1,-1),new i("nız",-1,-1)],or=[new i("leri",-1,-1),new i("ları",-1,-1)],sr=[new i("ni",-1,-1),new i("nu",-1,-1),new i("nü",-1,-1),new i("nı",-1,-1)],cr=[new i("in",-1,-1),new i("un",-1,-1),new i("ün",-1,-1),new i("ın",-1,-1)],lr=[new i("a",-1,-1),new i("e",-1,-1)],ar=[new i("na",-1,-1),new i("ne",-1,-1)],mr=[new i("da",-1,-1),new i("ta",-1,-1),new i("de",-1,-1),new i("te",-1,-1)],dr=[new i("nda",-1,-1),new i("nde",-1,-1)],fr=[new i("dan",-1,-1),new i("tan",-1,-1),new i("den",-1,-1),new i("ten",-1,-1)],br=[new i("ndan",-1,-1),new i("nden",-1,-1)],wr=[new i("la",-1,-1),new i("le",-1,-1)],_r=[new i("ca",-1,-1),new i("ce",-1,-1)],kr=[new i("im",-1,-1),new i("um",-1,-1),new i("üm",-1,-1),new i("ım",-1,-1)],pr=[new i("sin",-1,-1),new i("sun",-1,-1),new i("sün",-1,-1),new i("sın",-1,-1)],gr=[new i("iz",-1,-1),new i("uz",-1,-1),new i("üz",-1,-1),new i("ız",-1,-1)],yr=[new i("siniz",-1,-1),new i("sunuz",-1,-1),new i("sünüz",-1,-1),new i("sınız",-1,-1)],zr=[new i("lar",-1,-1),new i("ler",-1,-1)],vr=[new i("niz",-1,-1),new i("nuz",-1,-1),new i("nüz",-1,-1),new i("nız",-1,-1)],hr=[new i("dir",-1,-1),new i("tir",-1,-1),new i("dur",-1,-1),new i("tur",-1,-1),new i("dür",-1,-1),new i("tür",-1,-1),new i("dır",-1,-1),new i("tır",-1,-1)],qr=[new i("casına",-1,-1),new i("cesine",-1,-1)],Cr=[new i("di",-1,-1),new i("ti",-1,-1),new i("dik",-1,-1),new i("tik",-1,-1),new i("duk",-1,-1),new i("tuk",-1,-1),new i("dük",-1,-1),new i("tük",-1,-1),new i("dık",-1,-1),new i("tık",-1,-1),new i("dim",-1,-1),new i("tim",-1,-1),new i("dum",-1,-1),new i("tum",-1,-1),new i("düm",-1,-1),new i("tüm",-1,-1),new i("dım",-1,-1),new i("tım",-1,-1),new i("din",-1,-1),new i("tin",-1,-1),new i("dun",-1,-1),new i("tun",-1,-1),new i("dün",-1,-1),new i("tün",-1,-1),new i("dın",-1,-1),new i("tın",-1,-1),new i("du",-1,-1),new i("tu",-1,-1),new i("dü",-1,-1),new i("tü",-1,-1),new i("dı",-1,-1),new i("tı",-1,-1)],Pr=[new i("sa",-1,-1),new i("se",-1,-1),new i("sak",-1,-1),new i("sek",-1,-1),new i("sam",-1,-1),new i("sem",-1,-1),new i("san",-1,-1),new i("sen",-1,-1)],Fr=[new i("miş",-1,-1),new i("muş",-1,-1),new i("müş",-1,-1),new i("mış",-1,-1)],Sr=[new i("b",-1,1),new i("c",-1,2),new i("d",-1,3),new i("ğ",-1,4)],Wr=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,8,0,0,0,0,0,0,1],Lr=[1,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,1],xr=[1,64,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],Ar=[17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130],Er=[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],jr=[17],Tr=[65],Zr=[65],Br=[["a",xr,97,305],["e",Ar,101,252],["ı",Er,97,305],["i",jr,101,105],["o",Tr,111,117],["ö",Zr,246,252],["u",Tr,111,117]],Dr=new e;this.setCurrent=function(r){Dr.setCurrent(r)},this.getCurrent=function(){return Dr.getCurrent()},this.stem=function(){return!!($()&&(Dr.limit_backward=Dr.cursor,Dr.cursor=Dr.limit,J(),Dr.cursor=Dr.limit,nr&&(R(),Dr.cursor=Dr.limit_backward,er())))}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.tr.stemmer,"stemmer-tr"),r.tr.stopWordFilter=r.generateStopWordFilter("acaba altmış altı ama ancak arada aslında ayrıca bana bazı belki ben benden beni benim beri beş bile bin bir biri birkaç birkez birçok birşey birşeyi biz bizden bize bizi bizim bu buna bunda bundan bunlar bunları bunların bunu bunun burada böyle böylece da daha dahi de defa değil diye diğer doksan dokuz dolayı dolayısıyla dört edecek eden ederek edilecek ediliyor edilmesi ediyor elli en etmesi etti ettiği ettiğini eğer gibi göre halen hangi hatta hem henüz hep hepsi her herhangi herkesin hiç hiçbir iki ile ilgili ise itibaren itibariyle için işte kadar karşın katrilyon kendi kendilerine kendini kendisi kendisine kendisini kez ki kim kimden kime kimi kimse kırk milyar milyon mu mü mı nasıl ne neden nedenle nerde nerede nereye niye niçin o olan olarak oldu olduklarını olduğu olduğunu olmadı olmadığı olmak olması olmayan olmaz olsa olsun olup olur olursa oluyor on ona ondan onlar onlardan onları onların onu onun otuz oysa pek rağmen sadece sanki sekiz seksen sen senden seni senin siz sizden sizi sizin tarafından trilyon tüm var vardı ve veya ya yani yapacak yapmak yaptı yaptıkları yaptığı yaptığını yapılan yapılması yapıyor yedi yerine yetmiş yine yirmi yoksa yüz zaten çok çünkü öyle üzere üç şey şeyden şeyi şeyler şu şuna şunda şundan şunları şunu şöyle".split(" ")),r.Pipeline.registerFunction(r.tr.stopWordFilter,"stopWordFilter-tr")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.vi.min.js b/1.13/assets/javascripts/lunr/min/lunr.vi.min.js new file mode 100644 index 000000000..22aed28c4 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.vi.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/min/lunr.zh.min.js b/1.13/assets/javascripts/lunr/min/lunr.zh.min.js new file mode 100644 index 000000000..fda66e9c5 --- /dev/null +++ b/1.13/assets/javascripts/lunr/min/lunr.zh.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r(require("@node-rs/jieba")):r()(e.lunr)}(this,function(e){return function(r,t){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==r.version[0];r.zh=function(){this.pipeline.reset(),this.pipeline.add(r.zh.trimmer,r.zh.stopWordFilter,r.zh.stemmer),i?this.tokenizer=r.zh.tokenizer:(r.tokenizer&&(r.tokenizer=r.zh.tokenizer),this.tokenizerFn&&(this.tokenizerFn=r.zh.tokenizer))},r.zh.tokenizer=function(n){if(!arguments.length||null==n||void 0==n)return[];if(Array.isArray(n))return n.map(function(e){return i?new r.Token(e.toLowerCase()):e.toLowerCase()});t&&e.load(t);var o=n.toString().trim().toLowerCase(),s=[];e.cut(o,!0).forEach(function(e){s=s.concat(e.split(" "))}),s=s.filter(function(e){return!!e});var u=0;return s.map(function(e,t){if(i){var n=o.indexOf(e,u),s={};return s.position=[n,e.length],s.index=t,u=n,new r.Token(e,s)}return e})},r.zh.wordCharacters="\\w一-龥",r.zh.trimmer=r.trimmerSupport.generateTrimmer(r.zh.wordCharacters),r.Pipeline.registerFunction(r.zh.trimmer,"trimmer-zh"),r.zh.stemmer=function(){return function(e){return e}}(),r.Pipeline.registerFunction(r.zh.stemmer,"stemmer-zh"),r.zh.stopWordFilter=r.generateStopWordFilter("的 一 不 在 人 有 是 为 為 以 于 於 上 他 而 后 後 之 来 來 及 了 因 下 可 到 由 这 這 与 與 也 此 但 并 並 个 個 其 已 无 無 小 我 们 們 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 當 从 從 得 打 凡 儿 兒 尔 爾 该 該 各 给 給 跟 和 何 还 還 即 几 幾 既 看 据 據 距 靠 啦 另 么 麽 每 嘛 拿 哪 您 凭 憑 且 却 卻 让 讓 仍 啥 如 若 使 谁 誰 虽 雖 随 隨 同 所 她 哇 嗡 往 些 向 沿 哟 喲 用 咱 则 則 怎 曾 至 致 着 著 诸 諸 自".split(" ")),r.Pipeline.registerFunction(r.zh.stopWordFilter,"stopWordFilter-zh")}}); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/tinyseg.js b/1.13/assets/javascripts/lunr/tinyseg.js new file mode 100644 index 000000000..167fa6dd6 --- /dev/null +++ b/1.13/assets/javascripts/lunr/tinyseg.js @@ -0,0 +1,206 @@ +/** + * export the module via AMD, CommonJS or as a browser global + * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js + */ +;(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(factory) + } else if (typeof exports === 'object') { + /** + * Node. Does not work with strict CommonJS, but + * only CommonJS-like environments that support module.exports, + * like Node. + */ + module.exports = factory() + } else { + // Browser globals (root is window) + factory()(root.lunr); + } +}(this, function () { + /** + * Just return a value to define the module export. + * This example returns an object, but the module + * can return a function as the exported value. + */ + + return function(lunr) { + // TinySegmenter 0.1 -- Super compact Japanese tokenizer in Javascript + // (c) 2008 Taku Kudo + // TinySegmenter is freely distributable under the terms of a new BSD licence. + // For details, see http://chasen.org/~taku/software/TinySegmenter/LICENCE.txt + + function TinySegmenter() { + var patterns = { + "[一二三四五六七八九十百千万億兆]":"M", + "[一-龠々〆ヵヶ]":"H", + "[ぁ-ん]":"I", + "[ァ-ヴーア-ン゙ー]":"K", + "[a-zA-Za-zA-Z]":"A", + "[0-90-9]":"N" + } + this.chartype_ = []; + for (var i in patterns) { + var regexp = new RegExp(i); + this.chartype_.push([regexp, patterns[i]]); + } + + this.BIAS__ = -332 + this.BC1__ = {"HH":6,"II":2461,"KH":406,"OH":-1378}; + this.BC2__ = {"AA":-3267,"AI":2744,"AN":-878,"HH":-4070,"HM":-1711,"HN":4012,"HO":3761,"IA":1327,"IH":-1184,"II":-1332,"IK":1721,"IO":5492,"KI":3831,"KK":-8741,"MH":-3132,"MK":3334,"OO":-2920}; + this.BC3__ = {"HH":996,"HI":626,"HK":-721,"HN":-1307,"HO":-836,"IH":-301,"KK":2762,"MK":1079,"MM":4034,"OA":-1652,"OH":266}; + this.BP1__ = {"BB":295,"OB":304,"OO":-125,"UB":352}; + this.BP2__ = {"BO":60,"OO":-1762}; + this.BQ1__ = {"BHH":1150,"BHM":1521,"BII":-1158,"BIM":886,"BMH":1208,"BNH":449,"BOH":-91,"BOO":-2597,"OHI":451,"OIH":-296,"OKA":1851,"OKH":-1020,"OKK":904,"OOO":2965}; + this.BQ2__ = {"BHH":118,"BHI":-1159,"BHM":466,"BIH":-919,"BKK":-1720,"BKO":864,"OHH":-1139,"OHM":-181,"OIH":153,"UHI":-1146}; + this.BQ3__ = {"BHH":-792,"BHI":2664,"BII":-299,"BKI":419,"BMH":937,"BMM":8335,"BNN":998,"BOH":775,"OHH":2174,"OHM":439,"OII":280,"OKH":1798,"OKI":-793,"OKO":-2242,"OMH":-2402,"OOO":11699}; + this.BQ4__ = {"BHH":-3895,"BIH":3761,"BII":-4654,"BIK":1348,"BKK":-1806,"BMI":-3385,"BOO":-12396,"OAH":926,"OHH":266,"OHK":-2036,"ONN":-973}; + this.BW1__ = {",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682}; + this.BW2__ = {"..":-11822,"11":-669,"――":-5730,"−−":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"11":-669}; + this.BW3__ = {"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1000,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990}; + this.TC1__ = {"AAA":1093,"HHH":1029,"HHM":580,"HII":998,"HOH":-390,"HOM":-331,"IHI":1169,"IOH":-142,"IOI":-1015,"IOM":467,"MMH":187,"OOI":-1832}; + this.TC2__ = {"HHO":2088,"HII":-1023,"HMM":-1154,"IHI":-1965,"KKH":703,"OII":-2649}; + this.TC3__ = {"AAA":-294,"HHH":346,"HHI":-341,"HII":-1088,"HIK":731,"HOH":-1486,"IHH":128,"IHI":-3041,"IHO":-1935,"IIH":-825,"IIM":-1035,"IOI":-542,"KHH":-1216,"KKA":491,"KKH":-1217,"KOK":-1009,"MHH":-2694,"MHM":-457,"MHO":123,"MMH":-471,"NNH":-1689,"NNO":662,"OHO":-3393}; + this.TC4__ = {"HHH":-203,"HHI":1344,"HHK":365,"HHM":-122,"HHN":182,"HHO":669,"HIH":804,"HII":679,"HOH":446,"IHH":695,"IHO":-2324,"IIH":321,"III":1497,"IIO":656,"IOO":54,"KAK":4845,"KKA":3386,"KKK":3065,"MHH":-405,"MHI":201,"MMH":-241,"MMM":661,"MOM":841}; + this.TQ1__ = {"BHHH":-227,"BHHI":316,"BHIH":-132,"BIHH":60,"BIII":1595,"BNHH":-744,"BOHH":225,"BOOO":-908,"OAKK":482,"OHHH":281,"OHIH":249,"OIHI":200,"OIIH":-68}; + this.TQ2__ = {"BIHH":-1401,"BIII":-1033,"BKAK":-543,"BOOO":-5591}; + this.TQ3__ = {"BHHH":478,"BHHM":-1073,"BHIH":222,"BHII":-504,"BIIH":-116,"BIII":-105,"BMHI":-863,"BMHM":-464,"BOMH":620,"OHHH":346,"OHHI":1729,"OHII":997,"OHMH":481,"OIHH":623,"OIIH":1344,"OKAK":2792,"OKHH":587,"OKKA":679,"OOHH":110,"OOII":-685}; + this.TQ4__ = {"BHHH":-721,"BHHM":-3604,"BHII":-966,"BIIH":-607,"BIII":-2181,"OAAA":-2763,"OAKK":180,"OHHH":-294,"OHHI":2446,"OHHO":480,"OHIH":-1573,"OIHH":1935,"OIHI":-493,"OIIH":626,"OIII":-4007,"OKAK":-8156}; + this.TW1__ = {"につい":-4681,"東京都":2026}; + this.TW2__ = {"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216}; + this.TW3__ = {"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287}; + this.TW4__ = {"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865}; + this.UC1__ = {"A":484,"K":93,"M":645,"O":-505}; + this.UC2__ = {"A":819,"H":1059,"I":409,"M":3987,"N":5775,"O":646}; + this.UC3__ = {"A":-1370,"I":2311}; + this.UC4__ = {"A":-2643,"H":1809,"I":-1032,"K":-3450,"M":3565,"N":3876,"O":6646}; + this.UC5__ = {"H":313,"I":-1238,"K":-799,"M":539,"O":-831}; + this.UC6__ = {"H":-506,"I":-253,"K":87,"M":247,"O":-387}; + this.UP1__ = {"O":-214}; + this.UP2__ = {"B":69,"O":935}; + this.UP3__ = {"B":189}; + this.UQ1__ = {"BH":21,"BI":-12,"BK":-99,"BN":142,"BO":-56,"OH":-95,"OI":477,"OK":410,"OO":-2422}; + this.UQ2__ = {"BH":216,"BI":113,"OK":1759}; + this.UQ3__ = {"BA":-479,"BH":42,"BI":1913,"BK":-7198,"BM":3160,"BN":6427,"BO":14761,"OI":-827,"ON":-3212}; + this.UW1__ = {",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135}; + this.UW2__ = {",":-829,"、":-829,"〇":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568}; + this.UW3__ = {",":4889,"1":-800,"−":-1723,"、":4889,"々":-2311,"〇":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"1":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278}; + this.UW4__ = {",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"〇":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1000,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637}; + this.UW5__ = {",":465,".":-299,"1":-514,"E2":-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"1":-514,"E2":-32768,"「":363,"イ":241,"ル":451,"ン":-343}; + this.UW6__ = {",":227,".":808,"1":-270,"E1":306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"1":-270,"E1":306,"ル":-673,"ン":-496}; + + return this; + } + TinySegmenter.prototype.ctype_ = function(str) { + for (var i in this.chartype_) { + if (str.match(this.chartype_[i][0])) { + return this.chartype_[i][1]; + } + } + return "O"; + } + + TinySegmenter.prototype.ts_ = function(v) { + if (v) { return v; } + return 0; + } + + TinySegmenter.prototype.segment = function(input) { + if (input == null || input == undefined || input == "") { + return []; + } + var result = []; + var seg = ["B3","B2","B1"]; + var ctype = ["O","O","O"]; + var o = input.split(""); + for (i = 0; i < o.length; ++i) { + seg.push(o[i]); + ctype.push(this.ctype_(o[i])) + } + seg.push("E1"); + seg.push("E2"); + seg.push("E3"); + ctype.push("O"); + ctype.push("O"); + ctype.push("O"); + var word = seg[3]; + var p1 = "U"; + var p2 = "U"; + var p3 = "U"; + for (var i = 4; i < seg.length - 3; ++i) { + var score = this.BIAS__; + var w1 = seg[i-3]; + var w2 = seg[i-2]; + var w3 = seg[i-1]; + var w4 = seg[i]; + var w5 = seg[i+1]; + var w6 = seg[i+2]; + var c1 = ctype[i-3]; + var c2 = ctype[i-2]; + var c3 = ctype[i-1]; + var c4 = ctype[i]; + var c5 = ctype[i+1]; + var c6 = ctype[i+2]; + score += this.ts_(this.UP1__[p1]); + score += this.ts_(this.UP2__[p2]); + score += this.ts_(this.UP3__[p3]); + score += this.ts_(this.BP1__[p1 + p2]); + score += this.ts_(this.BP2__[p2 + p3]); + score += this.ts_(this.UW1__[w1]); + score += this.ts_(this.UW2__[w2]); + score += this.ts_(this.UW3__[w3]); + score += this.ts_(this.UW4__[w4]); + score += this.ts_(this.UW5__[w5]); + score += this.ts_(this.UW6__[w6]); + score += this.ts_(this.BW1__[w2 + w3]); + score += this.ts_(this.BW2__[w3 + w4]); + score += this.ts_(this.BW3__[w4 + w5]); + score += this.ts_(this.TW1__[w1 + w2 + w3]); + score += this.ts_(this.TW2__[w2 + w3 + w4]); + score += this.ts_(this.TW3__[w3 + w4 + w5]); + score += this.ts_(this.TW4__[w4 + w5 + w6]); + score += this.ts_(this.UC1__[c1]); + score += this.ts_(this.UC2__[c2]); + score += this.ts_(this.UC3__[c3]); + score += this.ts_(this.UC4__[c4]); + score += this.ts_(this.UC5__[c5]); + score += this.ts_(this.UC6__[c6]); + score += this.ts_(this.BC1__[c2 + c3]); + score += this.ts_(this.BC2__[c3 + c4]); + score += this.ts_(this.BC3__[c4 + c5]); + score += this.ts_(this.TC1__[c1 + c2 + c3]); + score += this.ts_(this.TC2__[c2 + c3 + c4]); + score += this.ts_(this.TC3__[c3 + c4 + c5]); + score += this.ts_(this.TC4__[c4 + c5 + c6]); + // score += this.ts_(this.TC5__[c4 + c5 + c6]); + score += this.ts_(this.UQ1__[p1 + c1]); + score += this.ts_(this.UQ2__[p2 + c2]); + score += this.ts_(this.UQ3__[p3 + c3]); + score += this.ts_(this.BQ1__[p2 + c2 + c3]); + score += this.ts_(this.BQ2__[p2 + c3 + c4]); + score += this.ts_(this.BQ3__[p3 + c2 + c3]); + score += this.ts_(this.BQ4__[p3 + c3 + c4]); + score += this.ts_(this.TQ1__[p2 + c1 + c2 + c3]); + score += this.ts_(this.TQ2__[p2 + c2 + c3 + c4]); + score += this.ts_(this.TQ3__[p3 + c1 + c2 + c3]); + score += this.ts_(this.TQ4__[p3 + c2 + c3 + c4]); + var p = "O"; + if (score > 0) { + result.push(word); + word = ""; + p = "B"; + } + p1 = p2; + p2 = p3; + p3 = p; + word += seg[i]; + } + result.push(word); + + return result; + } + + lunr.TinySegmenter = TinySegmenter; + }; + +})); \ No newline at end of file diff --git a/1.13/assets/javascripts/lunr/wordcut.js b/1.13/assets/javascripts/lunr/wordcut.js new file mode 100644 index 000000000..0d898c9ed --- /dev/null +++ b/1.13/assets/javascripts/lunr/wordcut.js @@ -0,0 +1,6708 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.lunr || (g.lunr = {})).wordcut = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1; + }) + this.addWords(words, false) + } + if(finalize){ + this.finalizeDict(); + } + }, + + dictSeek: function (l, r, ch, strOffset, pos) { + var ans = null; + while (l <= r) { + var m = Math.floor((l + r) / 2), + dict_item = this.dict[m], + len = dict_item.length; + if (len <= strOffset) { + l = m + 1; + } else { + var ch_ = dict_item[strOffset]; + if (ch_ < ch) { + l = m + 1; + } else if (ch_ > ch) { + r = m - 1; + } else { + ans = m; + if (pos == LEFT) { + r = m - 1; + } else { + l = m + 1; + } + } + } + } + return ans; + }, + + isFinal: function (acceptor) { + return this.dict[acceptor.l].length == acceptor.strOffset; + }, + + createAcceptor: function () { + return { + l: 0, + r: this.dict.length - 1, + strOffset: 0, + isFinal: false, + dict: this, + transit: function (ch) { + return this.dict.transit(this, ch); + }, + isError: false, + tag: "DICT", + w: 1, + type: "DICT" + }; + }, + + transit: function (acceptor, ch) { + var l = this.dictSeek(acceptor.l, + acceptor.r, + ch, + acceptor.strOffset, + LEFT); + if (l !== null) { + var r = this.dictSeek(l, + acceptor.r, + ch, + acceptor.strOffset, + RIGHT); + acceptor.l = l; + acceptor.r = r; + acceptor.strOffset++; + acceptor.isFinal = this.isFinal(acceptor); + } else { + acceptor.isError = true; + } + return acceptor; + }, + + sortuniq: function(a){ + return a.sort().filter(function(item, pos, arr){ + return !pos || item != arr[pos - 1]; + }) + }, + + flatten: function(a){ + //[[1,2],[3]] -> [1,2,3] + return [].concat.apply([], a); + } +}; +module.exports = WordcutDict; + +}).call(this,"/dist/tmp") +},{"glob":16,"path":22}],3:[function(require,module,exports){ +var WordRule = { + createAcceptor: function(tag) { + if (tag["WORD_RULE"]) + return null; + + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + var lch = ch.toLowerCase(); + if (lch >= "a" && lch <= "z") { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "WORD_RULE", + type: "WORD_RULE", + w: 1}; + } +}; + +var NumberRule = { + createAcceptor: function(tag) { + if (tag["NUMBER_RULE"]) + return null; + + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (ch >= "0" && ch <= "9") { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "NUMBER_RULE", + type: "NUMBER_RULE", + w: 1}; + } +}; + +var SpaceRule = { + tag: "SPACE_RULE", + createAcceptor: function(tag) { + + if (tag["SPACE_RULE"]) + return null; + + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (ch == " " || ch == "\t" || ch == "\r" || ch == "\n" || + ch == "\u00A0" || ch=="\u2003"//nbsp and emsp + ) { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: SpaceRule.tag, + w: 1, + type: "SPACE_RULE"}; + } +} + +var SingleSymbolRule = { + tag: "SINSYM", + createAcceptor: function(tag) { + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (this.strOffset == 0 && ch.match(/^[\@\(\)\/\,\-\."`]$/)) { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "SINSYM", + w: 1, + type: "SINSYM"}; + } +} + + +var LatinRules = [WordRule, SpaceRule, SingleSymbolRule, NumberRule]; + +module.exports = LatinRules; + +},{}],4:[function(require,module,exports){ +var _ = require("underscore") + , WordcutCore = require("./wordcut_core"); +var PathInfoBuilder = { + + /* + buildByPartAcceptors: function(path, acceptors, i) { + var + var genInfos = partAcceptors.reduce(function(genInfos, acceptor) { + + }, []); + + return genInfos; + } + */ + + buildByAcceptors: function(path, finalAcceptors, i) { + var self = this; + var infos = finalAcceptors.map(function(acceptor) { + var p = i - acceptor.strOffset + 1 + , _info = path[p]; + + var info = {p: p, + mw: _info.mw + (acceptor.mw === undefined ? 0 : acceptor.mw), + w: acceptor.w + _info.w, + unk: (acceptor.unk ? acceptor.unk : 0) + _info.unk, + type: acceptor.type}; + + if (acceptor.type == "PART") { + for(var j = p + 1; j <= i; j++) { + path[j].merge = p; + } + info.merge = p; + } + + return info; + }); + return infos.filter(function(info) { return info; }); + }, + + fallback: function(path, leftBoundary, text, i) { + var _info = path[leftBoundary]; + if (text[i].match(/[\u0E48-\u0E4E]/)) { + if (leftBoundary != 0) + leftBoundary = path[leftBoundary].p; + return {p: leftBoundary, + mw: 0, + w: 1 + _info.w, + unk: 1 + _info.unk, + type: "UNK"}; +/* } else if(leftBoundary > 0 && path[leftBoundary].type !== "UNK") { + leftBoundary = path[leftBoundary].p; + return {p: leftBoundary, + w: 1 + _info.w, + unk: 1 + _info.unk, + type: "UNK"}; */ + } else { + return {p: leftBoundary, + mw: _info.mw, + w: 1 + _info.w, + unk: 1 + _info.unk, + type: "UNK"}; + } + }, + + build: function(path, finalAcceptors, i, leftBoundary, text) { + var basicPathInfos = this.buildByAcceptors(path, finalAcceptors, i); + if (basicPathInfos.length > 0) { + return basicPathInfos; + } else { + return [this.fallback(path, leftBoundary, text, i)]; + } + } +}; + +module.exports = function() { + return _.clone(PathInfoBuilder); +} + +},{"./wordcut_core":8,"underscore":25}],5:[function(require,module,exports){ +var _ = require("underscore"); + + +var PathSelector = { + selectPath: function(paths) { + var path = paths.reduce(function(selectedPath, path) { + if (selectedPath == null) { + return path; + } else { + if (path.unk < selectedPath.unk) + return path; + if (path.unk == selectedPath.unk) { + if (path.mw < selectedPath.mw) + return path + if (path.mw == selectedPath.mw) { + if (path.w < selectedPath.w) + return path; + } + } + return selectedPath; + } + }, null); + return path; + }, + + createPath: function() { + return [{p:null, w:0, unk:0, type: "INIT", mw:0}]; + } +}; + +module.exports = function() { + return _.clone(PathSelector); +}; + +},{"underscore":25}],6:[function(require,module,exports){ +function isMatch(pat, offset, ch) { + if (pat.length <= offset) + return false; + var _ch = pat[offset]; + return _ch == ch || + (_ch.match(/[กข]/) && ch.match(/[ก-ฮ]/)) || + (_ch.match(/[มบ]/) && ch.match(/[ก-ฮ]/)) || + (_ch.match(/\u0E49/) && ch.match(/[\u0E48-\u0E4B]/)); +} + +var Rule0 = { + pat: "เหก็ม", + createAcceptor: function(tag) { + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (isMatch(Rule0.pat, this.strOffset,ch)) { + this.isFinal = (this.strOffset + 1 == Rule0.pat.length); + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "THAI_RULE", + type: "THAI_RULE", + w: 1}; + } +}; + +var PartRule = { + createAcceptor: function(tag) { + return {strOffset: 0, + patterns: [ + "แก", "เก", "ก้", "กก์", "กา", "กี", "กิ", "กืก" + ], + isFinal: false, + transit: function(ch) { + var offset = this.strOffset; + this.patterns = this.patterns.filter(function(pat) { + return isMatch(pat, offset, ch); + }); + + if (this.patterns.length > 0) { + var len = 1 + offset; + this.isFinal = this.patterns.some(function(pat) { + return pat.length == len; + }); + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "PART", + type: "PART", + unk: 1, + w: 1}; + } +}; + +var ThaiRules = [Rule0, PartRule]; + +module.exports = ThaiRules; + +},{}],7:[function(require,module,exports){ +var sys = require("sys") + , WordcutDict = require("./dict") + , WordcutCore = require("./wordcut_core") + , PathInfoBuilder = require("./path_info_builder") + , PathSelector = require("./path_selector") + , Acceptors = require("./acceptors") + , latinRules = require("./latin_rules") + , thaiRules = require("./thai_rules") + , _ = require("underscore"); + + +var Wordcut = Object.create(WordcutCore); +Wordcut.defaultPathInfoBuilder = PathInfoBuilder; +Wordcut.defaultPathSelector = PathSelector; +Wordcut.defaultAcceptors = Acceptors; +Wordcut.defaultLatinRules = latinRules; +Wordcut.defaultThaiRules = thaiRules; +Wordcut.defaultDict = WordcutDict; + + +Wordcut.initNoDict = function(dict_path) { + var self = this; + self.pathInfoBuilder = new self.defaultPathInfoBuilder; + self.pathSelector = new self.defaultPathSelector; + self.acceptors = new self.defaultAcceptors; + self.defaultLatinRules.forEach(function(rule) { + self.acceptors.creators.push(rule); + }); + self.defaultThaiRules.forEach(function(rule) { + self.acceptors.creators.push(rule); + }); +}; + +Wordcut.init = function(dict_path, withDefault, additionalWords) { + withDefault = withDefault || false; + this.initNoDict(); + var dict = _.clone(this.defaultDict); + dict.init(dict_path, withDefault, additionalWords); + this.acceptors.creators.push(dict); +}; + +module.exports = Wordcut; + +},{"./acceptors":1,"./dict":2,"./latin_rules":3,"./path_info_builder":4,"./path_selector":5,"./thai_rules":6,"./wordcut_core":8,"sys":28,"underscore":25}],8:[function(require,module,exports){ +var WordcutCore = { + + buildPath: function(text) { + var self = this + , path = self.pathSelector.createPath() + , leftBoundary = 0; + self.acceptors.reset(); + for (var i = 0; i < text.length; i++) { + var ch = text[i]; + self.acceptors.transit(ch); + + var possiblePathInfos = self + .pathInfoBuilder + .build(path, + self.acceptors.getFinalAcceptors(), + i, + leftBoundary, + text); + var selectedPath = self.pathSelector.selectPath(possiblePathInfos) + + path.push(selectedPath); + if (selectedPath.type !== "UNK") { + leftBoundary = i; + } + } + return path; + }, + + pathToRanges: function(path) { + var e = path.length - 1 + , ranges = []; + + while (e > 0) { + var info = path[e] + , s = info.p; + + if (info.merge !== undefined && ranges.length > 0) { + var r = ranges[ranges.length - 1]; + r.s = info.merge; + s = r.s; + } else { + ranges.push({s:s, e:e}); + } + e = s; + } + return ranges.reverse(); + }, + + rangesToText: function(text, ranges, delimiter) { + return ranges.map(function(r) { + return text.substring(r.s, r.e); + }).join(delimiter); + }, + + cut: function(text, delimiter) { + var path = this.buildPath(text) + , ranges = this.pathToRanges(path); + return this + .rangesToText(text, ranges, + (delimiter === undefined ? "|" : delimiter)); + }, + + cutIntoRanges: function(text, noText) { + var path = this.buildPath(text) + , ranges = this.pathToRanges(path); + + if (!noText) { + ranges.forEach(function(r) { + r.text = text.substring(r.s, r.e); + }); + } + return ranges; + }, + + cutIntoArray: function(text) { + var path = this.buildPath(text) + , ranges = this.pathToRanges(path); + + return ranges.map(function(r) { + return text.substring(r.s, r.e) + }); + } +}; + +module.exports = WordcutCore; + +},{}],9:[function(require,module,exports){ +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// when used in node, this will actually load the util module we depend on +// versus loading the builtin util module as happens otherwise +// this is a bug in node module loading as far as I am concerned +var util = require('util/'); + +var pSlice = Array.prototype.slice; +var hasOwn = Object.prototype.hasOwnProperty; + +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = module.exports = ok; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({ message: message, +// actual: actual, +// expected: expected }) + +assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError'; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + if (options.message) { + this.message = options.message; + this.generatedMessage = false; + } else { + this.message = getMessage(this); + this.generatedMessage = true; + } + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } + else { + // non v8 browsers so we can have a stacktrace + var err = new Error(); + if (err.stack) { + var out = err.stack; + + // try to strip useless frames + var fn_name = stackStartFunction.name; + var idx = out.indexOf('\n' + fn_name); + if (idx >= 0) { + // once we have located the function frame + // we need to strip out everything before it (and its line) + var next_line = out.indexOf('\n', idx + 1); + out = out.substring(next_line + 1); + } + + this.stack = out; + } + } +}; + +// assert.AssertionError instanceof Error +util.inherits(assert.AssertionError, Error); + +function replacer(key, value) { + if (util.isUndefined(value)) { + return '' + value; + } + if (util.isNumber(value) && !isFinite(value)) { + return value.toString(); + } + if (util.isFunction(value) || util.isRegExp(value)) { + return value.toString(); + } + return value; +} + +function truncate(s, n) { + if (util.isString(s)) { + return s.length < n ? s : s.slice(0, n); + } else { + return s; + } +} + +function getMessage(self) { + return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + + self.operator + ' ' + + truncate(JSON.stringify(self.expected, replacer), 128); +} + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, !!guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok); +} +assert.ok = ok; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, '==', assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual); + } +}; + +function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (util.isBuffer(actual) && util.isBuffer(expected)) { + if (actual.length != expected.length) return false; + + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) return false; + } + + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime(); + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase; + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (!util.isObject(actual) && !util.isObject(expected)) { + return actual == expected; + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b) { + if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) + return false; + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + // if one is a primitive, the other must be same + if (util.isPrimitive(a) || util.isPrimitive(b)) { + return a === b; + } + var aIsArgs = isArguments(a), + bIsArgs = isArguments(b); + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) + return false; + if (aIsArgs) { + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + var ka = objectKeys(a), + kb = objectKeys(b), + key, i; + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key])) return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected)) { + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); + } +}; + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as +// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (Object.prototype.toString.call(expected) == '[object RegExp]') { + return expected.test(actual); + } else if (actual instanceof expected) { + return true; + } else if (expected.call({}, actual) === true) { + return true; + } + + return false; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (util.isString(expected)) { + message = expected; + expected = null; + } + + try { + block(); + } catch (e) { + actual = e; + } + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message); + } + + if (!shouldThrow && expectedException(actual, expected)) { + fail(actual, expected, 'Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [true].concat(pSlice.call(arguments))); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function(err) { if (err) {throw err;}}; + +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + if (hasOwn.call(obj, key)) keys.push(key); + } + return keys; +}; + +},{"util/":28}],10:[function(require,module,exports){ +'use strict'; +module.exports = balanced; +function balanced(a, b, str) { + if (a instanceof RegExp) a = maybeMatch(a, str); + if (b instanceof RegExp) b = maybeMatch(b, str); + + var r = range(a, b, str); + + return r && { + start: r[0], + end: r[1], + pre: str.slice(0, r[0]), + body: str.slice(r[0] + a.length, r[1]), + post: str.slice(r[1] + b.length) + }; +} + +function maybeMatch(reg, str) { + var m = str.match(reg); + return m ? m[0] : null; +} + +balanced.range = range; +function range(a, b, str) { + var begs, beg, left, right, result; + var ai = str.indexOf(a); + var bi = str.indexOf(b, ai + 1); + var i = ai; + + if (ai >= 0 && bi > 0) { + begs = []; + left = str.length; + + while (i >= 0 && !result) { + if (i == ai) { + begs.push(i); + ai = str.indexOf(a, i + 1); + } else if (begs.length == 1) { + result = [ begs.pop(), bi ]; + } else { + beg = begs.pop(); + if (beg < left) { + left = beg; + right = bi; + } + + bi = str.indexOf(b, i + 1); + } + + i = ai < bi && ai >= 0 ? ai : bi; + } + + if (begs.length) { + result = [ left, right ]; + } + } + + return result; +} + +},{}],11:[function(require,module,exports){ +var concatMap = require('concat-map'); +var balanced = require('balanced-match'); + +module.exports = expandTop; + +var escSlash = '\0SLASH'+Math.random()+'\0'; +var escOpen = '\0OPEN'+Math.random()+'\0'; +var escClose = '\0CLOSE'+Math.random()+'\0'; +var escComma = '\0COMMA'+Math.random()+'\0'; +var escPeriod = '\0PERIOD'+Math.random()+'\0'; + +function numeric(str) { + return parseInt(str, 10) == str + ? parseInt(str, 10) + : str.charCodeAt(0); +} + +function escapeBraces(str) { + return str.split('\\\\').join(escSlash) + .split('\\{').join(escOpen) + .split('\\}').join(escClose) + .split('\\,').join(escComma) + .split('\\.').join(escPeriod); +} + +function unescapeBraces(str) { + return str.split(escSlash).join('\\') + .split(escOpen).join('{') + .split(escClose).join('}') + .split(escComma).join(',') + .split(escPeriod).join('.'); +} + + +// Basically just str.split(","), but handling cases +// where we have nested braced sections, which should be +// treated as individual members, like {a,{b,c},d} +function parseCommaParts(str) { + if (!str) + return ['']; + + var parts = []; + var m = balanced('{', '}', str); + + if (!m) + return str.split(','); + + var pre = m.pre; + var body = m.body; + var post = m.post; + var p = pre.split(','); + + p[p.length-1] += '{' + body + '}'; + var postParts = parseCommaParts(post); + if (post.length) { + p[p.length-1] += postParts.shift(); + p.push.apply(p, postParts); + } + + parts.push.apply(parts, p); + + return parts; +} + +function expandTop(str) { + if (!str) + return []; + + // I don't know why Bash 4.3 does this, but it does. + // Anything starting with {} will have the first two bytes preserved + // but *only* at the top level, so {},a}b will not expand to anything, + // but a{},b}c will be expanded to [a}c,abc]. + // One could argue that this is a bug in Bash, but since the goal of + // this module is to match Bash's rules, we escape a leading {} + if (str.substr(0, 2) === '{}') { + str = '\\{\\}' + str.substr(2); + } + + return expand(escapeBraces(str), true).map(unescapeBraces); +} + +function identity(e) { + return e; +} + +function embrace(str) { + return '{' + str + '}'; +} +function isPadded(el) { + return /^-?0\d/.test(el); +} + +function lte(i, y) { + return i <= y; +} +function gte(i, y) { + return i >= y; +} + +function expand(str, isTop) { + var expansions = []; + + var m = balanced('{', '}', str); + if (!m || /\$$/.test(m.pre)) return [str]; + + var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); + var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); + var isSequence = isNumericSequence || isAlphaSequence; + var isOptions = m.body.indexOf(',') >= 0; + if (!isSequence && !isOptions) { + // {a},b} + if (m.post.match(/,.*\}/)) { + str = m.pre + '{' + m.body + escClose + m.post; + return expand(str); + } + return [str]; + } + + var n; + if (isSequence) { + n = m.body.split(/\.\./); + } else { + n = parseCommaParts(m.body); + if (n.length === 1) { + // x{{a,b}}y ==> x{a}y x{b}y + n = expand(n[0], false).map(embrace); + if (n.length === 1) { + var post = m.post.length + ? expand(m.post, false) + : ['']; + return post.map(function(p) { + return m.pre + n[0] + p; + }); + } + } + } + + // at this point, n is the parts, and we know it's not a comma set + // with a single entry. + + // no need to expand pre, since it is guaranteed to be free of brace-sets + var pre = m.pre; + var post = m.post.length + ? expand(m.post, false) + : ['']; + + var N; + + if (isSequence) { + var x = numeric(n[0]); + var y = numeric(n[1]); + var width = Math.max(n[0].length, n[1].length) + var incr = n.length == 3 + ? Math.abs(numeric(n[2])) + : 1; + var test = lte; + var reverse = y < x; + if (reverse) { + incr *= -1; + test = gte; + } + var pad = n.some(isPadded); + + N = []; + + for (var i = x; test(i, y); i += incr) { + var c; + if (isAlphaSequence) { + c = String.fromCharCode(i); + if (c === '\\') + c = ''; + } else { + c = String(i); + if (pad) { + var need = width - c.length; + if (need > 0) { + var z = new Array(need + 1).join('0'); + if (i < 0) + c = '-' + z + c.slice(1); + else + c = z + c; + } + } + } + N.push(c); + } + } else { + N = concatMap(n, function(el) { return expand(el, false) }); + } + + for (var j = 0; j < N.length; j++) { + for (var k = 0; k < post.length; k++) { + var expansion = pre + N[j] + post[k]; + if (!isTop || isSequence || expansion) + expansions.push(expansion); + } + } + + return expansions; +} + + +},{"balanced-match":10,"concat-map":13}],12:[function(require,module,exports){ + +},{}],13:[function(require,module,exports){ +module.exports = function (xs, fn) { + var res = []; + for (var i = 0; i < xs.length; i++) { + var x = fn(xs[i], i); + if (isArray(x)) res.push.apply(res, x); + else res.push(x); + } + return res; +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +},{}],14:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],15:[function(require,module,exports){ +(function (process){ +exports.alphasort = alphasort +exports.alphasorti = alphasorti +exports.setopts = setopts +exports.ownProp = ownProp +exports.makeAbs = makeAbs +exports.finish = finish +exports.mark = mark +exports.isIgnored = isIgnored +exports.childrenIgnored = childrenIgnored + +function ownProp (obj, field) { + return Object.prototype.hasOwnProperty.call(obj, field) +} + +var path = require("path") +var minimatch = require("minimatch") +var isAbsolute = require("path-is-absolute") +var Minimatch = minimatch.Minimatch + +function alphasorti (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()) +} + +function alphasort (a, b) { + return a.localeCompare(b) +} + +function setupIgnores (self, options) { + self.ignore = options.ignore || [] + + if (!Array.isArray(self.ignore)) + self.ignore = [self.ignore] + + if (self.ignore.length) { + self.ignore = self.ignore.map(ignoreMap) + } +} + +function ignoreMap (pattern) { + var gmatcher = null + if (pattern.slice(-3) === '/**') { + var gpattern = pattern.replace(/(\/\*\*)+$/, '') + gmatcher = new Minimatch(gpattern) + } + + return { + matcher: new Minimatch(pattern), + gmatcher: gmatcher + } +} + +function setopts (self, pattern, options) { + if (!options) + options = {} + + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } + + self.silent = !!options.silent + self.pattern = pattern + self.strict = options.strict !== false + self.realpath = !!options.realpath + self.realpathCache = options.realpathCache || Object.create(null) + self.follow = !!options.follow + self.dot = !!options.dot + self.mark = !!options.mark + self.nodir = !!options.nodir + if (self.nodir) + self.mark = true + self.sync = !!options.sync + self.nounique = !!options.nounique + self.nonull = !!options.nonull + self.nosort = !!options.nosort + self.nocase = !!options.nocase + self.stat = !!options.stat + self.noprocess = !!options.noprocess + + self.maxLength = options.maxLength || Infinity + self.cache = options.cache || Object.create(null) + self.statCache = options.statCache || Object.create(null) + self.symlinks = options.symlinks || Object.create(null) + + setupIgnores(self, options) + + self.changedCwd = false + var cwd = process.cwd() + if (!ownProp(options, "cwd")) + self.cwd = cwd + else { + self.cwd = options.cwd + self.changedCwd = path.resolve(options.cwd) !== cwd + } + + self.root = options.root || path.resolve(self.cwd, "/") + self.root = path.resolve(self.root) + if (process.platform === "win32") + self.root = self.root.replace(/\\/g, "/") + + self.nomount = !!options.nomount + + // disable comments and negation unless the user explicitly + // passes in false as the option. + options.nonegate = options.nonegate === false ? false : true + options.nocomment = options.nocomment === false ? false : true + deprecationWarning(options) + + self.minimatch = new Minimatch(pattern, options) + self.options = self.minimatch.options +} + +// TODO(isaacs): remove entirely in v6 +// exported to reset in tests +exports.deprecationWarned +function deprecationWarning(options) { + if (!options.nonegate || !options.nocomment) { + if (process.noDeprecation !== true && !exports.deprecationWarned) { + var msg = 'glob WARNING: comments and negation will be disabled in v6' + if (process.throwDeprecation) + throw new Error(msg) + else if (process.traceDeprecation) + console.trace(msg) + else + console.error(msg) + + exports.deprecationWarned = true + } + } +} + +function finish (self) { + var nou = self.nounique + var all = nou ? [] : Object.create(null) + + for (var i = 0, l = self.matches.length; i < l; i ++) { + var matches = self.matches[i] + if (!matches || Object.keys(matches).length === 0) { + if (self.nonull) { + // do like the shell, and spit out the literal glob + var literal = self.minimatch.globSet[i] + if (nou) + all.push(literal) + else + all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) + all.push.apply(all, m) + else + m.forEach(function (m) { + all[m] = true + }) + } + } + + if (!nou) + all = Object.keys(all) + + if (!self.nosort) + all = all.sort(self.nocase ? alphasorti : alphasort) + + // at *some* point we statted all of these + if (self.mark) { + for (var i = 0; i < all.length; i++) { + all[i] = self._mark(all[i]) + } + if (self.nodir) { + all = all.filter(function (e) { + return !(/\/$/.test(e)) + }) + } + } + + if (self.ignore.length) + all = all.filter(function(m) { + return !isIgnored(self, m) + }) + + self.found = all +} + +function mark (self, p) { + var abs = makeAbs(self, p) + var c = self.cache[abs] + var m = p + if (c) { + var isDir = c === 'DIR' || Array.isArray(c) + var slash = p.slice(-1) === '/' + + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) + + if (m !== p) { + var mabs = makeAbs(self, m) + self.statCache[mabs] = self.statCache[abs] + self.cache[mabs] = self.cache[abs] + } + } + + return m +} + +// lotta situps... +function makeAbs (self, f) { + var abs = f + if (f.charAt(0) === '/') { + abs = path.join(self.root, f) + } else if (isAbsolute(f) || f === '') { + abs = f + } else if (self.changedCwd) { + abs = path.resolve(self.cwd, f) + } else { + abs = path.resolve(f) + } + return abs +} + + +// Return true, if pattern ends with globstar '**', for the accompanying parent directory. +// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents +function isIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +function childrenIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +}).call(this,require('_process')) +},{"_process":24,"minimatch":20,"path":22,"path-is-absolute":23}],16:[function(require,module,exports){ +(function (process){ +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern, false) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern, inGlobStar) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// +// If inGlobStar and PREFIX is symlink and points to dir +// set ENTRIES = [] +// else readdir(PREFIX) as ENTRIES +// If fail, END +// +// with ENTRIES +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// // Mark that this entry is a globstar match +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. + +module.exports = glob + +var fs = require('fs') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var inherits = require('inherits') +var EE = require('events').EventEmitter +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var globSync = require('./sync.js') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var inflight = require('inflight') +var util = require('util') +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored + +var once = require('once') + +function glob (pattern, options, cb) { + if (typeof options === 'function') cb = options, options = {} + if (!options) options = {} + + if (options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return globSync(pattern, options) + } + + return new Glob(pattern, options, cb) +} + +glob.sync = globSync +var GlobSync = glob.GlobSync = globSync.GlobSync + +// old api surface +glob.glob = glob + +glob.hasMagic = function (pattern, options_) { + var options = util._extend({}, options_) + options.noprocess = true + + var g = new Glob(pattern, options) + var set = g.minimatch.set + if (set.length > 1) + return true + + for (var j = 0; j < set[0].length; j++) { + if (typeof set[0][j] !== 'string') + return true + } + + return false +} + +glob.Glob = Glob +inherits(Glob, EE) +function Glob (pattern, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + + if (options && options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return new GlobSync(pattern, options) + } + + if (!(this instanceof Glob)) + return new Glob(pattern, options, cb) + + setopts(this, pattern, options) + this._didRealPath = false + + // process each pattern in the minimatch set + var n = this.minimatch.set.length + + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) + + if (typeof cb === 'function') { + cb = once(cb) + this.on('error', cb) + this.on('end', function (matches) { + cb(null, matches) + }) + } + + var self = this + var n = this.minimatch.set.length + this._processing = 0 + this.matches = new Array(n) + + this._emitQueue = [] + this._processQueue = [] + this.paused = false + + if (this.noprocess) + return this + + if (n === 0) + return done() + + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false, done) + } + + function done () { + --self._processing + if (self._processing <= 0) + self._finish() + } +} + +Glob.prototype._finish = function () { + assert(this instanceof Glob) + if (this.aborted) + return + + if (this.realpath && !this._didRealpath) + return this._realpath() + + common.finish(this) + this.emit('end', this.found) +} + +Glob.prototype._realpath = function () { + if (this._didRealpath) + return + + this._didRealpath = true + + var n = this.matches.length + if (n === 0) + return this._finish() + + var self = this + for (var i = 0; i < this.matches.length; i++) + this._realpathSet(i, next) + + function next () { + if (--n === 0) + self._finish() + } +} + +Glob.prototype._realpathSet = function (index, cb) { + var matchset = this.matches[index] + if (!matchset) + return cb() + + var found = Object.keys(matchset) + var self = this + var n = found.length + + if (n === 0) + return cb() + + var set = this.matches[index] = Object.create(null) + found.forEach(function (p, i) { + // If there's a problem with the stat, then it means that + // one or more of the links in the realpath couldn't be + // resolved. just return the abs value in that case. + p = self._makeAbs(p) + fs.realpath(p, self.realpathCache, function (er, real) { + if (!er) + set[real] = true + else if (er.syscall === 'stat') + set[p] = true + else + self.emit('error', er) // srsly wtf right here + + if (--n === 0) { + self.matches[index] = set + cb() + } + }) + }) +} + +Glob.prototype._mark = function (p) { + return common.mark(this, p) +} + +Glob.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +Glob.prototype.abort = function () { + this.aborted = true + this.emit('abort') +} + +Glob.prototype.pause = function () { + if (!this.paused) { + this.paused = true + this.emit('pause') + } +} + +Glob.prototype.resume = function () { + if (this.paused) { + this.emit('resume') + this.paused = false + if (this._emitQueue.length) { + var eq = this._emitQueue.slice(0) + this._emitQueue.length = 0 + for (var i = 0; i < eq.length; i ++) { + var e = eq[i] + this._emitMatch(e[0], e[1]) + } + } + if (this._processQueue.length) { + var pq = this._processQueue.slice(0) + this._processQueue.length = 0 + for (var i = 0; i < pq.length; i ++) { + var p = pq[i] + this._processing-- + this._process(p[0], p[1], p[2], p[3]) + } + } + } +} + +Glob.prototype._process = function (pattern, index, inGlobStar, cb) { + assert(this instanceof Glob) + assert(typeof cb === 'function') + + if (this.aborted) + return + + this._processing++ + if (this.paused) { + this._processQueue.push([pattern, index, inGlobStar, cb]) + return + } + + //console.error('PROCESS %d', this._processing, pattern) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index, cb) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip _processing + if (childrenIgnored(this, read)) + return cb() + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) +} + +Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + +Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return cb() + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return cb() + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return cb() + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + this._process([e].concat(remain), index, inGlobStar, cb) + } + cb() +} + +Glob.prototype._emitMatch = function (index, e) { + if (this.aborted) + return + + if (this.matches[index][e]) + return + + if (isIgnored(this, e)) + return + + if (this.paused) { + this._emitQueue.push([index, e]) + return + } + + var abs = this._makeAbs(e) + + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } + + if (this.mark) + e = this._mark(e) + + this.matches[index][e] = true + + var st = this.statCache[abs] + if (st) + this.emit('stat', e, st) + + this.emit('match', e) +} + +Glob.prototype._readdirInGlobStar = function (abs, cb) { + if (this.aborted) + return + + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false, cb) + + var lstatkey = 'lstat\0' + abs + var self = this + var lstatcb = inflight(lstatkey, lstatcb_) + + if (lstatcb) + fs.lstat(abs, lstatcb) + + function lstatcb_ (er, lstat) { + if (er) + return cb() + + var isSym = lstat.isSymbolicLink() + self.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) { + self.cache[abs] = 'FILE' + cb() + } else + self._readdir(abs, false, cb) + } +} + +Glob.prototype._readdir = function (abs, inGlobStar, cb) { + if (this.aborted) + return + + cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb) + if (!cb) + return + + //console.error('RD %j %j', +inGlobStar, abs) + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs, cb) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return cb() + + if (Array.isArray(c)) + return cb(null, c) + } + + var self = this + fs.readdir(abs, readdirCb(this, abs, cb)) +} + +function readdirCb (self, abs, cb) { + return function (er, entries) { + if (er) + self._readdirError(abs, er, cb) + else + self._readdirEntries(abs, entries, cb) + } +} + +Glob.prototype._readdirEntries = function (abs, entries, cb) { + if (this.aborted) + return + + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + return cb(null, entries) +} + +Glob.prototype._readdirError = function (f, er, cb) { + if (this.aborted) + return + + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) { + this.emit('error', er) + // If the error is handled, then we abort + // if not, we threw out of here + this.abort() + } + if (!this.silent) + console.error('glob error', er) + break + } + + return cb() +} + +Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + + +Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + //console.error('pgs2', prefix, remain[0], entries) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return cb() + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false, cb) + + var isSym = this.symlinks[abs] + var len = entries.length + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return cb() + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true, cb) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true, cb) + } + + cb() +} + +Glob.prototype._processSimple = function (prefix, index, cb) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var self = this + this._stat(prefix, function (er, exists) { + self._processSimple2(prefix, index, er, exists, cb) + }) +} +Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { + + //console.error('ps2', prefix, exists) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return cb() + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this._emitMatch(index, prefix) + cb() +} + +// Returns either 'DIR', 'FILE', or false +Glob.prototype._stat = function (f, cb) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return cb() + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return cb(null, c) + + if (needDir && c === 'FILE') + return cb() + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (stat !== undefined) { + if (stat === false) + return cb(null, stat) + else { + var type = stat.isDirectory() ? 'DIR' : 'FILE' + if (needDir && type === 'FILE') + return cb() + else + return cb(null, type, stat) + } + } + + var self = this + var statcb = inflight('stat\0' + abs, lstatcb_) + if (statcb) + fs.lstat(abs, statcb) + + function lstatcb_ (er, lstat) { + if (lstat && lstat.isSymbolicLink()) { + // If it's a symlink, then treat it as the target, unless + // the target does not exist, then treat it as a file. + return fs.stat(abs, function (er, stat) { + if (er) + self._stat2(f, abs, null, lstat, cb) + else + self._stat2(f, abs, er, stat, cb) + }) + } else { + self._stat2(f, abs, er, lstat, cb) + } + } +} + +Glob.prototype._stat2 = function (f, abs, er, stat, cb) { + if (er) { + this.statCache[abs] = false + return cb() + } + + var needDir = f.slice(-1) === '/' + this.statCache[abs] = stat + + if (abs.slice(-1) === '/' && !stat.isDirectory()) + return cb(null, false, stat) + + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c !== 'DIR') + return cb() + + return cb(null, c, stat) +} + +}).call(this,require('_process')) +},{"./common.js":15,"./sync.js":17,"_process":24,"assert":9,"events":14,"fs":12,"inflight":18,"inherits":19,"minimatch":20,"once":21,"path":22,"path-is-absolute":23,"util":28}],17:[function(require,module,exports){ +(function (process){ +module.exports = globSync +globSync.GlobSync = GlobSync + +var fs = require('fs') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var Glob = require('./glob.js').Glob +var util = require('util') +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var childrenIgnored = common.childrenIgnored + +function globSync (pattern, options) { + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + return new GlobSync(pattern, options).found +} + +function GlobSync (pattern, options) { + if (!pattern) + throw new Error('must provide pattern') + + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + if (!(this instanceof GlobSync)) + return new GlobSync(pattern, options) + + setopts(this, pattern, options) + + if (this.noprocess) + return this + + var n = this.minimatch.set.length + this.matches = new Array(n) + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false) + } + this._finish() +} + +GlobSync.prototype._finish = function () { + assert(this instanceof GlobSync) + if (this.realpath) { + var self = this + this.matches.forEach(function (matchset, index) { + var set = self.matches[index] = Object.create(null) + for (var p in matchset) { + try { + p = self._makeAbs(p) + var real = fs.realpathSync(p, self.realpathCache) + set[real] = true + } catch (er) { + if (er.syscall === 'stat') + set[self._makeAbs(p)] = true + else + throw er + } + } + }) + } + common.finish(this) +} + + +GlobSync.prototype._process = function (pattern, index, inGlobStar) { + assert(this instanceof GlobSync) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // See if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip processing + if (childrenIgnored(this, read)) + return + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar) +} + + +GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { + var entries = this._readdir(abs, inGlobStar) + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix.slice(-1) !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this.matches[index][e] = true + } + // This was the last one, and no stats were needed + return + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) + newPattern = [prefix, e] + else + newPattern = [e] + this._process(newPattern.concat(remain), index, inGlobStar) + } +} + + +GlobSync.prototype._emitMatch = function (index, e) { + var abs = this._makeAbs(e) + if (this.mark) + e = this._mark(e) + + if (this.matches[index][e]) + return + + if (this.nodir) { + var c = this.cache[this._makeAbs(e)] + if (c === 'DIR' || Array.isArray(c)) + return + } + + this.matches[index][e] = true + if (this.stat) + this._stat(e) +} + + +GlobSync.prototype._readdirInGlobStar = function (abs) { + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false) + + var entries + var lstat + var stat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + // lstat failed, doesn't exist + return null + } + + var isSym = lstat.isSymbolicLink() + this.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) + this.cache[abs] = 'FILE' + else + entries = this._readdir(abs, false) + + return entries +} + +GlobSync.prototype._readdir = function (abs, inGlobStar) { + var entries + + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return null + + if (Array.isArray(c)) + return c + } + + try { + return this._readdirEntries(abs, fs.readdirSync(abs)) + } catch (er) { + this._readdirError(abs, er) + return null + } +} + +GlobSync.prototype._readdirEntries = function (abs, entries) { + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + + // mark and cache dir-ness + return entries +} + +GlobSync.prototype._readdirError = function (f, er) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) + throw er + if (!this.silent) + console.error('glob error', er) + break + } +} + +GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { + + var entries = this._readdir(abs, inGlobStar) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false) + + var len = entries.length + var isSym = this.symlinks[abs] + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true) + } +} + +GlobSync.prototype._processSimple = function (prefix, index) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var exists = this._stat(prefix) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this.matches[index][prefix] = true +} + +// Returns either 'DIR', 'FILE', or false +GlobSync.prototype._stat = function (f) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return false + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return c + + if (needDir && c === 'FILE') + return false + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (!stat) { + var lstat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + return false + } + + if (lstat.isSymbolicLink()) { + try { + stat = fs.statSync(abs) + } catch (er) { + stat = lstat + } + } else { + stat = lstat + } + } + + this.statCache[abs] = stat + + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c !== 'DIR') + return false + + return c +} + +GlobSync.prototype._mark = function (p) { + return common.mark(this, p) +} + +GlobSync.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +}).call(this,require('_process')) +},{"./common.js":15,"./glob.js":16,"_process":24,"assert":9,"fs":12,"minimatch":20,"path":22,"path-is-absolute":23,"util":28}],18:[function(require,module,exports){ +(function (process){ +var wrappy = require('wrappy') +var reqs = Object.create(null) +var once = require('once') + +module.exports = wrappy(inflight) + +function inflight (key, cb) { + if (reqs[key]) { + reqs[key].push(cb) + return null + } else { + reqs[key] = [cb] + return makeres(key) + } +} + +function makeres (key) { + return once(function RES () { + var cbs = reqs[key] + var len = cbs.length + var args = slice(arguments) + + // XXX It's somewhat ambiguous whether a new callback added in this + // pass should be queued for later execution if something in the + // list of callbacks throws, or if it should just be discarded. + // However, it's such an edge case that it hardly matters, and either + // choice is likely as surprising as the other. + // As it happens, we do go ahead and schedule it for later execution. + try { + for (var i = 0; i < len; i++) { + cbs[i].apply(null, args) + } + } finally { + if (cbs.length > len) { + // added more in the interim. + // de-zalgo, just in case, but don't call again. + cbs.splice(0, len) + process.nextTick(function () { + RES.apply(null, args) + }) + } else { + delete reqs[key] + } + } + }) +} + +function slice (args) { + var length = args.length + var array = [] + + for (var i = 0; i < length; i++) array[i] = args[i] + return array +} + +}).call(this,require('_process')) +},{"_process":24,"once":21,"wrappy":29}],19:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],20:[function(require,module,exports){ +module.exports = minimatch +minimatch.Minimatch = Minimatch + +var path = { sep: '/' } +try { + path = require('path') +} catch (er) {} + +var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} +var expand = require('brace-expansion') + +var plTypes = { + '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, + '?': { open: '(?:', close: ')?' }, + '+': { open: '(?:', close: ')+' }, + '*': { open: '(?:', close: ')*' }, + '@': { open: '(?:', close: ')' } +} + +// any single thing other than / +// don't need to escape / when using new RegExp() +var qmark = '[^/]' + +// * => any number of characters +var star = qmark + '*?' + +// ** when dots are allowed. Anything goes, except .. and . +// not (^ or / followed by one or two dots followed by $ or /), +// followed by anything, any number of times. +var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?' + +// not a ^ or / followed by a dot, +// followed by anything, any number of times. +var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?' + +// characters that need to be escaped in RegExp. +var reSpecials = charSet('().*{}+?[]^$\\!') + +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split('').reduce(function (set, c) { + set[c] = true + return set + }, {}) +} + +// normalizes slashes. +var slashSplit = /\/+/ + +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} + +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} + +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch + + var orig = minimatch + + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } + + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } + + return m +} + +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} + +function minimatch (p, pattern, options) { + if (typeof pattern !== 'string') { + throw new TypeError('glob pattern string required') + } + + if (!options) options = {} + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + return false + } + + // "" only matches "" + if (pattern.trim() === '') return p === '' + + return new Minimatch(pattern, options).match(p) +} + +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options) + } + + if (typeof pattern !== 'string') { + throw new TypeError('glob pattern string required') + } + + if (!options) options = {} + pattern = pattern.trim() + + // windows support: need to use /, not \ + if (path.sep !== '/') { + pattern = pattern.split(path.sep).join('/') + } + + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + + // make the set of regexps etc. + this.make() +} + +Minimatch.prototype.debug = function () {} + +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return + + var pattern = this.pattern + var options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + var set = this.globSet = this.braceExpand() + + if (options.debug) this.debug = console.error + + this.debug(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) + + this.debug(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + this.debug(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return s.indexOf(false) === -1 + }) + + this.debug(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + var negate = false + var options = this.options + var negateOffset = 0 + + if (options.nonegate) return + + for (var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === '!' + ; i++) { + negate = !negate + negateOffset++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return braceExpand(pattern, options) +} + +Minimatch.prototype.braceExpand = braceExpand + +function braceExpand (pattern, options) { + if (!options) { + if (this instanceof Minimatch) { + options = this.options + } else { + options = {} + } + } + + pattern = typeof pattern === 'undefined' + ? this.pattern : pattern + + if (typeof pattern === 'undefined') { + throw new TypeError('undefined pattern') + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + return expand(pattern) +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + if (pattern.length > 1024 * 64) { + throw new TypeError('pattern is too long') + } + + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === '**') return GLOBSTAR + if (pattern === '') return '' + + var re = '' + var hasMagic = !!options.nocase + var escaping = false + // ? => one single character + var patternListStack = [] + var negativeLists = [] + var stateChar + var inClass = false + var reClassStart = -1 + var classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + var patternStart = pattern.charAt(0) === '.' ? '' // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' + : '(?!\\.)' + var self = this + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case '*': + re += star + hasMagic = true + break + case '?': + re += qmark + hasMagic = true + break + default: + re += '\\' + stateChar + break + } + self.debug('clearStateChar %j %j', stateChar, re) + stateChar = false + } + } + + for (var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i++) { + this.debug('%s\t%s %s %j', pattern, i, re, c) + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += '\\' + c + escaping = false + continue + } + + switch (c) { + case '/': + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case '\\': + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case '?': + case '*': + case '+': + case '@': + case '!': + this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c) + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + this.debug(' in class') + if (c === '!' && i === classStart + 1) c = '^' + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + self.debug('call clearStateChar %j', stateChar) + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case '(': + if (inClass) { + re += '(' + continue + } + + if (!stateChar) { + re += '\\(' + continue + } + + patternListStack.push({ + type: stateChar, + start: i - 1, + reStart: re.length, + open: plTypes[stateChar].open, + close: plTypes[stateChar].close + }) + // negation is (?:(?!js)[^/]*) + re += stateChar === '!' ? '(?:(?!(?:' : '(?:' + this.debug('plType %j %j', stateChar, re) + stateChar = false + continue + + case ')': + if (inClass || !patternListStack.length) { + re += '\\)' + continue + } + + clearStateChar() + hasMagic = true + var pl = patternListStack.pop() + // negation is (?:(?!js)[^/]*) + // The others are (?:) + re += pl.close + if (pl.type === '!') { + negativeLists.push(pl) + } + pl.reEnd = re.length + continue + + case '|': + if (inClass || !patternListStack.length || escaping) { + re += '\\|' + escaping = false + continue + } + + clearStateChar() + re += '|' + continue + + // these are mostly the same in regexp and glob + case '[': + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += '\\' + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case ']': + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += '\\' + c + escaping = false + continue + } + + // handle the case where we left a class open. + // "[z-a]" is valid, equivalent to "\[z-a\]" + if (inClass) { + // split where the last [ was, make sure we don't have + // an invalid re. if so, re-walk the contents of the + // would-be class to re-translate any characters that + // were passed through as-is + // TODO: It would probably be faster to determine this + // without a try/catch and a new RegExp, but it's tricky + // to do safely. For now, this is safe and works. + var cs = pattern.substring(classStart + 1, i) + try { + RegExp('[' + cs + ']') + } catch (er) { + // not a valid class! + var sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]' + hasMagic = hasMagic || sp[1] + inClass = false + continue + } + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === '^' && inClass)) { + re += '\\' + } + + re += c + + } // switch + } // for + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + cs = pattern.substr(classStart + 1) + sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + pl.open.length) + this.debug('setting tail', re, pl) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = '\\' + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + '|' + }) + + this.debug('tail=%j\n %s', tail, tail, pl, re) + var t = pl.type === '*' ? star + : pl.type === '?' ? qmark + : '\\' + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + t + '\\(' + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += '\\\\' + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case '.': + case '[': + case '(': addPatternStart = true + } + + // Hack to work around lack of negative lookbehind in JS + // A pattern like: *.!(x).!(y|z) needs to ensure that a name + // like 'a.xyz.yz' doesn't match. So, the first negative + // lookahead, has to look ALL the way ahead, to the end of + // the pattern. + for (var n = negativeLists.length - 1; n > -1; n--) { + var nl = negativeLists[n] + + var nlBefore = re.slice(0, nl.reStart) + var nlFirst = re.slice(nl.reStart, nl.reEnd - 8) + var nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + var nlAfter = re.slice(nl.reEnd) + + nlLast += nlAfter + + // Handle nested stuff like *(*.js|!(*.json)), where open parens + // mean that we should *not* include the ) in the bit that is considered + // "after" the negated section. + var openParensBefore = nlBefore.split('(').length - 1 + var cleanAfter = nlAfter + for (i = 0; i < openParensBefore; i++) { + cleanAfter = cleanAfter.replace(/\)[+*?]?/, '') + } + nlAfter = cleanAfter + + var dollar = '' + if (nlAfter === '' && isSub !== SUBPARSE) { + dollar = '$' + } + var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast + re = newRe + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== '' && hasMagic) { + re = '(?=.)' + re + } + + if (addPatternStart) { + re = patternStart + re + } + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [re, hasMagic] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? 'i' : '' + try { + var regExp = new RegExp('^' + re + '$', flags) + } catch (er) { + // If it was an invalid regular expression, then it can't match + // anything. This trick looks for a character after the end of + // the string, which is of course impossible, except in multi-line + // mode, but it's not a /m regex. + return new RegExp('$.') + } + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) { + this.regexp = false + return this.regexp + } + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + var flags = options.nocase ? 'i' : '' + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === 'string') ? regExpEscape(p) + : p._src + }).join('\\\/') + }).join('|') + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = '^(?:' + re + ')$' + + // can match anything, as long as it's not this. + if (this.negate) re = '^(?!' + re + ').*$' + + try { + this.regexp = new RegExp(re, flags) + } catch (ex) { + this.regexp = false + } + return this.regexp +} + +minimatch.match = function (list, pattern, options) { + options = options || {} + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (mm.options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + this.debug('match', f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === '' + + if (f === '/' && partial) return true + + var options = this.options + + // windows: need to use /, not \ + if (path.sep !== '/') { + f = f.split(path.sep).join('/') + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + this.debug(this.pattern, 'split', f) + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + this.debug(this.pattern, 'set', set) + + // Find the basename of the path by looking for the last non-empty segment + var filename + var i + for (i = f.length - 1; i >= 0; i--) { + filename = f[i] + if (filename) break + } + + for (i = 0; i < set.length; i++) { + var pattern = set[i] + var file = f + if (options.matchBase && pattern.length === 1) { + file = [filename] + } + var hit = this.matchOne(file, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + this.debug('matchOne', + { 'this': this, file: file, pattern: pattern }) + + this.debug('matchOne', file.length, pattern.length) + + for (var fi = 0, + pi = 0, + fl = file.length, + pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi++, pi++) { + this.debug('matchOne loop') + var p = pattern[pi] + var f = file[fi] + + this.debug(pattern, p, f) + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + this.debug('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + var pr = pi + 1 + if (pr === pl) { + this.debug('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for (; fi < fl; fi++) { + if (file[fi] === '.' || file[fi] === '..' || + (!options.dot && file[fi].charAt(0) === '.')) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + while (fr < fl) { + var swallowee = file[fr] + + this.debug('\nglobstar while', file, fr, pattern, pr, swallowee) + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + this.debug('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === '.' || swallowee === '..' || + (!options.dot && swallowee.charAt(0) === '.')) { + this.debug('dot detected!', file, fr, pattern, pr) + break + } + + // ** swallows a segment, and continue. + this.debug('globstar swallow a segment, and continue') + fr++ + } + } + + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + this.debug('\n>>> no match, partial?', file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === 'string') { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + this.debug('string match', p, f, hit) + } else { + hit = f.match(p) + this.debug('pattern match', p, f, hit) + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') + return emptyFileEnd + } + + // should be unreachable. + throw new Error('wtf?') +} + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, '$1') +} + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') +} + +},{"brace-expansion":11,"path":22}],21:[function(require,module,exports){ +var wrappy = require('wrappy') +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} + +},{"wrappy":29}],22:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,require('_process')) +},{"_process":24}],23:[function(require,module,exports){ +(function (process){ +'use strict'; + +function posix(path) { + return path.charAt(0) === '/'; +} + +function win32(path) { + // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56 + var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; + var result = splitDeviceRe.exec(path); + var device = result[1] || ''; + var isUnc = Boolean(device && device.charAt(1) !== ':'); + + // UNC paths are always absolute + return Boolean(result[2] || isUnc); +} + +module.exports = process.platform === 'win32' ? win32 : posix; +module.exports.posix = posix; +module.exports.win32 = win32; + +}).call(this,require('_process')) +},{"_process":24}],24:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],25:[function(require,module,exports){ +// Underscore.js 1.8.3 +// http://underscorejs.org +// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `exports` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind, + nativeCreate = Object.create; + + // Naked function reference for surrogate-prototype-swapping. + var Ctor = function(){}; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.8.3'; + + // Internal function that returns an efficient (for current engines) version + // of the passed-in callback, to be repeatedly applied in other Underscore + // functions. + var optimizeCb = function(func, context, argCount) { + if (context === void 0) return func; + switch (argCount == null ? 3 : argCount) { + case 1: return function(value) { + return func.call(context, value); + }; + case 2: return function(value, other) { + return func.call(context, value, other); + }; + case 3: return function(value, index, collection) { + return func.call(context, value, index, collection); + }; + case 4: return function(accumulator, value, index, collection) { + return func.call(context, accumulator, value, index, collection); + }; + } + return function() { + return func.apply(context, arguments); + }; + }; + + // A mostly-internal function to generate callbacks that can be applied + // to each element in a collection, returning the desired result — either + // identity, an arbitrary callback, a property matcher, or a property accessor. + var cb = function(value, context, argCount) { + if (value == null) return _.identity; + if (_.isFunction(value)) return optimizeCb(value, context, argCount); + if (_.isObject(value)) return _.matcher(value); + return _.property(value); + }; + _.iteratee = function(value, context) { + return cb(value, context, Infinity); + }; + + // An internal function for creating assigner functions. + var createAssigner = function(keysFunc, undefinedOnly) { + return function(obj) { + var length = arguments.length; + if (length < 2 || obj == null) return obj; + for (var index = 1; index < length; index++) { + var source = arguments[index], + keys = keysFunc(source), + l = keys.length; + for (var i = 0; i < l; i++) { + var key = keys[i]; + if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; + } + } + return obj; + }; + }; + + // An internal function for creating a new object that inherits from another. + var baseCreate = function(prototype) { + if (!_.isObject(prototype)) return {}; + if (nativeCreate) return nativeCreate(prototype); + Ctor.prototype = prototype; + var result = new Ctor; + Ctor.prototype = null; + return result; + }; + + var property = function(key) { + return function(obj) { + return obj == null ? void 0 : obj[key]; + }; + }; + + // Helper for collection methods to determine whether a collection + // should be iterated as an array or as an object + // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength + // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 + var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; + var getLength = property('length'); + var isArrayLike = function(collection) { + var length = getLength(collection); + return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; + }; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles raw objects in addition to array-likes. Treats all + // sparse array-likes as if they were dense. + _.each = _.forEach = function(obj, iteratee, context) { + iteratee = optimizeCb(iteratee, context); + var i, length; + if (isArrayLike(obj)) { + for (i = 0, length = obj.length; i < length; i++) { + iteratee(obj[i], i, obj); + } + } else { + var keys = _.keys(obj); + for (i = 0, length = keys.length; i < length; i++) { + iteratee(obj[keys[i]], keys[i], obj); + } + } + return obj; + }; + + // Return the results of applying the iteratee to each element. + _.map = _.collect = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + results = Array(length); + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + results[index] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Create a reducing function iterating left or right. + function createReduce(dir) { + // Optimized iterator function as using arguments.length + // in the main function will deoptimize the, see #1991. + function iterator(obj, iteratee, memo, keys, index, length) { + for (; index >= 0 && index < length; index += dir) { + var currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + } + + return function(obj, iteratee, memo, context) { + iteratee = optimizeCb(iteratee, context, 4); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + index = dir > 0 ? 0 : length - 1; + // Determine the initial value if none is provided. + if (arguments.length < 3) { + memo = obj[keys ? keys[index] : index]; + index += dir; + } + return iterator(obj, iteratee, memo, keys, index, length); + }; + } + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. + _.reduce = _.foldl = _.inject = createReduce(1); + + // The right-associative version of reduce, also known as `foldr`. + _.reduceRight = _.foldr = createReduce(-1); + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var key; + if (isArrayLike(obj)) { + key = _.findIndex(obj, predicate, context); + } else { + key = _.findKey(obj, predicate, context); + } + if (key !== void 0 && key !== -1) return obj[key]; + }; + + // Return all the elements that pass a truth test. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + predicate = cb(predicate, context); + _.each(obj, function(value, index, list) { + if (predicate(value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, _.negate(cb(predicate)), context); + }; + + // Determine whether all of the elements match a truth test. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (!predicate(obj[currentKey], currentKey, obj)) return false; + } + return true; + }; + + // Determine if at least one element in the object matches a truth test. + // Aliased as `any`. + _.some = _.any = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (predicate(obj[currentKey], currentKey, obj)) return true; + } + return false; + }; + + // Determine if the array or object contains a given item (using `===`). + // Aliased as `includes` and `include`. + _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + if (typeof fromIndex != 'number' || guard) fromIndex = 0; + return _.indexOf(obj, item, fromIndex) >= 0; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + var func = isFunc ? method : value[method]; + return func == null ? func : func.apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matcher(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matcher(attrs)); + }; + + // Return the maximum element (or element-based computation). + _.max = function(obj, iteratee, context) { + var result = -Infinity, lastComputed = -Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value > result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed > lastComputed || computed === -Infinity && result === -Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iteratee, context) { + var result = Infinity, lastComputed = Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value < result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed < lastComputed || computed === Infinity && result === Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Shuffle a collection, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var set = isArrayLike(obj) ? obj : _.values(obj); + var length = set.length; + var shuffled = Array(length); + for (var index = 0, rand; index < length; index++) { + rand = _.random(0, index); + if (rand !== index) shuffled[index] = shuffled[rand]; + shuffled[rand] = set[index]; + } + return shuffled; + }; + + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // Sort the object's values by a criterion produced by an iteratee. + _.sortBy = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iteratee(value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, iteratee, context) { + var result = {}; + iteratee = cb(iteratee, context); + _.each(obj, function(value, index) { + var key = iteratee(value, index, obj); + behavior(result, value, key); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, value, key) { + if (_.has(result, key)) result[key].push(value); else result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, value, key) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, value, key) { + if (_.has(result, key)) result[key]++; else result[key] = 1; + }); + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (isArrayLike(obj)) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return isArrayLike(obj) ? obj.length : _.keys(obj).length; + }; + + // Split a collection into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function(obj, predicate, context) { + predicate = cb(predicate, context); + var pass = [], fail = []; + _.each(obj, function(value, key, obj) { + (predicate(value, key, obj) ? pass : fail).push(value); + }); + return [pass, fail]; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[0]; + return _.initial(array, array.length - n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. + _.initial = function(array, n, guard) { + return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[array.length - 1]; + return _.rest(array, Math.max(0, array.length - n)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, n == null || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, strict, startIndex) { + var output = [], idx = 0; + for (var i = startIndex || 0, length = getLength(input); i < length; i++) { + var value = input[i]; + if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { + //flatten current level of array or arguments object + if (!shallow) value = flatten(value, shallow, strict); + var j = 0, len = value.length; + output.length += len; + while (j < len) { + output[idx++] = value[j++]; + } + } else if (!strict) { + output[idx++] = value; + } + } + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, false); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iteratee, context) { + if (!_.isBoolean(isSorted)) { + context = iteratee; + iteratee = isSorted; + isSorted = false; + } + if (iteratee != null) iteratee = cb(iteratee, context); + var result = []; + var seen = []; + for (var i = 0, length = getLength(array); i < length; i++) { + var value = array[i], + computed = iteratee ? iteratee(value, i, array) : value; + if (isSorted) { + if (!i || seen !== computed) result.push(value); + seen = computed; + } else if (iteratee) { + if (!_.contains(seen, computed)) { + seen.push(computed); + result.push(value); + } + } else if (!_.contains(result, value)) { + result.push(value); + } + } + return result; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(flatten(arguments, true, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var result = []; + var argsLength = arguments.length; + for (var i = 0, length = getLength(array); i < length; i++) { + var item = array[i]; + if (_.contains(result, item)) continue; + for (var j = 1; j < argsLength; j++) { + if (!_.contains(arguments[j], item)) break; + } + if (j === argsLength) result.push(item); + } + return result; + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = flatten(arguments, true, true, 1); + return _.filter(array, function(value){ + return !_.contains(rest, value); + }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + return _.unzip(arguments); + }; + + // Complement of _.zip. Unzip accepts an array of arrays and groups + // each array's elements on shared indices + _.unzip = function(array) { + var length = array && _.max(array, getLength).length || 0; + var result = Array(length); + + for (var index = 0; index < length; index++) { + result[index] = _.pluck(array, index); + } + return result; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + var result = {}; + for (var i = 0, length = getLength(list); i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // Generator function to create the findIndex and findLastIndex functions + function createPredicateIndexFinder(dir) { + return function(array, predicate, context) { + predicate = cb(predicate, context); + var length = getLength(array); + var index = dir > 0 ? 0 : length - 1; + for (; index >= 0 && index < length; index += dir) { + if (predicate(array[index], index, array)) return index; + } + return -1; + }; + } + + // Returns the first index on an array-like that passes a predicate test + _.findIndex = createPredicateIndexFinder(1); + _.findLastIndex = createPredicateIndexFinder(-1); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iteratee, context) { + iteratee = cb(iteratee, context, 1); + var value = iteratee(obj); + var low = 0, high = getLength(array); + while (low < high) { + var mid = Math.floor((low + high) / 2); + if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; + } + return low; + }; + + // Generator function to create the indexOf and lastIndexOf functions + function createIndexFinder(dir, predicateFind, sortedIndex) { + return function(array, item, idx) { + var i = 0, length = getLength(array); + if (typeof idx == 'number') { + if (dir > 0) { + i = idx >= 0 ? idx : Math.max(idx + length, i); + } else { + length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; + } + } else if (sortedIndex && idx && length) { + idx = sortedIndex(array, item); + return array[idx] === item ? idx : -1; + } + if (item !== item) { + idx = predicateFind(slice.call(array, i, length), _.isNaN); + return idx >= 0 ? idx + i : -1; + } + for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { + if (array[idx] === item) return idx; + } + return -1; + }; + } + + // Return the position of the first occurrence of an item in an array, + // or -1 if the item is not included in the array. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); + _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (stop == null) { + stop = start || 0; + start = 0; + } + step = step || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var range = Array(length); + + for (var idx = 0; idx < length; idx++, start += step) { + range[idx] = start; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Determines whether to execute a function as a constructor + // or a normal function with the provided arguments + var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { + if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); + var self = baseCreate(sourceFunc.prototype); + var result = sourceFunc.apply(self, args); + if (_.isObject(result)) return result; + return self; + }; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); + var args = slice.call(arguments, 2); + var bound = function() { + return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); + }; + return bound; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + var bound = function() { + var position = 0, length = boundArgs.length; + var args = Array(length); + for (var i = 0; i < length; i++) { + args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; + } + while (position < arguments.length) args.push(arguments[position++]); + return executeBound(func, bound, this, this, args); + }; + return bound; + }; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function(obj) { + var i, length = arguments.length, key; + if (length <= 1) throw new Error('bindAll must be passed function names'); + for (i = 1; i < length; i++) { + key = arguments[i]; + obj[key] = _.bind(obj[key], obj); + } + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memoize = function(key) { + var cache = memoize.cache; + var address = '' + (hasher ? hasher.apply(this, arguments) : key); + if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); + return cache[address]; + }; + memoize.cache = {}; + return memoize; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ + return func.apply(null, args); + }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = _.partial(_.delay, _, 1); + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + if (!options) options = {}; + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + if (!timeout) context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0 || remaining > wait) { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + previous = now; + result = func.apply(context, args); + if (!timeout) context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function() { + var last = _.now() - timestamp; + + if (last < wait && last >= 0) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + if (!timeout) context = args = null; + } + } + }; + + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a negated version of the passed-in predicate. + _.negate = function(predicate) { + return function() { + return !predicate.apply(this, arguments); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var args = arguments; + var start = args.length - 1; + return function() { + var i = start; + var result = args[start].apply(this, arguments); + while (i--) result = args[i].call(this, result); + return result; + }; + }; + + // Returns a function that will only be executed on and after the Nth call. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Returns a function that will only be executed up to (but not including) the Nth call. + _.before = function(times, func) { + var memo; + return function() { + if (--times > 0) { + memo = func.apply(this, arguments); + } + if (times <= 1) func = null; + return memo; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = _.partial(_.before, 2); + + // Object Functions + // ---------------- + + // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. + var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); + var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', + 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; + + function collectNonEnumProps(obj, keys) { + var nonEnumIdx = nonEnumerableProps.length; + var constructor = obj.constructor; + var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; + + // Constructor is a special case. + var prop = 'constructor'; + if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); + + while (nonEnumIdx--) { + prop = nonEnumerableProps[nonEnumIdx]; + if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { + keys.push(prop); + } + } + } + + // Retrieve the names of an object's own properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve all the property names of an object. + _.allKeys = function(obj) { + if (!_.isObject(obj)) return []; + var keys = []; + for (var key in obj) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Returns the results of applying the iteratee to each element of the object + // In contrast to _.map it returns an object + _.mapObject = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = _.keys(obj), + length = keys.length, + results = {}, + currentKey; + for (var index = 0; index < length; index++) { + currentKey = keys[index]; + results[currentKey] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = createAssigner(_.allKeys); + + // Assigns a given object with all the own properties in the passed-in object(s) + // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) + _.extendOwn = _.assign = createAssigner(_.keys); + + // Returns the first key on an object that passes a predicate test + _.findKey = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = _.keys(obj), key; + for (var i = 0, length = keys.length; i < length; i++) { + key = keys[i]; + if (predicate(obj[key], key, obj)) return key; + } + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(object, oiteratee, context) { + var result = {}, obj = object, iteratee, keys; + if (obj == null) return result; + if (_.isFunction(oiteratee)) { + keys = _.allKeys(obj); + iteratee = optimizeCb(oiteratee, context); + } else { + keys = flatten(arguments, false, false, 1); + iteratee = function(value, key, obj) { return key in obj; }; + obj = Object(obj); + } + for (var i = 0, length = keys.length; i < length; i++) { + var key = keys[i]; + var value = obj[key]; + if (iteratee(value, key, obj)) result[key] = value; + } + return result; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj, iteratee, context) { + if (_.isFunction(iteratee)) { + iteratee = _.negate(iteratee); + } else { + var keys = _.map(flatten(arguments, false, false, 1), String); + iteratee = function(value, key) { + return !_.contains(keys, key); + }; + } + return _.pick(obj, iteratee, context); + }; + + // Fill in a given object with default properties. + _.defaults = createAssigner(_.allKeys, true); + + // Creates an object that inherits from the given prototype object. + // If additional properties are provided then they will be added to the + // created object. + _.create = function(prototype, props) { + var result = baseCreate(prototype); + if (props) _.extendOwn(result, props); + return result; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Returns whether an object has a given set of `key:value` pairs. + _.isMatch = function(object, attrs) { + var keys = _.keys(attrs), length = keys.length; + if (object == null) return !length; + var obj = Object(object); + for (var i = 0; i < length; i++) { + var key = keys[i]; + if (attrs[key] !== obj[key] || !(key in obj)) return false; + } + return true; + }; + + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a === 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className !== toString.call(b)) return false; + switch (className) { + // Strings, numbers, regular expressions, dates, and booleans are compared by value. + case '[object RegExp]': + // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return '' + a === '' + b; + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. + // Object(NaN) is equivalent to NaN + if (+a !== +a) return +b !== +b; + // An `egal` comparison is performed for other numeric values. + return +a === 0 ? 1 / +a === 1 / b : +a === +b; + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a === +b; + } + + var areArrays = className === '[object Array]'; + if (!areArrays) { + if (typeof a != 'object' || typeof b != 'object') return false; + + // Objects with different constructors are not equivalent, but `Object`s or `Array`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && + _.isFunction(bCtor) && bCtor instanceof bCtor) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + } + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + + // Initializing stack of traversed objects. + // It's done here since we only need them for objects and arrays comparison. + aStack = aStack || []; + bStack = bStack || []; + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] === a) return bStack[length] === b; + } + + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + + // Recursively compare objects and arrays. + if (areArrays) { + // Compare array lengths to determine if a deep comparison is necessary. + length = a.length; + if (length !== b.length) return false; + // Deep compare the contents, ignoring non-numeric properties. + while (length--) { + if (!eq(a[length], b[length], aStack, bStack)) return false; + } + } else { + // Deep compare objects. + var keys = _.keys(a), key; + length = keys.length; + // Ensure that both objects contain the same number of properties before comparing deep equality. + if (_.keys(b).length !== length) return false; + while (length--) { + // Deep compare each member + key = keys[length]; + if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return true; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; + return _.keys(obj).length === 0; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) === '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. + _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) === '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE < 9), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return _.has(obj, 'callee'); + }; + } + + // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, + // IE 11 (#1621), and in Safari 8 (#1929). + if (typeof /./ != 'function' && typeof Int8Array != 'object') { + _.isFunction = function(obj) { + return typeof obj == 'function' || false; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj !== +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return obj != null && hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iteratees. + _.identity = function(value) { + return value; + }; + + // Predicate-generating functions. Often useful outside of Underscore. + _.constant = function(value) { + return function() { + return value; + }; + }; + + _.noop = function(){}; + + _.property = property; + + // Generates a function for a given object that returns a given property. + _.propertyOf = function(obj) { + return obj == null ? function(){} : function(key) { + return obj[key]; + }; + }; + + // Returns a predicate for checking whether an object has a given set of + // `key:value` pairs. + _.matcher = _.matches = function(attrs) { + attrs = _.extendOwn({}, attrs); + return function(obj) { + return _.isMatch(obj, attrs); + }; + }; + + // Run a function **n** times. + _.times = function(n, iteratee, context) { + var accum = Array(Math.max(0, n)); + iteratee = optimizeCb(iteratee, context, 1); + for (var i = 0; i < n; i++) accum[i] = iteratee(i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { + return new Date().getTime(); + }; + + // List of HTML entities for escaping. + var escapeMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + var unescapeMap = _.invert(escapeMap); + + // Functions for escaping and unescaping strings to/from HTML interpolation. + var createEscaper = function(map) { + var escaper = function(match) { + return map[match]; + }; + // Regexes for identifying a key that needs to be escaped + var source = '(?:' + _.keys(map).join('|') + ')'; + var testRegexp = RegExp(source); + var replaceRegexp = RegExp(source, 'g'); + return function(string) { + string = string == null ? '' : '' + string; + return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; + }; + }; + _.escape = createEscaper(escapeMap); + _.unescape = createEscaper(unescapeMap); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property, fallback) { + var value = object == null ? void 0 : object[property]; + if (value === void 0) { + value = fallback; + } + return _.isFunction(value) ? value.call(object) : value; + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\u2028|\u2029/g; + + var escapeChar = function(match) { + return '\\' + escapes[match]; + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + // NB: `oldSettings` only exists for backwards compatibility. + _.template = function(text, settings, oldSettings) { + if (!settings && oldSettings) settings = oldSettings; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset).replace(escaper, escapeChar); + index = offset + match.length; + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } else if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } else if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + + // Adobe VMs need the match returned to produce the correct offest. + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + 'return __p;\n'; + + try { + var render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled source as a convenience for precompilation. + var argument = settings.variable || 'obj'; + template.source = 'function(' + argument + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function. Start chaining a wrapped Underscore object. + _.chain = function(obj) { + var instance = _(obj); + instance._chain = true; + return instance; + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(instance, obj) { + return instance._chain ? _(obj).chain() : obj; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + _.each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result(this, func.apply(_, args)); + }; + }); + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; + return result(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + _.each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result(this, method.apply(this._wrapped, arguments)); + }; + }); + + // Extracts the result from a wrapped and chained object. + _.prototype.value = function() { + return this._wrapped; + }; + + // Provide unwrapping proxy for some methods used in engine operations + // such as arithmetic and JSON stringification. + _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; + + _.prototype.toString = function() { + return '' + this._wrapped; + }; + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}.call(this)); + +},{}],26:[function(require,module,exports){ +arguments[4][19][0].apply(exports,arguments) +},{"dup":19}],27:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],28:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":27,"_process":24,"inherits":26}],29:[function(require,module,exports){ +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} + +},{}]},{},[7])(7) +}); \ No newline at end of file diff --git a/1.13/assets/javascripts/workers/search.1e90e0fb.min.js b/1.13/assets/javascripts/workers/search.1e90e0fb.min.js new file mode 100644 index 000000000..ff43aeddd --- /dev/null +++ b/1.13/assets/javascripts/workers/search.1e90e0fb.min.js @@ -0,0 +1,2 @@ +"use strict";(()=>{var xe=Object.create;var G=Object.defineProperty,ve=Object.defineProperties,Se=Object.getOwnPropertyDescriptor,Te=Object.getOwnPropertyDescriptors,Qe=Object.getOwnPropertyNames,Y=Object.getOwnPropertySymbols,Ee=Object.getPrototypeOf,X=Object.prototype.hasOwnProperty,be=Object.prototype.propertyIsEnumerable;var Z=Math.pow,J=(t,e,r)=>e in t?G(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,_=(t,e)=>{for(var r in e||(e={}))X.call(e,r)&&J(t,r,e[r]);if(Y)for(var r of Y(e))be.call(e,r)&&J(t,r,e[r]);return t},B=(t,e)=>ve(t,Te(e));var Le=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var we=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Qe(e))!X.call(t,i)&&i!==r&&G(t,i,{get:()=>e[i],enumerable:!(n=Se(e,i))||n.enumerable});return t};var Pe=(t,e,r)=>(r=t!=null?xe(Ee(t)):{},we(e||!t||!t.__esModule?G(r,"default",{value:t,enumerable:!0}):r,t));var W=(t,e,r)=>new Promise((n,i)=>{var s=u=>{try{a(r.next(u))}catch(c){i(c)}},o=u=>{try{a(r.throw(u))}catch(c){i(c)}},a=u=>u.done?n(u.value):Promise.resolve(u.value).then(s,o);a((r=r.apply(t,e)).next())});var te=Le((K,ee)=>{(function(){var t=function(e){var r=new t.Builder;return r.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),r.searchPipeline.add(t.stemmer),e.call(r,r),r.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(r){e.console&&console.warn&&console.warn(r)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var r=Object.create(null),n=Object.keys(e),i=0;i0){var f=t.utils.clone(r)||{};f.position=[a,c],f.index=s.length,s.push(new t.Token(n.slice(a,o),f))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,r){r in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+r),e.label=r,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var r=e.label&&e.label in this.registeredFunctions;r||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,e)},t.Pipeline.load=function(e){var r=new t.Pipeline;return e.forEach(function(n){var i=t.Pipeline.registeredFunctions[n];if(i)r.add(i);else throw new Error("Cannot load unregistered function: "+n)}),r},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(r){t.Pipeline.warnIfFunctionNotRegistered(r),this._stack.push(r)},this)},t.Pipeline.prototype.after=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");n=n+1,this._stack.splice(n,0,r)},t.Pipeline.prototype.before=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");this._stack.splice(n,0,r)},t.Pipeline.prototype.remove=function(e){var r=this._stack.indexOf(e);r!=-1&&this._stack.splice(r,1)},t.Pipeline.prototype.run=function(e){for(var r=this._stack.length,n=0;n1&&(oe&&(n=s),o!=e);)i=n-r,s=r+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ou?f+=2:a==u&&(r+=n[c+1]*i[f+1],c+=2,f+=2);return r},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),r=1,n=0;r0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}if(s.str.length==0&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}s.str.length==1&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var f=s.str.charAt(0),g=s.str.charAt(1),l;g in s.node.edges?l=s.node.edges[g]:(l=new t.TokenSet,s.node.edges[g]=l),s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:f+s.str.slice(2)})}}}return n},t.TokenSet.fromString=function(e){for(var r=new t.TokenSet,n=r,i=0,s=e.length;i=e;r--){var n=this.uncheckedNodes[r],i=n.child.toString();i in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[i]:(n.child._str=i,this.minimizedNodes[i]=n.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(r){var n=new t.QueryParser(e,r);n.parse()})},t.Index.prototype.query=function(e){for(var r=new t.Query(this.fields),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,r){var n=e[this._ref],i=Object.keys(this._fields);this._documents[n]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,r;do e=this.next(),r=e.charCodeAt(0);while(r>47&&r<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var r=e.next();if(r==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(r.charCodeAt(0)==92){e.escapeCharacter();continue}if(r==":")return t.QueryLexer.lexField;if(r=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(r=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(r=="+"&&e.width()===1||r=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(r.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,r){this.lexer=new t.QueryLexer(e),this.query=r,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var r=e.peekLexeme();if(r!=null)switch(r.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(n+=" with value '"+r.str+"'"),new t.QueryParseError(n,r.start,r.end)}},t.QueryParser.parsePresence=function(e){var r=e.consumeLexeme();if(r!=null){switch(r.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+r.str+"'";throw new t.QueryParseError(n,r.start,r.end)}var i=e.peekLexeme();if(i==null){var n="expecting term or field, found nothing";throw new t.QueryParseError(n,r.start,r.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(n,i.start,i.end)}}},t.QueryParser.parseField=function(e){var r=e.consumeLexeme();if(r!=null){if(e.query.allFields.indexOf(r.str)==-1){var n=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+r.str+"', possible fields: "+n;throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.fields=[r.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,r.start,r.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var r=e.consumeLexeme();if(r!=null){e.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(n==null){e.nextClause();return}switch(n.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+n.type+"'";throw new t.QueryParseError(i,n.start,n.end)}}},t.QueryParser.parseEditDistance=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="edit distance must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.editDistance=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="boost must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.boost=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,r){typeof define=="function"&&define.amd?define(r):typeof K=="object"?ee.exports=r():e.lunr=r()}(this,function(){return t})})()});var de=Pe(te());function re(t,e=document){let r=ke(t,e);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${t}" to be present`);return r}function ke(t,e=document){return e.querySelector(t)||void 0}Object.entries||(Object.entries=function(t){let e=[];for(let r of Object.keys(t))e.push([r,t[r]]);return e});Object.values||(Object.values=function(t){let e=[];for(let r of Object.keys(t))e.push(t[r]);return e});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(t,e){typeof t=="object"?(this.scrollLeft=t.left,this.scrollTop=t.top):(this.scrollLeft=t,this.scrollTop=e)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...t){let e=this.parentNode;if(e){t.length===0&&e.removeChild(this);for(let r=t.length-1;r>=0;r--){let n=t[r];typeof n=="string"?n=document.createTextNode(n):n.parentNode&&n.parentNode.removeChild(n),r?e.insertBefore(this.previousSibling,n):e.replaceChild(n,this)}}}));function ne(t){let e=new Map;for(let r of t){let[n]=r.location.split("#"),i=e.get(n);typeof i=="undefined"?e.set(n,r):(e.set(r.location,r),r.parent=i)}return e}function H(t,e,r){var s;e=new RegExp(e,"g");let n,i=0;do{n=e.exec(t);let o=(s=n==null?void 0:n.index)!=null?s:t.length;if(in?e(r,1,n,n=i):t.charAt(i)===">"&&(t.charAt(n+1)==="/"?--s===0&&e(r++,2,n,i+1):t.charAt(i-1)!=="/"&&s++===0&&e(r,0,n,i+1),n=i+1);i>n&&e(r,1,n,i)}function se(t,e,r,n=!1){return q([t],e,r,n).pop()}function q(t,e,r,n=!1){let i=[0];for(let s=1;s>>2&1023,c=a[0]>>>12;i.push(+(u>c)+i[i.length-1])}return t.map((s,o)=>{let a=0,u=new Map;for(let f of r.sort((g,l)=>g-l)){let g=f&1048575,l=f>>>20;if(i[l]!==o)continue;let m=u.get(l);typeof m=="undefined"&&u.set(l,m=[]),m.push(g)}if(u.size===0)return s;let c=[];for(let[f,g]of u){let l=e[f],m=l[0]>>>12,x=l[l.length-1]>>>12,v=l[l.length-1]>>>2&1023;n&&m>a&&c.push(s.slice(a,m));let d=s.slice(m,x+v);for(let y of g.sort((b,E)=>E-b)){let b=(l[y]>>>12)-m,E=(l[y]>>>2&1023)+b;d=[d.slice(0,b),"",d.slice(b,E),"",d.slice(E)].join("")}if(a=x+v,c.push(d)===2)break}return n&&a{var f;switch(i[f=o+=s]||(i[f]=[]),a){case 0:case 2:i[o].push(u<<12|c-u<<2|a);break;case 1:let g=r[n].slice(u,c);H(g,lunr.tokenizer.separator,(l,m)=>{if(typeof lunr.segmenter!="undefined"){let x=g.slice(l,m);if(/^[MHIK]$/.test(lunr.segmenter.ctype_(x))){let v=lunr.segmenter.segment(x);for(let d=0,y=0;dr){return t.trim().split(/"([^"]+)"/g).map((r,n)=>n&1?r.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):r).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").split(/\s+/g).reduce((r,n)=>{let i=e(n);return[...r,...Array.isArray(i)?i:[i]]},[]).map(r=>/([~^]$)/.test(r)?`${r}1`:r).map(r=>/(^[+-]|[~^]\d+$)/.test(r)?r:`${r}*`).join(" ")}function ue(t){return ae(t,e=>{let r=[],n=new lunr.QueryLexer(e);n.run();for(let{type:i,str:s,start:o,end:a}of n.lexemes)switch(i){case"FIELD":["title","text","tags"].includes(s)||(e=[e.slice(0,a)," ",e.slice(a+1)].join(""));break;case"TERM":H(s,lunr.tokenizer.separator,(...u)=>{r.push([e.slice(0,o),s.slice(...u),e.slice(a)].join(""))})}return r})}function ce(t){let e=new lunr.Query(["title","text","tags"]);new lunr.QueryParser(t,e).parse();for(let n of e.clauses)n.usePipeline=!0,n.term.startsWith("*")&&(n.wildcard=lunr.Query.wildcard.LEADING,n.term=n.term.slice(1)),n.term.endsWith("*")&&(n.wildcard=lunr.Query.wildcard.TRAILING,n.term=n.term.slice(0,-1));return e.clauses}function le(t,e){var i;let r=new Set(t),n={};for(let s=0;s0;){let o=i[--s];for(let u=1;un[o]-u&&(r.add(t.slice(o,o+u)),i[s++]=o+u);let a=o+n[o];n[a]&&ar=>{if(typeof r[e]=="undefined")return;let n=[r.location,e].join(":");return t.set(n,lunr.tokenizer.table=[]),r[e]}}function Re(t,e){let[r,n]=[new Set(t),new Set(e)];return[...new Set([...r].filter(i=>!n.has(i)))]}var U=class{constructor({config:e,docs:r,options:n}){let i=Oe(this.table=new Map);this.map=ne(r),this.options=n,this.index=lunr(function(){this.metadataWhitelist=["position"],this.b(0),e.lang.length===1&&e.lang[0]!=="en"?this.use(lunr[e.lang[0]]):e.lang.length>1&&this.use(lunr.multiLanguage(...e.lang)),this.tokenizer=oe,lunr.tokenizer.separator=new RegExp(e.separator),lunr.segmenter="TinySegmenter"in lunr?new lunr.TinySegmenter:void 0;let s=Re(["trimmer","stopWordFilter","stemmer"],e.pipeline);for(let o of e.lang.map(a=>a==="en"?lunr:lunr[a]))for(let a of s)this.pipeline.remove(o[a]),this.searchPipeline.remove(o[a]);this.ref("location");for(let[o,a]of Object.entries(e.fields))this.field(o,B(_({},a),{extractor:i(o)}));for(let o of r)this.add(o,{boost:o.boost})})}search(e){if(e=e.replace(new RegExp("\\p{sc=Han}+","gu"),s=>[...he(s,this.index.invertedIndex)].join("* ")),e=ue(e),!e)return{items:[]};let r=ce(e).filter(s=>s.presence!==lunr.Query.presence.PROHIBITED),n=this.index.search(e).reduce((s,{ref:o,score:a,matchData:u})=>{let c=this.map.get(o);if(typeof c!="undefined"){c=_({},c),c.tags&&(c.tags=[...c.tags]);let f=le(r,Object.keys(u.metadata));for(let l of this.index.fields){if(typeof c[l]=="undefined")continue;let m=[];for(let d of Object.values(u.metadata))typeof d[l]!="undefined"&&m.push(...d[l].position);if(!m.length)continue;let x=this.table.get([c.location,l].join(":")),v=Array.isArray(c[l])?q:se;c[l]=v(c[l],x,m,l!=="text")}let g=+!c.parent+Object.values(f).filter(l=>l).length/Object.keys(f).length;s.push(B(_({},c),{score:a*(1+Z(g,2)),terms:f}))}return s},[]).sort((s,o)=>o.score-s.score).reduce((s,o)=>{let a=this.map.get(o.location);if(typeof a!="undefined"){let u=a.parent?a.parent.location:a.location;s.set(u,[...s.get(u)||[],o])}return s},new Map);for(let[s,o]of n)if(!o.find(a=>a.location===s)){let a=this.map.get(s);o.push(B(_({},a),{score:0,terms:{}}))}let i;if(this.options.suggest){let s=this.index.query(o=>{for(let a of r)o.term(a.term,{fields:["title"],presence:lunr.Query.presence.REQUIRED,wildcard:lunr.Query.wildcard.TRAILING})});i=s.length?Object.keys(s[0].matchData.metadata):[]}return _({items:[...n.values()]},typeof i!="undefined"&&{suggest:i})}};var fe;function Ie(t){return W(this,null,function*(){let e="../lunr";if(typeof parent!="undefined"&&"IFrameWorker"in parent){let n=re("script[src]"),[i]=n.src.split("/worker");e=e.replace("..",i)}let r=[];for(let n of t.lang){switch(n){case"ja":r.push(`${e}/tinyseg.js`);break;case"hi":case"th":r.push(`${e}/wordcut.js`);break}n!=="en"&&r.push(`${e}/min/lunr.${n}.min.js`)}t.lang.length>1&&r.push(`${e}/min/lunr.multi.min.js`),r.length&&(yield importScripts(`${e}/min/lunr.stemmer.support.min.js`,...r))})}function Fe(t){return W(this,null,function*(){switch(t.type){case 0:return yield Ie(t.data.config),fe=new U(t.data),{type:1};case 2:let e=t.data;try{return{type:3,data:fe.search(e)}}catch(r){return console.warn(`Invalid query: ${e} \u2013 see https://bit.ly/2s3ChXG`),console.warn(r),{type:3,data:{items:[]}}}default:throw new TypeError("Invalid message type")}})}self.lunr=de.default;addEventListener("message",t=>W(void 0,null,function*(){postMessage(yield Fe(t.data))}));})(); diff --git a/1.13/assets/stylesheets/glightbox.min.css b/1.13/assets/stylesheets/glightbox.min.css new file mode 100644 index 000000000..3c9ff8775 --- /dev/null +++ b/1.13/assets/stylesheets/glightbox.min.css @@ -0,0 +1 @@ +.glightbox-container{width:100%;height:100%;position:fixed;top:0;left:0;z-index:999999!important;overflow:hidden;-ms-touch-action:none;touch-action:none;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;outline:0}.glightbox-container.inactive{display:none}.glightbox-container .gcontainer{position:relative;width:100%;height:100%;z-index:9999;overflow:hidden}.glightbox-container .gslider{-webkit-transition:-webkit-transform .4s ease;transition:-webkit-transform .4s ease;transition:transform .4s ease;transition:transform .4s ease,-webkit-transform .4s ease;height:100%;left:0;top:0;width:100%;position:relative;overflow:hidden;display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.glightbox-container .gslide{width:100%;position:absolute;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;opacity:0}.glightbox-container .gslide.current{opacity:1;z-index:99999;position:relative}.glightbox-container .gslide.prev{opacity:1;z-index:9999}.glightbox-container .gslide-inner-content{width:100%}.glightbox-container .ginner-container{position:relative;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-width:100%;margin:auto;height:100vh}.glightbox-container .ginner-container.gvideo-container{width:100%}.glightbox-container .ginner-container.desc-bottom,.glightbox-container .ginner-container.desc-top{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.glightbox-container .ginner-container.desc-left,.glightbox-container .ginner-container.desc-right{max-width:100%!important}.gslide iframe,.gslide video{outline:0!important;border:none;min-height:165px;-webkit-overflow-scrolling:touch;-ms-touch-action:auto;touch-action:auto}.gslide:not(.current){pointer-events:none}.gslide-image{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.gslide-image img{max-height:100vh;display:block;padding:0;float:none;outline:0;border:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;max-width:100vw;width:auto;height:auto;-o-object-fit:cover;object-fit:cover;-ms-touch-action:none;touch-action:none;margin:auto;min-width:200px}.desc-bottom .gslide-image img,.desc-top .gslide-image img{width:auto}.desc-left .gslide-image img,.desc-right .gslide-image img{width:auto;max-width:100%}.gslide-image img.zoomable{position:relative}.gslide-image img.dragging{cursor:-webkit-grabbing!important;cursor:grabbing!important;-webkit-transition:none;transition:none}.gslide-video{position:relative;max-width:100vh;width:100%!important}.gslide-video .plyr__poster-enabled.plyr--loading .plyr__poster{display:none}.gslide-video .gvideo-wrapper{width:100%;margin:auto}.gslide-video::before{content:'';position:absolute;width:100%;height:100%;background:rgba(255,0,0,.34);display:none}.gslide-video.playing::before{display:none}.gslide-video.fullscreen{max-width:100%!important;min-width:100%;height:75vh}.gslide-video.fullscreen video{max-width:100%!important;width:100%!important}.gslide-inline{background:#fff;text-align:left;max-height:calc(100vh - 40px);overflow:auto;max-width:100%;margin:auto}.gslide-inline .ginlined-content{padding:20px;width:100%}.gslide-inline .dragging{cursor:-webkit-grabbing!important;cursor:grabbing!important;-webkit-transition:none;transition:none}.ginlined-content{overflow:auto;display:block!important;opacity:1}.gslide-external{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;min-width:100%;background:#fff;padding:0;overflow:auto;max-height:75vh;height:100%}.gslide-media{display:-webkit-box;display:-ms-flexbox;display:flex;width:auto}.zoomed .gslide-media{-webkit-box-shadow:none!important;box-shadow:none!important}.desc-bottom .gslide-media,.desc-top .gslide-media{margin:0 auto;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.gslide-description{position:relative;-webkit-box-flex:1;-ms-flex:1 0 100%;flex:1 0 100%}.gslide-description.description-left,.gslide-description.description-right{max-width:100%}.gslide-description.description-bottom,.gslide-description.description-top{margin:0 auto;width:100%}.gslide-description p{margin-bottom:12px}.gslide-description p:last-child{margin-bottom:0}.zoomed .gslide-description{display:none}.glightbox-button-hidden{display:none}.glightbox-mobile .glightbox-container .gslide-description{height:auto!important;width:100%;position:absolute;bottom:0;padding:19px 11px;max-width:100vw!important;-webkit-box-ordinal-group:3!important;-ms-flex-order:2!important;order:2!important;max-height:78vh;overflow:auto!important;background:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,.75)));background:linear-gradient(to bottom,rgba(0,0,0,0) 0,rgba(0,0,0,.75) 100%);-webkit-transition:opacity .3s linear;transition:opacity .3s linear;padding-bottom:50px}.glightbox-mobile .glightbox-container .gslide-title{color:#fff;font-size:1em}.glightbox-mobile .glightbox-container .gslide-desc{color:#a1a1a1}.glightbox-mobile .glightbox-container .gslide-desc a{color:#fff;font-weight:700}.glightbox-mobile .glightbox-container .gslide-desc *{color:inherit}.glightbox-mobile .glightbox-container .gslide-desc .desc-more{color:#fff;opacity:.4}.gdesc-open .gslide-media{-webkit-transition:opacity .5s ease;transition:opacity .5s ease;opacity:.4}.gdesc-open .gdesc-inner{padding-bottom:30px}.gdesc-closed .gslide-media{-webkit-transition:opacity .5s ease;transition:opacity .5s ease;opacity:1}.greset{-webkit-transition:all .3s ease;transition:all .3s ease}.gabsolute{position:absolute}.grelative{position:relative}.glightbox-desc{display:none!important}.glightbox-open{overflow:hidden}.gloader{height:25px;width:25px;-webkit-animation:lightboxLoader .8s infinite linear;animation:lightboxLoader .8s infinite linear;border:2px solid #fff;border-right-color:transparent;border-radius:50%;position:absolute;display:block;z-index:9999;left:0;right:0;margin:0 auto;top:47%}.goverlay{width:100%;height:calc(100vh + 1px);position:fixed;top:-1px;left:0;background:#000;will-change:opacity}.glightbox-mobile .goverlay{background:#000}.gclose,.gnext,.gprev{z-index:99999;cursor:pointer;width:26px;height:44px;border:none;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.gclose svg,.gnext svg,.gprev svg{display:block;width:25px;height:auto;margin:0;padding:0}.gclose.disabled,.gnext.disabled,.gprev.disabled{opacity:.1}.gclose .garrow,.gnext .garrow,.gprev .garrow{stroke:#fff}.gbtn.focused{outline:2px solid #0f3d81}iframe.wait-autoplay{opacity:0}.glightbox-closing .gclose,.glightbox-closing .gnext,.glightbox-closing .gprev{opacity:0!important}.glightbox-clean .gslide-description{background:#fff}.glightbox-clean .gdesc-inner{padding:22px 20px}.glightbox-clean .gslide-title{font-size:1em;font-weight:400;font-family:arial;color:#000;margin-bottom:19px;line-height:1.4em}.glightbox-clean .gslide-desc{font-size:.86em;margin-bottom:0;font-family:arial;line-height:1.4em}.glightbox-clean .gslide-video{background:#000}.glightbox-clean .gclose,.glightbox-clean .gnext,.glightbox-clean .gprev{background-color:rgba(0,0,0,.75);border-radius:4px}.glightbox-clean .gclose path,.glightbox-clean .gnext path,.glightbox-clean .gprev path{fill:#fff}.glightbox-clean .gprev{position:absolute;top:-100%;left:30px;width:40px;height:50px}.glightbox-clean .gnext{position:absolute;top:-100%;right:30px;width:40px;height:50px}.glightbox-clean .gclose{width:35px;height:35px;top:15px;right:10px;position:absolute}.glightbox-clean .gclose svg{width:18px;height:auto}.glightbox-clean .gclose:hover{opacity:1}.gfadeIn{-webkit-animation:gfadeIn .5s ease;animation:gfadeIn .5s ease}.gfadeOut{-webkit-animation:gfadeOut .5s ease;animation:gfadeOut .5s ease}.gslideOutLeft{-webkit-animation:gslideOutLeft .3s ease;animation:gslideOutLeft .3s ease}.gslideInLeft{-webkit-animation:gslideInLeft .3s ease;animation:gslideInLeft .3s ease}.gslideOutRight{-webkit-animation:gslideOutRight .3s ease;animation:gslideOutRight .3s ease}.gslideInRight{-webkit-animation:gslideInRight .3s ease;animation:gslideInRight .3s ease}.gzoomIn{-webkit-animation:gzoomIn .5s ease;animation:gzoomIn .5s ease}.gzoomOut{-webkit-animation:gzoomOut .5s ease;animation:gzoomOut .5s ease}@-webkit-keyframes lightboxLoader{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes lightboxLoader{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes gfadeIn{from{opacity:0}to{opacity:1}}@keyframes gfadeIn{from{opacity:0}to{opacity:1}}@-webkit-keyframes gfadeOut{from{opacity:1}to{opacity:0}}@keyframes gfadeOut{from{opacity:1}to{opacity:0}}@-webkit-keyframes gslideInLeft{from{opacity:0;-webkit-transform:translate3d(-60%,0,0);transform:translate3d(-60%,0,0)}to{visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes gslideInLeft{from{opacity:0;-webkit-transform:translate3d(-60%,0,0);transform:translate3d(-60%,0,0)}to{visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes gslideOutLeft{from{opacity:1;visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(-60%,0,0);transform:translate3d(-60%,0,0);opacity:0;visibility:hidden}}@keyframes gslideOutLeft{from{opacity:1;visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(-60%,0,0);transform:translate3d(-60%,0,0);opacity:0;visibility:hidden}}@-webkit-keyframes gslideInRight{from{opacity:0;visibility:visible;-webkit-transform:translate3d(60%,0,0);transform:translate3d(60%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes gslideInRight{from{opacity:0;visibility:visible;-webkit-transform:translate3d(60%,0,0);transform:translate3d(60%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes gslideOutRight{from{opacity:1;visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(60%,0,0);transform:translate3d(60%,0,0);opacity:0}}@keyframes gslideOutRight{from{opacity:1;visibility:visible;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{-webkit-transform:translate3d(60%,0,0);transform:translate3d(60%,0,0);opacity:0}}@-webkit-keyframes gzoomIn{from{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:1}}@keyframes gzoomIn{from{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:1}}@-webkit-keyframes gzoomOut{from{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}@keyframes gzoomOut{from{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}@media (min-width:769px){.glightbox-container .ginner-container{width:auto;height:auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.glightbox-container .ginner-container.desc-top .gslide-description{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.glightbox-container .ginner-container.desc-top .gslide-image,.glightbox-container .ginner-container.desc-top .gslide-image img{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.glightbox-container .ginner-container.desc-left .gslide-description{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.glightbox-container .ginner-container.desc-left .gslide-image{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.gslide-image img{max-height:97vh;max-width:100%}.gslide-image img.zoomable{cursor:-webkit-zoom-in;cursor:zoom-in}.zoomed .gslide-image img.zoomable{cursor:-webkit-grab;cursor:grab}.gslide-inline{max-height:95vh}.gslide-external{max-height:100vh}.gslide-description.description-left,.gslide-description.description-right{max-width:275px}.glightbox-open{height:auto}.goverlay{background:rgba(0,0,0,.92)}.glightbox-clean .gslide-media{-webkit-box-shadow:1px 2px 9px 0 rgba(0,0,0,.65);box-shadow:1px 2px 9px 0 rgba(0,0,0,.65)}.glightbox-clean .description-left .gdesc-inner,.glightbox-clean .description-right .gdesc-inner{position:absolute;height:100%;overflow-y:auto}.glightbox-clean .gclose,.glightbox-clean .gnext,.glightbox-clean .gprev{background-color:rgba(0,0,0,.32)}.glightbox-clean .gclose:hover,.glightbox-clean .gnext:hover,.glightbox-clean .gprev:hover{background-color:rgba(0,0,0,.7)}.glightbox-clean .gprev{top:45%}.glightbox-clean .gnext{top:45%}}@media (min-width:992px){.glightbox-clean .gclose{opacity:.7;right:20px}}@media screen and (max-height:420px){.goverlay{background:#000}} \ No newline at end of file diff --git a/1.13/assets/stylesheets/main.c0d16a3a.min.css b/1.13/assets/stylesheets/main.c0d16a3a.min.css new file mode 100644 index 000000000..344d70aa8 --- /dev/null +++ b/1.13/assets/stylesheets/main.c0d16a3a.min.css @@ -0,0 +1 @@ +@charset "UTF-8";html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;box-sizing:border-box}*,:after,:before{box-sizing:inherit}@media (prefers-reduced-motion){*,:after,:before{transition:none!important}}body{margin:0}a,button,input,label{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{border:0;box-sizing:initial;display:block;height:.05rem;overflow:visible;padding:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:initial;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{background:#0000;border:0;font-family:inherit;font-size:inherit;margin:0;padding:0}input{border:0;outline:none}:root{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:#526cfe1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-scheme=default]{color-scheme:light}[data-md-color-scheme=default] img[src$="#gh-dark-mode-only"],[data-md-color-scheme=default] img[src$="#only-dark"]{display:none}:root,[data-md-color-scheme=default]{--md-hue:225deg;--md-default-fg-color:#000000de;--md-default-fg-color--light:#0000008a;--md-default-fg-color--lighter:#00000052;--md-default-fg-color--lightest:#00000012;--md-default-bg-color:#fff;--md-default-bg-color--light:#ffffffb3;--md-default-bg-color--lighter:#ffffff4d;--md-default-bg-color--lightest:#ffffff1f;--md-code-fg-color:#36464e;--md-code-bg-color:#f5f5f5;--md-code-bg-color--light:#f5f5f5b3;--md-code-bg-color--lighter:#f5f5f54d;--md-code-hl-color:#4287ff;--md-code-hl-color--light:#4287ff1a;--md-code-hl-number-color:#d52a2a;--md-code-hl-special-color:#db1457;--md-code-hl-function-color:#a846b9;--md-code-hl-constant-color:#6e59d9;--md-code-hl-keyword-color:#3f6ec6;--md-code-hl-string-color:#1c7d4d;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-del-color:#f5503d26;--md-typeset-ins-color:#0bd57026;--md-typeset-kbd-color:#fafafa;--md-typeset-kbd-accent-color:#fff;--md-typeset-kbd-border-color:#b8b8b8;--md-typeset-mark-color:#ffff0080;--md-typeset-table-color:#0000001f;--md-typeset-table-color--light:rgba(0,0,0,.035);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-warning-fg-color:#000000de;--md-warning-bg-color:#ff9;--md-footer-fg-color:#fff;--md-footer-fg-color--light:#ffffffb3;--md-footer-fg-color--lighter:#ffffff73;--md-footer-bg-color:#000000de;--md-footer-bg-color--dark:#00000052;--md-shadow-z1:0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;--md-shadow-z2:0 0.2rem 0.5rem #0000001a,0 0 0.05rem #00000040;--md-shadow-z3:0 0.2rem 0.5rem #0003,0 0 0.05rem #00000059}.md-icon svg{fill:currentcolor;display:block;height:1.2rem;width:1.2rem}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--md-text-font-family:var(--md-text-font,_),-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;--md-code-font-family:var(--md-code-font,_),SFMono-Regular,Consolas,Menlo,monospace}aside,body,input{font-feature-settings:"kern","liga";color:var(--md-typeset-color);font-family:var(--md-text-font-family)}code,kbd,pre{font-feature-settings:"kern";font-family:var(--md-code-font-family)}:root{--md-typeset-table-sort-icon:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--asc:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--desc:url('data:image/svg+xml;charset=utf-8,')}.md-typeset{-webkit-print-color-adjust:exact;color-adjust:exact;font-size:.8rem;line-height:1.6}@media print{.md-typeset{font-size:.68rem}}.md-typeset blockquote,.md-typeset dl,.md-typeset figure,.md-typeset ol,.md-typeset pre,.md-typeset ul{margin-bottom:1em;margin-top:1em}.md-typeset h1{color:var(--md-default-fg-color--light);font-size:2em;line-height:1.3;margin:0 0 1.25em}.md-typeset h1,.md-typeset h2{font-weight:300;letter-spacing:-.01em}.md-typeset h2{font-size:1.5625em;line-height:1.4;margin:1.6em 0 .64em}.md-typeset h3{font-size:1.25em;font-weight:400;letter-spacing:-.01em;line-height:1.5;margin:1.6em 0 .8em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{font-weight:700;letter-spacing:-.01em;margin:1em 0}.md-typeset h5,.md-typeset h6{color:var(--md-default-fg-color--light);font-size:.8em;font-weight:700;letter-spacing:-.01em;margin:1.25em 0}.md-typeset h5{text-transform:uppercase}.md-typeset hr{border-bottom:.05rem solid var(--md-default-fg-color--lightest);display:flow-root;margin:1.5em 0}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a:before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset a:focus code,.md-typeset a:hover code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-typeset a code{color:var(--md-typeset-a-color)}.md-typeset a.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset code,.md-typeset kbd,.md-typeset pre{color:var(--md-code-fg-color);direction:ltr;font-variant-ligatures:none;transition:background-color 125ms}@media print{.md-typeset code,.md-typeset kbd,.md-typeset pre{white-space:pre-wrap}}.md-typeset code{background-color:var(--md-code-bg-color);border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone;font-size:.85em;padding:0 .2941176471em;transition:color 125ms,background-color 125ms;word-break:break-word}.md-typeset code:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-typeset pre{display:flow-root;line-height:1.4;position:relative}.md-typeset pre>code{-webkit-box-decoration-break:slice;box-decoration-break:slice;box-shadow:none;display:block;margin:0;outline-color:var(--md-accent-fg-color);overflow:auto;padding:.7720588235em 1.1764705882em;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin;touch-action:auto;word-break:normal}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-typeset pre>code::-webkit-scrollbar{height:.2rem;width:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}.md-typeset kbd{background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -.1rem .2rem var(--md-typeset-kbd-accent-color) inset;color:var(--md-default-fg-color);display:inline-block;font-size:.75em;padding:0 .6666666667em;vertical-align:text-top;word-break:break-word}.md-typeset mark{background-color:var(--md-typeset-mark-color);-webkit-box-decoration-break:clone;box-decoration-break:clone;color:inherit;word-break:break-word}.md-typeset abbr{cursor:help;text-decoration:none}.md-typeset [data-preview],.md-typeset abbr{border-bottom:.05rem dotted var(--md-default-fg-color--light)}.md-typeset small{opacity:.75}[dir=ltr] .md-typeset sub,[dir=ltr] .md-typeset sup{margin-left:.078125em}[dir=rtl] .md-typeset sub,[dir=rtl] .md-typeset sup{margin-right:.078125em}[dir=ltr] .md-typeset blockquote{padding-left:.6rem}[dir=rtl] .md-typeset blockquote{padding-right:.6rem}[dir=ltr] .md-typeset blockquote{border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{border-right:.2rem solid var(--md-default-fg-color--lighter)}.md-typeset blockquote{color:var(--md-default-fg-color--light);margin-left:0;margin-right:0}.md-typeset ul{list-style-type:disc}[dir=ltr] .md-typeset ol,[dir=ltr] .md-typeset ul{margin-left:.625em}[dir=rtl] .md-typeset ol,[dir=rtl] .md-typeset ul{margin-right:.625em}.md-typeset ol,.md-typeset ul{padding:0}.md-typeset ol:not([hidden]),.md-typeset ul:not([hidden]){display:flow-root}.md-typeset ol ol,.md-typeset ul ol{list-style-type:lower-alpha}.md-typeset ol ol ol,.md-typeset ul ol ol{list-style-type:lower-roman}[dir=ltr] .md-typeset ol li,[dir=ltr] .md-typeset ul li{margin-left:1.25em}[dir=rtl] .md-typeset ol li,[dir=rtl] .md-typeset ul li{margin-right:1.25em}.md-typeset ol li,.md-typeset ul li{margin-bottom:.5em}.md-typeset ol li blockquote,.md-typeset ol li p,.md-typeset ul li blockquote,.md-typeset ul li p{margin:.5em 0}.md-typeset ol li:last-child,.md-typeset ul li:last-child{margin-bottom:0}[dir=ltr] .md-typeset ol li ol,[dir=ltr] .md-typeset ol li ul,[dir=ltr] .md-typeset ul li ol,[dir=ltr] .md-typeset ul li ul{margin-left:.625em}[dir=rtl] .md-typeset ol li ol,[dir=rtl] .md-typeset ol li ul,[dir=rtl] .md-typeset ul li ol,[dir=rtl] .md-typeset ul li ul{margin-right:.625em}.md-typeset ol li ol,.md-typeset ol li ul,.md-typeset ul li ol,.md-typeset ul li ul{margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset dd{margin-left:1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em}.md-typeset dd{margin-bottom:1.5em;margin-top:1em}.md-typeset img,.md-typeset svg,.md-typeset video{height:auto;max-width:100%}.md-typeset img[align=left]{margin:1em 1em 1em 0}.md-typeset img[align=right]{margin:1em 0 1em 1em}.md-typeset img[align]:only-child{margin-top:0}.md-typeset figure{display:flow-root;margin:1em auto;max-width:100%;text-align:center;width:-moz-fit-content;width:fit-content}.md-typeset figure img{display:block;margin:0 auto}.md-typeset figcaption{font-style:italic;margin:1em auto;max-width:24rem}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){background-color:var(--md-default-bg-color);border:.05rem solid var(--md-typeset-table-color);border-radius:.1rem;display:inline-block;font-size:.64rem;max-width:100%;overflow:auto;touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) td>:first-child,.md-typeset table:not([class]) th>:first-child{margin-top:0}.md-typeset table:not([class]) td>:last-child,.md-typeset table:not([class]) th>:last-child{margin-bottom:0}.md-typeset table:not([class]) td:not([align]),.md-typeset table:not([class]) th:not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) td:not([align]),[dir=rtl] .md-typeset table:not([class]) th:not([align]){text-align:right}.md-typeset table:not([class]) th{font-weight:700;min-width:5rem;padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) td{border-top:.05rem solid var(--md-typeset-table-color);padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) tbody tr{transition:background-color 125ms}.md-typeset table:not([class]) tbody tr:hover{background-color:var(--md-typeset-table-color--light);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}[dir=ltr] .md-typeset table th[role=columnheader]:after{margin-left:.5em}[dir=rtl] .md-typeset table th[role=columnheader]:after{margin-right:.5em}.md-typeset table th[role=columnheader]:after{content:"";display:inline-block;height:1.2em;-webkit-mask-image:var(--md-typeset-table-sort-icon);mask-image:var(--md-typeset-table-sort-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset table th[role=columnheader]:hover:after{background-color:var(--md-default-fg-color--lighter)}.md-typeset table th[role=columnheader][aria-sort=ascending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--asc);mask-image:var(--md-typeset-table-sort-icon--asc)}.md-typeset table th[role=columnheader][aria-sort=descending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--desc);mask-image:var(--md-typeset-table-sort-icon--desc)}.md-typeset__scrollwrap{margin:1em -.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;margin:0;overflow:hidden;width:100%}@media screen and (max-width:44.984375em){.md-content__inner>pre{margin:1em -.8rem}.md-content__inner>pre code{border-radius:0}}.md-typeset .md-author{border-radius:100%;display:block;flex-shrink:0;height:1.6rem;overflow:hidden;position:relative;transition:color 125ms,transform 125ms;width:1.6rem}.md-typeset .md-author img{display:block}.md-typeset .md-author--more{background:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--lighter);font-size:.6rem;font-weight:700;line-height:1.6rem;text-align:center}.md-typeset .md-author--long{height:2.4rem;width:2.4rem}.md-typeset a.md-author{transform:scale(1)}.md-typeset a.md-author img{border-radius:100%;filter:grayscale(100%) opacity(75%);transition:filter 125ms}.md-typeset a.md-author:focus,.md-typeset a.md-author:hover{transform:scale(1.1);z-index:1}.md-typeset a.md-author:focus img,.md-typeset a.md-author:hover img{filter:grayscale(0)}.md-banner{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color);overflow:auto}@media print{.md-banner{display:none}}.md-banner--warning{background-color:var(--md-warning-bg-color);color:var(--md-warning-fg-color)}.md-banner__inner{font-size:.7rem;margin:.6rem auto;padding:0 .8rem}[dir=ltr] .md-banner__button{float:right}[dir=rtl] .md-banner__button{float:left}.md-banner__button{color:inherit;cursor:pointer;transition:opacity .25s}.no-js .md-banner__button{display:none}.md-banner__button:hover{opacity:.7}html{font-size:125%;height:100%;overflow-x:hidden}@media screen and (min-width:100em){html{font-size:137.5%}}@media screen and (min-width:125em){html{font-size:150%}}body{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;font-size:.5rem;min-height:100%;position:relative;width:100%}@media print{body{display:block}}@media screen and (max-width:59.984375em){body[data-md-scrolllock]{position:fixed}}.md-grid{margin-left:auto;margin-right:auto;max-width:61rem}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;text-overflow:ellipsis}.md-toggle{display:none}.md-option{height:0;opacity:0;position:absolute;width:0}.md-option:checked+label:not([hidden]){display:block}.md-option.focus-visible+label{outline-color:var(--md-accent-fg-color);outline-style:auto}.md-skip{background-color:var(--md-default-fg-color);border-radius:.1rem;color:var(--md-default-bg-color);font-size:.64rem;margin:.5rem;opacity:0;outline-color:var(--md-accent-fg-color);padding:.3rem .5rem;position:fixed;transform:translateY(.4rem);z-index:-1}.md-skip:focus{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 175ms 75ms;z-index:10}@page{margin:25mm}:root{--md-clipboard-icon:url('data:image/svg+xml;charset=utf-8,')}.md-clipboard{border-radius:.1rem;color:var(--md-default-fg-color--lightest);cursor:pointer;height:1.5em;outline-color:var(--md-accent-fg-color);outline-offset:.1rem;transition:color .25s;width:1.5em;z-index:1}@media print{.md-clipboard{display:none}}.md-clipboard:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:focus,.md-clipboard:hover{color:var(--md-accent-fg-color)}.md-clipboard:after{background-color:currentcolor;content:"";display:block;height:1.125em;margin:0 auto;-webkit-mask-image:var(--md-clipboard-icon);mask-image:var(--md-clipboard-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:1.125em}.md-clipboard--inline{cursor:pointer}.md-clipboard--inline code{transition:color .25s,background-color .25s}.md-clipboard--inline:focus code,.md-clipboard--inline:hover code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}:root{--md-code-select-icon:url('data:image/svg+xml;charset=utf-8,');--md-code-copy-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .md-code__content{display:grid}.md-code__nav{background-color:var(--md-code-bg-color--lighter);border-radius:.1rem;display:flex;gap:.2rem;padding:.2rem;position:absolute;right:.25em;top:.25em;transition:background-color .25s;z-index:1}:hover>.md-code__nav{background-color:var(--md-code-bg-color--light)}.md-code__button{color:var(--md-default-fg-color--lightest);cursor:pointer;display:block;height:1.5em;outline-color:var(--md-accent-fg-color);outline-offset:.1rem;transition:color .25s;width:1.5em}:hover>*>.md-code__button{color:var(--md-default-fg-color--light)}.md-code__button.focus-visible,.md-code__button:hover{color:var(--md-accent-fg-color)}.md-code__button--active{color:var(--md-default-fg-color)!important}.md-code__button:after{background-color:currentcolor;content:"";display:block;height:1.125em;margin:0 auto;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:1.125em}.md-code__button[data-md-type=select]:after{-webkit-mask-image:var(--md-code-select-icon);mask-image:var(--md-code-select-icon)}.md-code__button[data-md-type=copy]:after{-webkit-mask-image:var(--md-code-copy-icon);mask-image:var(--md-code-copy-icon)}@keyframes consent{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes overlay{0%{opacity:0}to{opacity:1}}.md-consent__overlay{animation:overlay .25s both;-webkit-backdrop-filter:blur(.1rem);backdrop-filter:blur(.1rem);background-color:#0000008a;height:100%;opacity:1;position:fixed;top:0;width:100%;z-index:5}.md-consent__inner{animation:consent .5s cubic-bezier(.1,.7,.1,1) both;background-color:var(--md-default-bg-color);border:0;border-radius:.1rem;bottom:0;box-shadow:0 0 .2rem #0000001a,0 .2rem .4rem #0003;max-height:100%;overflow:auto;padding:0;position:fixed;width:100%;z-index:5}.md-consent__form{padding:.8rem}.md-consent__settings{display:none;margin:1em 0}input:checked+.md-consent__settings{display:block}.md-consent__controls{margin-bottom:.8rem}.md-typeset .md-consent__controls .md-button{display:inline}@media screen and (max-width:44.984375em){.md-typeset .md-consent__controls .md-button{display:block;margin-top:.4rem;text-align:center;width:100%}}.md-consent label{cursor:pointer}.md-content{flex-grow:1;min-width:0}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width:76.25em){[dir=ltr] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=ltr] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner,[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}}.md-content__inner:before{content:"";display:block;height:.4rem}.md-content__inner>:last-child{margin-bottom:0}[dir=ltr] .md-content__button{float:right}[dir=rtl] .md-content__button{float:left}[dir=ltr] .md-content__button{margin-left:.4rem}[dir=rtl] .md-content__button{margin-right:.4rem}.md-content__button{margin:.4rem 0;padding:0}@media print{.md-content__button{display:none}}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}[dir=ltr] .md-dialog{right:.8rem}[dir=rtl] .md-dialog{left:.8rem}.md-dialog{background-color:var(--md-default-fg-color);border-radius:.1rem;bottom:.8rem;box-shadow:var(--md-shadow-z3);min-width:11.1rem;opacity:0;padding:.4rem .6rem;pointer-events:none;position:fixed;transform:translateY(100%);transition:transform 0ms .4s,opacity .4s;z-index:4}@media print{.md-dialog{display:none}}.md-dialog--active{opacity:1;pointer-events:auto;transform:translateY(0);transition:transform .4s cubic-bezier(.075,.85,.175,1),opacity .4s}.md-dialog__inner{color:var(--md-default-bg-color);font-size:.7rem}.md-feedback{margin:2em 0 1em;text-align:center}.md-feedback fieldset{border:none;margin:0;padding:0}.md-feedback__title{font-weight:700;margin:1em auto}.md-feedback__inner{position:relative}.md-feedback__list{display:flex;flex-wrap:wrap;place-content:baseline center;position:relative}.md-feedback__list:hover .md-icon:not(:disabled){color:var(--md-default-fg-color--lighter)}:disabled .md-feedback__list{min-height:1.8rem}.md-feedback__icon{color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;margin:0 .1rem;transition:color 125ms}.md-feedback__icon:not(:disabled).md-icon:hover{color:var(--md-accent-fg-color)}.md-feedback__icon:disabled{color:var(--md-default-fg-color--lightest);pointer-events:none}.md-feedback__note{opacity:0;position:relative;transform:translateY(.4rem);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-feedback__note>*{margin:0 auto;max-width:16rem}:disabled .md-feedback__note{opacity:1;transform:translateY(0)}.md-footer{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color)}@media print{.md-footer{display:none}}.md-footer__inner{justify-content:space-between;overflow:auto;padding:.2rem}.md-footer__inner:not([hidden]){display:flex}.md-footer__link{align-items:end;display:flex;flex-grow:0.01;margin-bottom:.4rem;margin-top:1rem;max-width:100%;outline-color:var(--md-accent-fg-color);overflow:hidden;transition:opacity .25s}.md-footer__link:focus,.md-footer__link:hover{opacity:.7}[dir=rtl] .md-footer__link svg{transform:scaleX(-1)}@media screen and (max-width:44.984375em){.md-footer__link--prev{flex-shrink:0}.md-footer__link--prev .md-footer__title{display:none}}[dir=ltr] .md-footer__link--next{margin-left:auto}[dir=rtl] .md-footer__link--next{margin-right:auto}.md-footer__link--next{text-align:right}[dir=rtl] .md-footer__link--next{text-align:left}.md-footer__title{flex-grow:1;font-size:.9rem;margin-bottom:.7rem;max-width:calc(100% - 2.4rem);padding:0 1rem;white-space:nowrap}.md-footer__button{margin:.2rem;padding:.4rem}.md-footer__direction{font-size:.64rem;opacity:.7}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:focus,html .md-footer-meta.md-typeset a:hover{color:var(--md-footer-fg-color)}.md-copyright{color:var(--md-footer-fg-color--lighter);font-size:.64rem;margin:auto .6rem;padding:.4rem 0;width:100%}@media screen and (min-width:45em){.md-copyright{width:auto}}.md-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-social{display:inline-flex;gap:.2rem;margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width:45em){.md-social{padding:.6rem 0}}.md-social__link{display:inline-block;height:1.6rem;text-align:center;width:1.6rem}.md-social__link:before{line-height:1.9}.md-social__link svg{fill:currentcolor;max-height:.8rem;vertical-align:-25%}.md-typeset .md-button{border:.1rem solid;border-radius:.1rem;color:var(--md-primary-fg-color);cursor:pointer;display:inline-block;font-weight:700;padding:.625em 2em;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color)}.md-typeset .md-button:focus,.md-typeset .md-button:hover{background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[dir=ltr] .md-typeset .md-input{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .md-input,[dir=rtl] .md-typeset .md-input{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .md-input{border-top-left-radius:.1rem}.md-typeset .md-input{border-bottom:.1rem solid var(--md-default-fg-color--lighter);box-shadow:var(--md-shadow-z1);font-size:.8rem;height:1.8rem;padding:0 .6rem;transition:border .25s,box-shadow .25s}.md-typeset .md-input:focus,.md-typeset .md-input:hover{border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input--stretch{width:100%}.md-header{background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem #0000,0 .2rem .4rem #0000;color:var(--md-primary-bg-color);display:block;left:0;position:sticky;right:0;top:0;z-index:4}@media print{.md-header{display:none}}.md-header[hidden]{transform:translateY(-100%);transition:transform .25s cubic-bezier(.8,0,.6,1),box-shadow .25s}.md-header--shadow{box-shadow:0 0 .2rem #0000001a,0 .2rem .4rem #0003;transition:transform .25s cubic-bezier(.1,.7,.1,1),box-shadow .25s}.md-header__inner{align-items:center;display:flex;padding:0 .2rem}.md-header__button{color:currentcolor;cursor:pointer;margin:.2rem;outline-color:var(--md-accent-fg-color);padding:.4rem;position:relative;transition:opacity .25s;vertical-align:middle;z-index:1}.md-header__button:hover{opacity:.7}.md-header__button:not([hidden]){display:inline-block}.md-header__button:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-header__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width:76.234375em){.md-header__button.md-logo{display:none}}.md-header__button.md-logo img,.md-header__button.md-logo svg{fill:currentcolor;display:block;height:1.2rem;width:auto}@media screen and (min-width:60em){.md-header__button[for=__search]{display:none}}.no-js .md-header__button[for=__search]{display:none}[dir=rtl] .md-header__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width:76.25em){.md-header__button[for=__drawer]{display:none}}.md-header__topic{display:flex;max-width:100%;position:absolute;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;white-space:nowrap}.md-header__topic+.md-header__topic{opacity:0;pointer-events:none;transform:translateX(1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__topic+.md-header__topic{transform:translateX(-1.25rem)}.md-header__topic:first-child{font-weight:700}[dir=ltr] .md-header__title{margin-left:1rem;margin-right:.4rem}[dir=rtl] .md-header__title{margin-left:.4rem;margin-right:1rem}.md-header__title{flex-grow:1;font-size:.9rem;height:2.4rem;line-height:2.4rem}.md-header__title--active .md-header__topic{opacity:0;pointer-events:none;transform:translateX(-1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__title--active .md-header__topic{transform:translateX(1.25rem)}.md-header__title--active .md-header__topic+.md-header__topic{opacity:1;pointer-events:auto;transform:translateX(0);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;z-index:0}.md-header__title>.md-header__ellipsis{height:100%;position:relative;width:100%}.md-header__option{display:flex;flex-shrink:0;max-width:100%;transition:max-width 0ms .25s,opacity .25s .25s;white-space:nowrap}[data-md-toggle=search]:checked~.md-header .md-header__option{max-width:0;opacity:0;transition:max-width 0ms,opacity 0ms}.md-header__option>input{bottom:0}.md-header__source{display:none}@media screen and (min-width:60em){[dir=ltr] .md-header__source{margin-left:1rem}[dir=rtl] .md-header__source{margin-right:1rem}.md-header__source{display:block;max-width:11.7rem;width:11.7rem}}@media screen and (min-width:76.25em){[dir=ltr] .md-header__source{margin-left:1.4rem}[dir=rtl] .md-header__source{margin-right:1.4rem}}.md-meta{color:var(--md-default-fg-color--light);font-size:.7rem;line-height:1.3}.md-meta__list{display:inline-flex;flex-wrap:wrap;list-style:none;margin:0;padding:0}.md-meta__item:not(:last-child):after{content:"·";margin-left:.2rem;margin-right:.2rem}.md-meta__link{color:var(--md-typeset-a-color)}.md-meta__link:focus,.md-meta__link:hover{color:var(--md-accent-fg-color)}.md-draft{background-color:#ff1744;border-radius:.125em;color:#fff;display:inline-block;font-weight:700;padding-left:.5714285714em;padding-right:.5714285714em}:root{--md-nav-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-nav-icon--next:url('data:image/svg+xml;charset=utf-8,');--md-toc-icon:url('data:image/svg+xml;charset=utf-8,')}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{color:var(--md-default-fg-color--light);display:block;font-weight:700;overflow:hidden;padding:0 .6rem;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{height:100%;width:auto}.md-nav__title .md-nav__button.md-logo img,.md-nav__title .md-nav__button.md-logo svg{fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__list{list-style:none;margin:0;padding:0}.md-nav__link{align-items:flex-start;display:flex;gap:.4rem;margin-top:.625em;scroll-snap-align:start;transition:color 125ms}.md-nav__link--passed,.md-nav__link--passed code{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active,.md-nav__item .md-nav__link--active code{color:var(--md-typeset-a-color)}.md-nav__link .md-ellipsis{position:relative}.md-nav__link .md-ellipsis code{word-break:normal}[dir=ltr] .md-nav__link .md-icon:last-child{margin-left:auto}[dir=rtl] .md-nav__link .md-icon:last-child{margin-right:auto}.md-nav__link .md-typeset{font-size:.7rem;line-height:1.3}.md-nav__link svg{fill:currentcolor;flex-shrink:0;height:1.3em}.md-nav__link[for]:focus,.md-nav__link[for]:hover,.md-nav__link[href]:focus,.md-nav__link[href]:hover{color:var(--md-accent-fg-color);cursor:pointer}.md-nav__link[for]:focus code,.md-nav__link[for]:hover code,.md-nav__link[href]:focus code,.md-nav__link[href]:hover code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-nav__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{background-color:currentcolor;display:block;height:100%;-webkit-mask-image:var(--md-toc-icon);mask-image:var(--md-toc-icon);width:100%}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__container>.md-nav__link{margin-top:0}.md-nav__container>.md-nav__link:first-child{flex-grow:1;min-width:0}.md-nav__icon{flex-shrink:0}.md-nav__source{display:none}@media screen and (max-width:76.234375em){.md-nav--primary,.md-nav--primary .md-nav{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;height:100%;left:0;position:absolute;right:0;top:0;z-index:1}.md-nav--primary .md-nav__item,.md-nav--primary .md-nav__title{font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);cursor:pointer;height:5.6rem;line-height:2.4rem;padding:3rem .8rem .2rem;position:relative;white-space:nowrap}[dir=ltr] .md-nav--primary .md-nav__title .md-nav__icon{left:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem}.md-nav--primary .md-nav__title .md-nav__icon{display:block;height:1.2rem;margin:.2rem;position:absolute;top:.4rem;width:1.2rem}.md-nav--primary .md-nav__title .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--prev);mask-image:var(--md-nav-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}.md-nav--primary .md-nav__title~.md-nav__list{background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;overflow-y:auto;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);font-weight:700}.md-nav--primary .md-nav__title .md-logo{display:block;left:.2rem;margin:.2rem;padding:.4rem;position:absolute;right:.2rem;top:.2rem}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:focus,.md-nav--primary .md-nav__item--active>.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{margin-top:0;padding:.6rem .8rem}.md-nav--primary .md-nav__link svg{margin-top:.1em}.md-nav--primary .md-nav__link>.md-nav__link{padding:0}[dir=ltr] .md-nav--primary .md-nav__link .md-nav__icon{margin-right:-.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{margin-left:-.2rem}.md-nav--primary .md-nav__link .md-nav__icon{font-size:1.2rem;height:1.2rem;width:1.2rem}.md-nav--primary .md-nav__link .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-nav--primary .md-nav__icon:after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav{background-color:initial;position:static}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem}.md-nav--secondary{background-color:initial}.md-nav__toggle~.md-nav{display:flex;opacity:0;transform:translateX(100%);transition:transform .25s cubic-bezier(.8,0,.6,1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{opacity:1;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{-webkit-backface-visibility:hidden;backface-visibility:hidden}}@media screen and (max-width:59.984375em){.md-nav--primary .md-nav__link[for=__toc]{display:flex}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{background-color:var(--md-primary-fg-color--dark);color:var(--md-primary-bg-color);display:block;padding:0 .2rem}}@media screen and (min-width:60em) and (max-width:76.234375em){.md-nav--integrated .md-nav__link[for=__toc]{display:flex}.md-nav--integrated .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width:60em){.md-nav{margin-bottom:-.4rem}.md-nav--secondary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:sticky;top:0;z-index:1}.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}[dir=ltr] .md-nav--secondary .md-nav__list{padding-left:.6rem}[dir=rtl] .md-nav--secondary .md-nav__list{padding-right:.6rem}.md-nav--secondary .md-nav__list{padding-bottom:.4rem}[dir=ltr] .md-nav--secondary .md-nav__item>.md-nav__link{margin-right:.4rem}[dir=rtl] .md-nav--secondary .md-nav__item>.md-nav__link{margin-left:.4rem}}@media screen and (min-width:76.25em){.md-nav{margin-bottom:-.4rem;transition:max-height .25s cubic-bezier(.86,0,.07,1)}.md-nav--primary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:sticky;top:0;z-index:1}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon{display:none}[dir=ltr] .md-nav--primary .md-nav__list{padding-left:.6rem}[dir=rtl] .md-nav--primary .md-nav__list{padding-right:.6rem}.md-nav--primary .md-nav__list{padding-bottom:.4rem}[dir=ltr] .md-nav--primary .md-nav__item>.md-nav__link{margin-right:.4rem}[dir=rtl] .md-nav--primary .md-nav__item>.md-nav__link{margin-left:.4rem}.md-nav__toggle~.md-nav{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows .25s cubic-bezier(.86,0,.07,1),opacity .25s,visibility 0ms .25s;visibility:collapse}.md-nav__toggle~.md-nav>.md-nav__list{overflow:hidden}.md-nav__toggle.md-toggle--indeterminate~.md-nav,.md-nav__toggle:checked~.md-nav{grid-template-rows:1fr;opacity:1;transition:grid-template-rows .25s cubic-bezier(.86,0,.07,1),opacity .15s .1s,visibility 0ms;visibility:visible}.md-nav__toggle.md-toggle--indeterminate~.md-nav{transition:none}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{font-weight:700}.md-nav__item--section>.md-nav__link[for]{color:var(--md-default-fg-color--light)}.md-nav__item--section>.md-nav__link:not(.md-nav__container){pointer-events:none}.md-nav__item--section>.md-nav__link .md-icon,.md-nav__item--section>.md-nav__link>[for]{display:none}[dir=ltr] .md-nav__item--section>.md-nav{margin-left:-.6rem}[dir=rtl] .md-nav__item--section>.md-nav{margin-right:-.6rem}.md-nav__item--section>.md-nav{display:block;opacity:1;visibility:visible}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{border-radius:100%;height:.9rem;transition:background-color .25s;width:.9rem}.md-nav__icon:hover{background-color:var(--md-accent-fg-color--transparent)}.md-nav__icon:after{background-color:currentcolor;border-radius:100%;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:transform .25s;vertical-align:-.1rem;width:100%}[dir=rtl] .md-nav__icon:after{transform:rotate(180deg)}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon:after,.md-nav__item--nested .md-toggle--indeterminate~.md-nav__link .md-nav__icon:after{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);margin-top:0;position:sticky;top:0;z-index:1}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link:not(.md-nav__container){pointer-events:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active.md-nav__item--section{margin:0}[dir=ltr] .md-nav--lifted>.md-nav__list>.md-nav__item>.md-nav:not(.md-nav--secondary){margin-left:-.6rem}[dir=rtl] .md-nav--lifted>.md-nav__list>.md-nav__item>.md-nav:not(.md-nav--secondary){margin-right:-.6rem}.md-nav--lifted>.md-nav__list>.md-nav__item>[for]{color:var(--md-default-fg-color--light)}.md-nav--lifted .md-nav[data-md-level="1"]{grid-template-rows:1fr;opacity:1;visibility:visible}[dir=ltr] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-left:.05rem solid var(--md-primary-fg-color)}[dir=rtl] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-right:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{display:block;margin-bottom:1.25em;opacity:1;visibility:visible}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary>.md-nav__list{overflow:visible;padding-bottom:0}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary>.md-nav__title{display:none}}.md-pagination{font-size:.8rem;font-weight:700;gap:.4rem}.md-pagination,.md-pagination>*{align-items:center;display:flex;justify-content:center}.md-pagination>*{border-radius:.2rem;height:1.8rem;min-width:1.8rem;text-align:center}.md-pagination__current{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light)}.md-pagination__link{transition:color 125ms,background-color 125ms}.md-pagination__link:focus,.md-pagination__link:hover{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-pagination__link:focus svg,.md-pagination__link:hover svg{color:var(--md-accent-fg-color)}.md-pagination__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-pagination__link svg{fill:currentcolor;color:var(--md-default-fg-color--lighter);display:block;max-height:100%;width:1.2rem}:root{--md-path-icon:url('data:image/svg+xml;charset=utf-8,')}.md-path{font-size:.7rem;margin:0 .8rem;overflow:auto;padding-top:1.2rem}.md-path:not([hidden]){display:block}@media screen and (min-width:76.25em){.md-path{margin:0 1.2rem}}.md-path__list{align-items:center;display:flex;gap:.2rem;list-style:none;margin:0;padding:0}.md-path__item:not(:first-child){display:inline-flex;gap:.2rem;white-space:nowrap}.md-path__item:not(:first-child):before{background-color:var(--md-default-fg-color--lighter);content:"";display:inline;height:.8rem;-webkit-mask-image:var(--md-path-icon);mask-image:var(--md-path-icon);width:.8rem}.md-path__link{align-items:center;color:var(--md-default-fg-color--light);display:flex}.md-path__link:focus,.md-path__link:hover{color:var(--md-accent-fg-color)}:root{--md-post-pin-icon:url('data:image/svg+xml;charset=utf-8,')}.md-post__back{border-bottom:.05rem solid var(--md-default-fg-color--lightest);margin-bottom:1.2rem;padding-bottom:1.2rem}@media screen and (max-width:76.234375em){.md-post__back{display:none}}[dir=rtl] .md-post__back svg{transform:scaleX(-1)}.md-post__authors{display:flex;flex-direction:column;gap:.6rem;margin:0 .6rem 1.2rem}.md-post .md-post__meta a{transition:color 125ms}.md-post .md-post__meta a:focus,.md-post .md-post__meta a:hover{color:var(--md-accent-fg-color)}.md-post__title{color:var(--md-default-fg-color--light);font-weight:700}.md-post--excerpt{margin-bottom:3.2rem}.md-post--excerpt .md-post__header{align-items:center;display:flex;gap:.6rem;min-height:1.6rem}.md-post--excerpt .md-post__authors{align-items:center;display:inline-flex;flex-direction:row;gap:.2rem;margin:0;min-height:2.4rem}[dir=ltr] .md-post--excerpt .md-post__meta .md-meta__list{margin-right:.4rem}[dir=rtl] .md-post--excerpt .md-post__meta .md-meta__list{margin-left:.4rem}.md-post--excerpt .md-post__content>:first-child{--md-scroll-margin:6rem;margin-top:0}.md-post>.md-nav--secondary{margin:1em 0}.md-pin{background:var(--md-default-fg-color--lightest);border-radius:1rem;margin-top:-.05rem;padding:.2rem}.md-pin:after{background-color:currentcolor;content:"";display:block;height:.6rem;margin:0 auto;-webkit-mask-image:var(--md-post-pin-icon);mask-image:var(--md-post-pin-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.6rem}.md-profile{align-items:center;display:flex;font-size:.7rem;gap:.6rem;line-height:1.4;width:100%}.md-profile__description{flex-grow:1}.md-content--post{display:flex}@media screen and (max-width:76.234375em){.md-content--post{flex-flow:column-reverse}}.md-content--post>.md-content__inner{min-width:0}@media screen and (min-width:76.25em){[dir=ltr] .md-content--post>.md-content__inner{margin-left:1.2rem}[dir=rtl] .md-content--post>.md-content__inner{margin-right:1.2rem}}@media screen and (max-width:76.234375em){.md-sidebar.md-sidebar--post{padding:0;position:static;width:100%}.md-sidebar.md-sidebar--post .md-sidebar__scrollwrap{overflow:visible}.md-sidebar.md-sidebar--post .md-sidebar__inner{padding:0}.md-sidebar.md-sidebar--post .md-post__meta{margin-left:.6rem;margin-right:.6rem}.md-sidebar.md-sidebar--post .md-nav__item{border:none;display:inline}.md-sidebar.md-sidebar--post .md-nav__list{display:inline-flex;flex-wrap:wrap;gap:.6rem;padding-bottom:.6rem;padding-top:.6rem}.md-sidebar.md-sidebar--post .md-nav__link{padding:0}.md-sidebar.md-sidebar--post .md-nav{height:auto;margin-bottom:0;position:static}}:root{--md-progress-value:0;--md-progress-delay:400ms}.md-progress{background:var(--md-primary-bg-color);height:.075rem;opacity:min(clamp(0,var(--md-progress-value),1),clamp(0,100 - var(--md-progress-value),1));position:fixed;top:0;transform:scaleX(calc(var(--md-progress-value)*1%));transform-origin:left;transition:transform .5s cubic-bezier(.19,1,.22,1),opacity .25s var(--md-progress-delay);width:100%;z-index:4}:root{--md-search-result-icon:url('data:image/svg+xml;charset=utf-8,')}.md-search{position:relative}@media screen and (min-width:60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{opacity:0;z-index:1}@media screen and (max-width:59.984375em){[dir=ltr] .md-search__overlay{left:-2.2rem}[dir=rtl] .md-search__overlay{right:-2.2rem}.md-search__overlay{background-color:var(--md-default-bg-color);border-radius:1rem;height:2rem;overflow:hidden;pointer-events:none;position:absolute;top:-1rem;transform-origin:center;transition:transform .3s .1s,opacity .2s .2s;width:2rem}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform .4s,opacity .1s}}@media screen and (min-width:60em){[dir=ltr] .md-search__overlay{left:0}[dir=rtl] .md-search__overlay{right:0}.md-search__overlay{background-color:#0000008a;cursor:pointer;height:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0}[data-md-toggle=search]:checked~.md-header .md-search__overlay{height:200vh;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@media screen and (max-width:29.984375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width:30em) and (max-width:44.984375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width:45em) and (max-width:59.984375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{-webkit-backface-visibility:hidden;backface-visibility:hidden}@media screen and (max-width:59.984375em){[dir=ltr] .md-search__inner{left:0}[dir=rtl] .md-search__inner{right:0}.md-search__inner{height:0;opacity:0;overflow:hidden;position:fixed;top:0;transform:translateX(5%);transition:width 0ms .3s,height 0ms .3s,transform .15s cubic-bezier(.4,0,.2,1) .15s,opacity .15s .15s;width:0;z-index:2}[dir=rtl] .md-search__inner{transform:translateX(-5%)}[data-md-toggle=search]:checked~.md-header .md-search__inner{height:100%;opacity:1;transform:translateX(0);transition:width 0ms 0ms,height 0ms 0ms,transform .15s cubic-bezier(.1,.7,.1,1) .15s,opacity .15s .15s;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__inner{float:right}[dir=rtl] .md-search__inner{float:left}.md-search__inner{padding:.1rem 0;position:relative;transition:width .25s cubic-bezier(.1,.7,.1,1);width:11.7rem}}@media screen and (min-width:60em) and (max-width:76.234375em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width:76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{background-color:var(--md-default-bg-color);box-shadow:0 0 .6rem #0000;height:2.4rem;position:relative;transition:color .25s,background-color .25s;z-index:2}@media screen and (min-width:60em){.md-search__form{background-color:#00000042;border-radius:.1rem;height:1.8rem}.md-search__form:hover{background-color:#ffffff1f}}[data-md-toggle=search]:checked~.md-header .md-search__form{background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0;box-shadow:0 0 .6rem #00000012;color:var(--md-default-fg-color)}[dir=ltr] .md-search__input{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__input{padding-left:2.2rem;padding-right:3.6rem}.md-search__input{background:#0000;font-size:.9rem;height:100%;position:relative;text-overflow:ellipsis;width:100%;z-index:2}.md-search__input::placeholder{transition:color .25s}.md-search__input::placeholder,.md-search__input~.md-search__icon{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width:59.984375em){.md-search__input{font-size:.9rem;height:2.4rem;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__input{padding-left:2.2rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input{color:inherit;font-size:.8rem}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}[data-md-toggle=search]:checked~.md-header .md-search__input{text-overflow:clip}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:#0000}}.md-search__icon{cursor:pointer;display:inline-block;height:1.2rem;transition:color .25s,opacity .25s;width:1.2rem}.md-search__icon:hover{opacity:.7}[dir=ltr] .md-search__icon[for=__search]{left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem}.md-search__icon[for=__search]{position:absolute;top:.3rem;z-index:2}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width:59.984375em){[dir=ltr] .md-search__icon[for=__search]{left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem}.md-search__icon[for=__search]{top:.6rem}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width:60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}[dir=ltr] .md-search__options{right:.5rem}[dir=rtl] .md-search__options{left:.5rem}.md-search__options{pointer-events:none;position:absolute;top:.3rem;z-index:2}@media screen and (max-width:59.984375em){[dir=ltr] .md-search__options{right:.8rem}[dir=rtl] .md-search__options{left:.8rem}.md-search__options{top:.6rem}}[dir=ltr] .md-search__options>.md-icon{margin-left:.2rem}[dir=rtl] .md-search__options>.md-icon{margin-right:.2rem}.md-search__options>.md-icon{color:var(--md-default-fg-color--light);opacity:0;transform:scale(.75);transition:transform .15s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-search__options>.md-icon:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>.md-icon{opacity:1;pointer-events:auto;transform:scale(1)}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>.md-icon:hover{opacity:.7}[dir=ltr] .md-search__suggest{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__suggest{padding-left:2.2rem;padding-right:3.6rem}.md-search__suggest{align-items:center;color:var(--md-default-fg-color--lighter);display:flex;font-size:.9rem;height:100%;opacity:0;position:absolute;top:0;transition:opacity 50ms;white-space:nowrap;width:100%}@media screen and (min-width:60em){[dir=ltr] .md-search__suggest{padding-left:2.2rem}[dir=rtl] .md-search__suggest{padding-right:2.2rem}.md-search__suggest{font-size:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__suggest{opacity:1;transition:opacity .3s .1s}[dir=ltr] .md-search__output{border-bottom-left-radius:.1rem}[dir=ltr] .md-search__output,[dir=rtl] .md-search__output{border-bottom-right-radius:.1rem}[dir=rtl] .md-search__output{border-bottom-left-radius:.1rem}.md-search__output{overflow:hidden;position:absolute;width:100%;z-index:1}@media screen and (max-width:59.984375em){.md-search__output{bottom:0;top:2.4rem}}@media screen and (min-width:60em){.md-search__output{opacity:0;top:1.9rem;transition:opacity .4s}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:var(--md-shadow-z3);opacity:1}}.md-search__scrollwrap{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);height:100%;overflow-y:auto;touch-action:pan-y}@media (-webkit-max-device-pixel-ratio:1),(max-resolution:1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width:60em) and (max-width:76.234375em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width:76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width:60em){.md-search__scrollwrap{max-height:0;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-search__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;padding:0 .8rem;scroll-snap-align:start}@media screen and (min-width:60em){[dir=ltr] .md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem}}.md-search-result__list{list-style:none;margin:0;padding:0;-webkit-user-select:none;user-select:none}.md-search-result__item{box-shadow:0 -.05rem var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;scroll-snap-align:start;transition:background-color .25s}.md-search-result__link:focus,.md-search-result__link:hover{background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more>summary{cursor:pointer;display:block;outline:none;position:sticky;scroll-snap-align:start;top:0;z-index:1}.md-search-result__more>summary::marker{display:none}.md-search-result__more>summary::-webkit-details-marker{display:none}.md-search-result__more>summary>div{color:var(--md-typeset-a-color);font-size:.64rem;padding:.75em .8rem;transition:color .25s,background-color .25s}@media screen and (min-width:60em){[dir=ltr] .md-search-result__more>summary>div{padding-left:2.2rem}[dir=rtl] .md-search-result__more>summary>div{padding-right:2.2rem}}.md-search-result__more>summary:focus>div,.md-search-result__more>summary:hover>div{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more[open]>summary{background-color:var(--md-default-bg-color)}.md-search-result__article{overflow:hidden;padding:0 .8rem;position:relative}@media screen and (min-width:60em){[dir=ltr] .md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem}}[dir=ltr] .md-search-result__icon{left:0}[dir=rtl] .md-search-result__icon{right:0}.md-search-result__icon{color:var(--md-default-fg-color--light);height:1.2rem;margin:.5rem;position:absolute;width:1.2rem}@media screen and (max-width:59.984375em){.md-search-result__icon{display:none}}.md-search-result__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-search-result-icon);mask-image:var(--md-search-result-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-search-result__icon:after{transform:scaleX(-1)}.md-search-result .md-typeset{color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.6}.md-search-result .md-typeset h1{color:var(--md-default-fg-color);font-size:.8rem;font-weight:400;line-height:1.4;margin:.55rem 0}.md-search-result .md-typeset h1 mark{text-decoration:none}.md-search-result .md-typeset h2{color:var(--md-default-fg-color);font-size:.64rem;font-weight:700;line-height:1.6;margin:.5em 0}.md-search-result .md-typeset h2 mark{text-decoration:none}.md-search-result__terms{color:var(--md-default-fg-color);display:block;font-size:.64rem;font-style:italic;margin:.5em 0}.md-search-result mark{background-color:initial;color:var(--md-accent-fg-color);text-decoration:underline}.md-select{position:relative;z-index:1}.md-select__inner{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);left:50%;margin-top:.2rem;max-height:0;opacity:0;position:absolute;top:calc(100% - .2rem);transform:translate3d(-50%,.3rem,0);transition:transform .25s 375ms,opacity .25s .25s,max-height 0ms .5s}.md-select:focus-within .md-select__inner,.md-select:hover .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select__inner:after{border-bottom:.2rem solid #0000;border-bottom-color:var(--md-default-bg-color);border-left:.2rem solid #0000;border-right:.2rem solid #0000;border-top:0;content:"";height:0;left:50%;margin-left:-.2rem;margin-top:-.2rem;position:absolute;top:0;width:0}.md-select__list{border-radius:.1rem;font-size:.8rem;list-style-type:none;margin:0;max-height:inherit;overflow:auto;padding:0}.md-select__item{line-height:1.8rem}[dir=ltr] .md-select__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-select__link{padding-left:1.2rem;padding-right:.6rem}.md-select__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:background-color .25s,color .25s;width:100%}.md-select__link:focus,.md-select__link:hover{color:var(--md-accent-fg-color)}.md-select__link:focus{background-color:var(--md-default-fg-color--lightest)}.md-sidebar{align-self:flex-start;flex-shrink:0;padding:1.2rem 0;position:sticky;top:2.4rem;width:12.1rem}@media print{.md-sidebar{display:none}}@media screen and (max-width:76.234375em){[dir=ltr] .md-sidebar--primary{left:-12.1rem}[dir=rtl] .md-sidebar--primary{right:-12.1rem}.md-sidebar--primary{background-color:var(--md-default-bg-color);display:block;height:100%;position:fixed;top:0;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s;width:12.1rem;z-index:5}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:var(--md-shadow-z3);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{bottom:0;left:0;margin:0;overflow:hidden;position:absolute;right:0;scroll-snap-type:none;top:0}}@media screen and (min-width:76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}.md-header--lifted~.md-container .md-sidebar{top:4.8rem}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width:60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{scrollbar-gutter:stable;-webkit-backface-visibility:hidden;backface-visibility:hidden;margin:0 .2rem;overflow-y:auto;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin}.md-sidebar__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-sidebar__scrollwrap:focus-within,.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-sidebar__scrollwrap:focus-within::-webkit-scrollbar-thumb,.md-sidebar__scrollwrap:hover::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap:focus-within::-webkit-scrollbar-thumb:hover,.md-sidebar__scrollwrap:hover::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@supports selector(::-webkit-scrollbar){.md-sidebar__scrollwrap{scrollbar-gutter:auto}[dir=ltr] .md-sidebar__inner{padding-right:calc(100% - 11.5rem)}[dir=rtl] .md-sidebar__inner{padding-left:calc(100% - 11.5rem)}}@media screen and (max-width:76.234375em){.md-overlay{background-color:#0000008a;height:0;opacity:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0;z-index:5}[data-md-toggle=drawer]:checked~.md-overlay{height:100%;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@keyframes facts{0%{height:0}to{height:.65rem}}@keyframes fact{0%{opacity:0;transform:translateY(100%)}50%{opacity:0}to{opacity:1;transform:translateY(0)}}:root{--md-source-forks-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-repositories-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-stars-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-source{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.65rem;line-height:1.2;outline-color:var(--md-accent-fg-color);transition:opacity .25s;white-space:nowrap}.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;height:2.4rem;vertical-align:middle;width:2rem}[dir=ltr] .md-source__icon svg{margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem}.md-source__icon svg{margin-top:.6rem}[dir=ltr] .md-source__icon+.md-source__repository{padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{padding-right:2rem}[dir=ltr] .md-source__icon+.md-source__repository{margin-left:-2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem}[dir=ltr] .md-source__repository{margin-left:.6rem}[dir=rtl] .md-source__repository{margin-right:.6rem}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);overflow:hidden;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{display:flex;font-size:.55rem;gap:.4rem;list-style-type:none;margin:.1rem 0 0;opacity:.75;overflow:hidden;padding:0;width:100%}.md-source__repository--active .md-source__facts{animation:facts .25s ease-in}.md-source__fact{overflow:hidden;text-overflow:ellipsis}.md-source__repository--active .md-source__fact{animation:fact .4s ease-out}[dir=ltr] .md-source__fact:before{margin-right:.1rem}[dir=rtl] .md-source__fact:before{margin-left:.1rem}.md-source__fact:before{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-top;width:.6rem}.md-source__fact:nth-child(1n+2){flex-shrink:0}.md-source__fact--version:before{-webkit-mask-image:var(--md-source-version-icon);mask-image:var(--md-source-version-icon)}.md-source__fact--stars:before{-webkit-mask-image:var(--md-source-stars-icon);mask-image:var(--md-source-stars-icon)}.md-source__fact--forks:before{-webkit-mask-image:var(--md-source-forks-icon);mask-image:var(--md-source-forks-icon)}.md-source__fact--repositories:before{-webkit-mask-image:var(--md-source-repositories-icon);mask-image:var(--md-source-repositories-icon)}.md-source-file{margin:1em 0}[dir=ltr] .md-source-file__fact{margin-right:.6rem}[dir=rtl] .md-source-file__fact{margin-left:.6rem}.md-source-file__fact{align-items:center;color:var(--md-default-fg-color--light);display:inline-flex;font-size:.68rem;gap:.3rem}.md-source-file__fact .md-icon{flex-shrink:0;margin-bottom:.05rem}[dir=ltr] .md-source-file__fact .md-author{float:left}[dir=rtl] .md-source-file__fact .md-author{float:right}.md-source-file__fact .md-author{margin-right:.2rem}.md-source-file__fact svg{width:.9rem}:root{--md-status:url('data:image/svg+xml;charset=utf-8,');--md-status--new:url('data:image/svg+xml;charset=utf-8,');--md-status--deprecated:url('data:image/svg+xml;charset=utf-8,');--md-status--encrypted:url('data:image/svg+xml;charset=utf-8,')}.md-status:after{background-color:var(--md-default-fg-color--light);content:"";display:inline-block;height:1.125em;-webkit-mask-image:var(--md-status);mask-image:var(--md-status);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-bottom;width:1.125em}.md-status:hover:after{background-color:currentcolor}.md-status--new:after{-webkit-mask-image:var(--md-status--new);mask-image:var(--md-status--new)}.md-status--deprecated:after{-webkit-mask-image:var(--md-status--deprecated);mask-image:var(--md-status--deprecated)}.md-status--encrypted:after{-webkit-mask-image:var(--md-status--encrypted);mask-image:var(--md-status--encrypted)}.md-tabs{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);display:block;line-height:1.3;overflow:auto;width:100%;z-index:3}@media print{.md-tabs{display:none}}@media screen and (max-width:76.234375em){.md-tabs{display:none}}.md-tabs[hidden]{pointer-events:none}[dir=ltr] .md-tabs__list{margin-left:.2rem}[dir=rtl] .md-tabs__list{margin-right:.2rem}.md-tabs__list{contain:content;display:flex;list-style:none;margin:0;overflow:auto;padding:0;scrollbar-width:none;white-space:nowrap}.md-tabs__list::-webkit-scrollbar{display:none}.md-tabs__item{height:2.4rem;padding-left:.6rem;padding-right:.6rem}.md-tabs__item--active .md-tabs__link{color:inherit;opacity:1}.md-tabs__link{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:flex;font-size:.7rem;margin-top:.8rem;opacity:.7;outline-color:var(--md-accent-fg-color);outline-offset:.2rem;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s}.md-tabs__link:focus,.md-tabs__link:hover{color:inherit;opacity:1}[dir=ltr] .md-tabs__link svg{margin-right:.4rem}[dir=rtl] .md-tabs__link svg{margin-left:.4rem}.md-tabs__link svg{fill:currentcolor;height:1.3em}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:.1s}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:.12s}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:.14s}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:.16s}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:.18s}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:.2s}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:.22s}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:.24s}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:.26s}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:.28s}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:.3s}.md-tabs[hidden] .md-tabs__link{opacity:0;transform:translateY(50%);transition:transform 0ms .1s,opacity .1s}:root{--md-tag-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .md-tags:not([hidden]){display:inline-flex;flex-wrap:wrap;gap:.5em;margin-bottom:.75em;margin-top:-.125em}.md-typeset .md-tag{align-items:center;background:var(--md-default-fg-color--lightest);border-radius:2.4rem;display:inline-flex;font-size:.64rem;font-size:min(.8em,.64rem);font-weight:700;gap:.5em;letter-spacing:normal;line-height:1.6;padding:.3125em .78125em}.md-typeset .md-tag[href]{-webkit-tap-highlight-color:transparent;color:inherit;outline:none;transition:color 125ms,background-color 125ms}.md-typeset .md-tag[href]:focus,.md-typeset .md-tag[href]:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[id]>.md-typeset .md-tag{vertical-align:text-top}.md-typeset .md-tag-shadow{opacity:.5}.md-typeset .md-tag-icon:before{background-color:var(--md-default-fg-color--lighter);content:"";display:inline-block;height:1.2em;-webkit-mask-image:var(--md-tag-icon);mask-image:var(--md-tag-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset .md-tag-icon[href]:focus:before,.md-typeset .md-tag-icon[href]:hover:before{background-color:var(--md-accent-bg-color)}@keyframes pulse{0%{transform:scale(.95)}75%{transform:scale(1)}to{transform:scale(.95)}}:root{--md-annotation-bg-icon:url('data:image/svg+xml;charset=utf-8,');--md-annotation-icon:url('data:image/svg+xml;charset=utf-8,')}.md-tooltip{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);font-family:var(--md-text-font-family);left:clamp(var(--md-tooltip-0,0rem) + .8rem,var(--md-tooltip-x),100vw + var(--md-tooltip-0,0rem) + .8rem - var(--md-tooltip-width) - 2 * .8rem);max-width:calc(100vw - 1.6rem);opacity:0;position:absolute;top:var(--md-tooltip-y);transform:translateY(-.4rem);transition:transform 0ms .25s,opacity .25s,z-index .25s;width:var(--md-tooltip-width);z-index:0}.md-tooltip--active{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,z-index 0ms;z-index:2}.md-tooltip--inline{font-weight:700;-webkit-user-select:none;user-select:none;width:auto}.md-tooltip--inline:not(.md-tooltip--active){transform:translateY(.2rem) scale(.9)}.md-tooltip--inline .md-tooltip__inner{font-size:.5rem;padding:.2rem .4rem}[hidden]+.md-tooltip--inline{display:none}.focus-visible>.md-tooltip,.md-tooltip:target{outline:var(--md-accent-fg-color) auto}.md-tooltip__inner{font-size:.64rem;padding:.8rem}.md-tooltip__inner.md-typeset>:first-child{margin-top:0}.md-tooltip__inner.md-typeset>:last-child{margin-bottom:0}.md-annotation{font-weight:400;outline:none;vertical-align:text-bottom;white-space:normal}[dir=rtl] .md-annotation{direction:rtl}code .md-annotation{font-family:var(--md-code-font-family);font-size:inherit}.md-annotation:not([hidden]){display:inline-block;line-height:1.25}.md-annotation__index{border-radius:.01px;cursor:pointer;display:inline-block;margin-left:.4ch;margin-right:.4ch;outline:none;overflow:hidden;position:relative;-webkit-user-select:none;user-select:none;vertical-align:text-top;z-index:0}.md-annotation .md-annotation__index{transition:z-index .25s}@media screen{.md-annotation__index{width:2.2ch}[data-md-visible]>.md-annotation__index{animation:pulse 2s infinite}.md-annotation__index:before{background:var(--md-default-bg-color);-webkit-mask-image:var(--md-annotation-bg-icon);mask-image:var(--md-annotation-bg-icon)}.md-annotation__index:after,.md-annotation__index:before{content:"";height:2.2ch;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:-.1ch;width:2.2ch;z-index:-1}.md-annotation__index:after{background-color:var(--md-default-fg-color--lighter);-webkit-mask-image:var(--md-annotation-icon);mask-image:var(--md-annotation-icon);transform:scale(1.0001);transition:background-color .25s,transform .25s}.md-tooltip--active+.md-annotation__index:after{transform:rotate(45deg)}.md-tooltip--active+.md-annotation__index:after,:hover>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}}.md-tooltip--active+.md-annotation__index{animation-play-state:paused;transition-duration:0ms;z-index:2}.md-annotation__index [data-md-annotation-id]{display:inline-block}@media print{.md-annotation__index [data-md-annotation-id]{background:var(--md-default-fg-color--lighter);border-radius:2ch;color:var(--md-default-bg-color);font-weight:700;padding:0 .6ch;white-space:nowrap}.md-annotation__index [data-md-annotation-id]:after{content:attr(data-md-annotation-id)}}.md-typeset .md-annotation-list{counter-reset:xxx;list-style:none}.md-typeset .md-annotation-list li{position:relative}[dir=ltr] .md-typeset .md-annotation-list li:before{left:-2.125em}[dir=rtl] .md-typeset .md-annotation-list li:before{right:-2.125em}.md-typeset .md-annotation-list li:before{background:var(--md-default-fg-color--lighter);border-radius:2ch;color:var(--md-default-bg-color);content:counter(xxx);counter-increment:xxx;font-size:.8875em;font-weight:700;height:2ch;line-height:1.25;min-width:2ch;padding:0 .6ch;position:absolute;text-align:center;top:.25em}:root{--md-tooltip-width:20rem;--md-tooltip-tail:0.3rem}.md-tooltip2{-webkit-backface-visibility:hidden;backface-visibility:hidden;color:var(--md-default-fg-color);font-family:var(--md-text-font-family);opacity:0;pointer-events:none;position:absolute;top:calc(var(--md-tooltip-host-y) + var(--md-tooltip-y));transform:translateY(-.4rem);transform-origin:calc(var(--md-tooltip-host-x) + var(--md-tooltip-x)) 0;transition:transform 0ms .25s,opacity .25s,z-index .25s;width:100%;z-index:0}.md-tooltip2:before{border-left:var(--md-tooltip-tail) solid #0000;border-right:var(--md-tooltip-tail) solid #0000;content:"";display:block;left:clamp(1.5 * .8rem,var(--md-tooltip-host-x) + var(--md-tooltip-x) - var(--md-tooltip-tail),100vw - 2 * var(--md-tooltip-tail) - 1.5 * .8rem);position:absolute;z-index:1}.md-tooltip2--top:before{border-top:var(--md-tooltip-tail) solid var(--md-default-bg-color);bottom:calc(var(--md-tooltip-tail)*-1 + .025rem);filter:drop-shadow(0 1px 0 hsla(0,0%,0%,.05))}.md-tooltip2--bottom:before{border-bottom:var(--md-tooltip-tail) solid var(--md-default-bg-color);filter:drop-shadow(0 -1px 0 hsla(0,0%,0%,.05));top:calc(var(--md-tooltip-tail)*-1 + .025rem)}.md-tooltip2--active{opacity:1;transform:translateY(0);transition:transform .4s cubic-bezier(0,1,.5,1),opacity .25s,z-index 0ms;z-index:2}.md-tooltip2__inner{scrollbar-gutter:stable;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);left:clamp(.8rem,var(--md-tooltip-host-x) - .8rem,100vw - var(--md-tooltip-width) - .8rem);max-height:40vh;max-width:calc(100vw - 1.6rem);position:relative;scrollbar-width:thin}.md-tooltip2__inner::-webkit-scrollbar{height:.2rem;width:.2rem}.md-tooltip2__inner::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-tooltip2__inner::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}[role=dialog]>.md-tooltip2__inner{font-size:.64rem;overflow:auto;padding:0 .8rem;pointer-events:auto;width:var(--md-tooltip-width)}[role=dialog]>.md-tooltip2__inner:after,[role=dialog]>.md-tooltip2__inner:before{content:"";display:block;height:.8rem;position:sticky;width:100%;z-index:10}[role=dialog]>.md-tooltip2__inner:before{background:linear-gradient(var(--md-default-bg-color),#0000 75%);top:0}[role=dialog]>.md-tooltip2__inner:after{background:linear-gradient(#0000,var(--md-default-bg-color) 75%);bottom:0}[role=tooltip]>.md-tooltip2__inner{font-size:.5rem;font-weight:700;left:clamp(.8rem,var(--md-tooltip-host-x) + var(--md-tooltip-x) - var(--md-tooltip-width)/2,100vw - var(--md-tooltip-width) - .8rem);max-width:min(100vw - 2 * .8rem,400px);padding:.2rem .4rem;-webkit-user-select:none;user-select:none;width:-moz-fit-content;width:fit-content}.md-tooltip2__inner.md-typeset>:first-child{margin-top:0}.md-tooltip2__inner.md-typeset>:last-child{margin-bottom:0}[dir=ltr] .md-top{margin-left:50%}[dir=rtl] .md-top{margin-right:50%}.md-top{background-color:var(--md-default-bg-color);border-radius:1.6rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color--light);cursor:pointer;display:block;font-size:.7rem;outline:none;padding:.4rem .8rem;position:fixed;top:3.2rem;transform:translate(-50%);transition:color 125ms,background-color 125ms,transform 125ms cubic-bezier(.4,0,.2,1),opacity 125ms;z-index:2}@media print{.md-top{display:none}}[dir=rtl] .md-top{transform:translate(50%)}.md-top[hidden]{opacity:0;pointer-events:none;transform:translate(-50%,.2rem);transition-duration:0ms}[dir=rtl] .md-top[hidden]{transform:translate(50%,.2rem)}.md-top:focus,.md-top:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top svg{display:inline-block;vertical-align:-.5em}@keyframes hoverfix{0%{pointer-events:none}}:root{--md-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-version{flex-shrink:0;font-size:.8rem;height:2.4rem}[dir=ltr] .md-version__current{margin-left:1.4rem;margin-right:.4rem}[dir=rtl] .md-version__current{margin-left:.4rem;margin-right:1.4rem}.md-version__current{color:inherit;cursor:pointer;outline:none;position:relative;top:.05rem}[dir=ltr] .md-version__current:after{margin-left:.4rem}[dir=rtl] .md-version__current:after{margin-right:.4rem}.md-version__current:after{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-image:var(--md-version-icon);mask-image:var(--md-version-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.4rem}.md-version__alias{margin-left:.3rem;opacity:.7}.md-version__list{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);list-style-type:none;margin:.2rem .8rem;max-height:0;opacity:0;overflow:auto;padding:0;position:absolute;scroll-snap-type:y mandatory;top:.15rem;transition:max-height 0ms .5s,opacity .25s .25s;z-index:3}.md-version:focus-within .md-version__list,.md-version:hover .md-version__list{max-height:10rem;opacity:1;transition:max-height 0ms,opacity .25s}@media (hover:none),(pointer:coarse){.md-version:hover .md-version__list{animation:hoverfix .25s forwards}.md-version:focus-within .md-version__list{animation:none}}.md-version__item{line-height:1.8rem}[dir=ltr] .md-version__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-version__link{padding-left:1.2rem;padding-right:.6rem}.md-version__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:color .25s,background-color .25s;white-space:nowrap;width:100%}.md-version__link:focus,.md-version__link:hover{color:var(--md-accent-fg-color)}.md-version__link:focus{background-color:var(--md-default-fg-color--lightest)}:root{--md-admonition-icon--note:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--abstract:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--info:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--tip:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--success:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--question:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--warning:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--failure:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--danger:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--bug:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--quote:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .admonition,.md-typeset details{background-color:var(--md-admonition-bg-color);border:.075rem solid #448aff;border-radius:.2rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid;transition:box-shadow 125ms}@media print{.md-typeset .admonition,.md-typeset details{box-shadow:none}}.md-typeset .admonition:focus-within,.md-typeset details:focus-within{box-shadow:0 0 0 .2rem #448aff1a}.md-typeset .admonition>*,.md-typeset details>*{box-sizing:border-box}.md-typeset .admonition .admonition,.md-typeset .admonition details,.md-typeset details .admonition,.md-typeset details details{margin-bottom:1em;margin-top:1em}.md-typeset .admonition .md-typeset__scrollwrap,.md-typeset details .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset .admonition .md-typeset__table,.md-typeset details .md-typeset__table{padding:0 .6rem}.md-typeset .admonition>.tabbed-set:only-child,.md-typeset details>.tabbed-set:only-child{margin-top:0}html .md-typeset .admonition>:last-child,html .md-typeset details>:last-child{margin-bottom:.6rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{padding-left:2rem;padding-right:.6rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{padding-left:.6rem;padding-right:2rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{border-left-width:.2rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-right-width:.2rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset .admonition-title,.md-typeset summary{background-color:#448aff1a;border:none;font-weight:700;margin:0 -.6rem;padding-bottom:.4rem;padding-top:.4rem;position:relative}html .md-typeset .admonition-title:last-child,html .md-typeset summary:last-child{margin-bottom:0}[dir=ltr] .md-typeset .admonition-title:before,[dir=ltr] .md-typeset summary:before{left:.6rem}[dir=rtl] .md-typeset .admonition-title:before,[dir=rtl] .md-typeset summary:before{right:.6rem}.md-typeset .admonition-title:before,.md-typeset summary:before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset .admonition-title code,.md-typeset summary code{box-shadow:0 0 0 .05rem var(--md-default-fg-color--lightest)}.md-typeset .admonition.note,.md-typeset details.note{border-color:#448aff}.md-typeset .admonition.note:focus-within,.md-typeset details.note:focus-within{box-shadow:0 0 0 .2rem #448aff1a}.md-typeset .note>.admonition-title,.md-typeset .note>summary{background-color:#448aff1a}.md-typeset .note>.admonition-title:before,.md-typeset .note>summary:before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note)}.md-typeset .note>.admonition-title:after,.md-typeset .note>summary:after{color:#448aff}.md-typeset .admonition.abstract,.md-typeset details.abstract{border-color:#00b0ff}.md-typeset .admonition.abstract:focus-within,.md-typeset details.abstract:focus-within{box-shadow:0 0 0 .2rem #00b0ff1a}.md-typeset .abstract>.admonition-title,.md-typeset .abstract>summary{background-color:#00b0ff1a}.md-typeset .abstract>.admonition-title:before,.md-typeset .abstract>summary:before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract)}.md-typeset .abstract>.admonition-title:after,.md-typeset .abstract>summary:after{color:#00b0ff}.md-typeset .admonition.info,.md-typeset details.info{border-color:#00b8d4}.md-typeset .admonition.info:focus-within,.md-typeset details.info:focus-within{box-shadow:0 0 0 .2rem #00b8d41a}.md-typeset .info>.admonition-title,.md-typeset .info>summary{background-color:#00b8d41a}.md-typeset .info>.admonition-title:before,.md-typeset .info>summary:before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info)}.md-typeset .info>.admonition-title:after,.md-typeset .info>summary:after{color:#00b8d4}.md-typeset .admonition.tip,.md-typeset details.tip{border-color:#00bfa5}.md-typeset .admonition.tip:focus-within,.md-typeset details.tip:focus-within{box-shadow:0 0 0 .2rem #00bfa51a}.md-typeset .tip>.admonition-title,.md-typeset .tip>summary{background-color:#00bfa51a}.md-typeset .tip>.admonition-title:before,.md-typeset .tip>summary:before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip)}.md-typeset .tip>.admonition-title:after,.md-typeset .tip>summary:after{color:#00bfa5}.md-typeset .admonition.success,.md-typeset details.success{border-color:#00c853}.md-typeset .admonition.success:focus-within,.md-typeset details.success:focus-within{box-shadow:0 0 0 .2rem #00c8531a}.md-typeset .success>.admonition-title,.md-typeset .success>summary{background-color:#00c8531a}.md-typeset .success>.admonition-title:before,.md-typeset .success>summary:before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success)}.md-typeset .success>.admonition-title:after,.md-typeset .success>summary:after{color:#00c853}.md-typeset .admonition.question,.md-typeset details.question{border-color:#64dd17}.md-typeset .admonition.question:focus-within,.md-typeset details.question:focus-within{box-shadow:0 0 0 .2rem #64dd171a}.md-typeset .question>.admonition-title,.md-typeset .question>summary{background-color:#64dd171a}.md-typeset .question>.admonition-title:before,.md-typeset .question>summary:before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question)}.md-typeset .question>.admonition-title:after,.md-typeset .question>summary:after{color:#64dd17}.md-typeset .admonition.warning,.md-typeset details.warning{border-color:#ff9100}.md-typeset .admonition.warning:focus-within,.md-typeset details.warning:focus-within{box-shadow:0 0 0 .2rem #ff91001a}.md-typeset .warning>.admonition-title,.md-typeset .warning>summary{background-color:#ff91001a}.md-typeset .warning>.admonition-title:before,.md-typeset .warning>summary:before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning)}.md-typeset .warning>.admonition-title:after,.md-typeset .warning>summary:after{color:#ff9100}.md-typeset .admonition.failure,.md-typeset details.failure{border-color:#ff5252}.md-typeset .admonition.failure:focus-within,.md-typeset details.failure:focus-within{box-shadow:0 0 0 .2rem #ff52521a}.md-typeset .failure>.admonition-title,.md-typeset .failure>summary{background-color:#ff52521a}.md-typeset .failure>.admonition-title:before,.md-typeset .failure>summary:before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure)}.md-typeset .failure>.admonition-title:after,.md-typeset .failure>summary:after{color:#ff5252}.md-typeset .admonition.danger,.md-typeset details.danger{border-color:#ff1744}.md-typeset .admonition.danger:focus-within,.md-typeset details.danger:focus-within{box-shadow:0 0 0 .2rem #ff17441a}.md-typeset .danger>.admonition-title,.md-typeset .danger>summary{background-color:#ff17441a}.md-typeset .danger>.admonition-title:before,.md-typeset .danger>summary:before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger)}.md-typeset .danger>.admonition-title:after,.md-typeset .danger>summary:after{color:#ff1744}.md-typeset .admonition.bug,.md-typeset details.bug{border-color:#f50057}.md-typeset .admonition.bug:focus-within,.md-typeset details.bug:focus-within{box-shadow:0 0 0 .2rem #f500571a}.md-typeset .bug>.admonition-title,.md-typeset .bug>summary{background-color:#f500571a}.md-typeset .bug>.admonition-title:before,.md-typeset .bug>summary:before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug)}.md-typeset .bug>.admonition-title:after,.md-typeset .bug>summary:after{color:#f50057}.md-typeset .admonition.example,.md-typeset details.example{border-color:#7c4dff}.md-typeset .admonition.example:focus-within,.md-typeset details.example:focus-within{box-shadow:0 0 0 .2rem #7c4dff1a}.md-typeset .example>.admonition-title,.md-typeset .example>summary{background-color:#7c4dff1a}.md-typeset .example>.admonition-title:before,.md-typeset .example>summary:before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example)}.md-typeset .example>.admonition-title:after,.md-typeset .example>summary:after{color:#7c4dff}.md-typeset .admonition.quote,.md-typeset details.quote{border-color:#9e9e9e}.md-typeset .admonition.quote:focus-within,.md-typeset details.quote:focus-within{box-shadow:0 0 0 .2rem #9e9e9e1a}.md-typeset .quote>.admonition-title,.md-typeset .quote>summary{background-color:#9e9e9e1a}.md-typeset .quote>.admonition-title:before,.md-typeset .quote>summary:before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote)}.md-typeset .quote>.admonition-title:after,.md-typeset .quote>summary:after{color:#9e9e9e}:root{--md-footnotes-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}[dir=ltr] .md-typeset .footnote>ol{margin-left:0}[dir=rtl] .md-typeset .footnote>ol{margin-right:0}.md-typeset .footnote>ol>li{transition:color 125ms}.md-typeset .footnote>ol>li:target{color:var(--md-default-fg-color)}.md-typeset .footnote>ol>li:focus-within .footnote-backref{opacity:1;transform:translateX(0);transition:none}.md-typeset .footnote>ol>li:hover .footnote-backref,.md-typeset .footnote>ol>li:target .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li>:first-child{margin-top:0}.md-typeset .footnote-ref{font-size:.75em;font-weight:700}html .md-typeset .footnote-ref{outline-offset:.1rem}.md-typeset [id^="fnref:"]:target>.footnote-ref{outline:auto}.md-typeset .footnote-backref{color:var(--md-typeset-a-color);display:inline-block;font-size:0;opacity:0;transform:translateX(.25rem);transition:color .25s,transform .25s .25s,opacity 125ms .25s;vertical-align:text-bottom}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);opacity:1;transform:translateX(0)}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref:before{background-color:currentcolor;content:"";display:inline-block;height:.8rem;-webkit-mask-image:var(--md-footnotes-icon);mask-image:var(--md-footnotes-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.8rem}[dir=rtl] .md-typeset .footnote-backref:before svg{transform:scaleX(-1)}[dir=ltr] .md-typeset .headerlink{margin-left:.5rem}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem}.md-typeset .headerlink{color:var(--md-default-fg-color--lighter);display:inline-block;opacity:0;transition:color .25s,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}.md-typeset .headerlink:focus,.md-typeset :hover>.headerlink,.md-typeset :target>.headerlink{opacity:1;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset .headerlink:hover,.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset :target{--md-scroll-margin:3.6rem;--md-scroll-offset:0rem;scroll-margin-top:calc(var(--md-scroll-margin) - var(--md-scroll-offset))}@media screen and (min-width:76.25em){.md-header--lifted~.md-container .md-typeset :target{--md-scroll-margin:6rem}}.md-typeset h1:target,.md-typeset h2:target,.md-typeset h3:target{--md-scroll-offset:0.2rem}.md-typeset h4:target{--md-scroll-offset:0.15rem}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width:44.984375em){.md-typeset div.arithmatex{margin:0 -.8rem}.md-typeset div.arithmatex>*{width:min-content}}.md-typeset div.arithmatex>*{margin-left:auto!important;margin-right:auto!important;padding:0 .8rem;touch-action:auto}.md-typeset div.arithmatex>* mjx-container{margin:0!important}.md-typeset div.arithmatex mjx-assistive-mml{height:0}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset del.critic,.md-typeset ins.critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{-webkit-box-decoration-break:clone;box-decoration-break:clone;color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment:before{content:"/* "}.md-typeset .critic.comment:after{content:" */"}.md-typeset .critic.block{box-shadow:none;display:block;margin:1em 0;overflow:auto;padding-left:.8rem;padding-right:.8rem}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset details{display:flow-root;overflow:visible;padding-top:0}.md-typeset details[open]>summary:after{transform:rotate(90deg)}.md-typeset details:not([open]){box-shadow:none;padding-bottom:0}.md-typeset details:not([open])>summary{border-radius:.1rem}[dir=ltr] .md-typeset summary{padding-right:1.8rem}[dir=rtl] .md-typeset summary{padding-left:1.8rem}[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset summary{cursor:pointer;display:block;min-height:1rem;overflow:hidden}.md-typeset summary.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset summary:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[dir=ltr] .md-typeset summary:after{right:.4rem}[dir=rtl] .md-typeset summary:after{left:.4rem}.md-typeset summary:after{background-color:currentcolor;content:"";height:1rem;-webkit-mask-image:var(--md-details-icon);mask-image:var(--md-details-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;transform:rotate(0deg);transition:transform .25s;width:1rem}[dir=rtl] .md-typeset summary:after{transform:rotate(180deg)}.md-typeset summary::marker{display:none}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset .emojione,.md-typeset .gemoji,.md-typeset .twemoji{--md-icon-size:1.125em;display:inline-flex;height:var(--md-icon-size);vertical-align:text-top}.md-typeset .emojione svg,.md-typeset .gemoji svg,.md-typeset .twemoji svg{fill:currentcolor;max-height:100%;width:var(--md-icon-size)}.md-typeset .lg,.md-typeset .xl,.md-typeset .xxl,.md-typeset .xxxl{vertical-align:text-bottom}.md-typeset .middle{vertical-align:middle}.md-typeset .lg{--md-icon-size:1.5em}.md-typeset .xl{--md-icon-size:2.25em}.md-typeset .xxl{--md-icon-size:3em}.md-typeset .xxxl{--md-icon-size:4em}.highlight .o,.highlight .ow{color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight .cpf,.highlight .l,.highlight .s,.highlight .s1,.highlight .s2,.highlight .sb,.highlight .sc,.highlight .si,.highlight .ss{color:var(--md-code-hl-string-color)}.highlight .cp,.highlight .se,.highlight .sh,.highlight .sr,.highlight .sx{color:var(--md-code-hl-special-color)}.highlight .il,.highlight .m,.highlight .mb,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:var(--md-code-hl-number-color)}.highlight .k,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:var(--md-code-hl-keyword-color)}.highlight .kc,.highlight .n{color:var(--md-code-hl-name-color)}.highlight .bp,.highlight .nb,.highlight .no{color:var(--md-code-hl-constant-color)}.highlight .nc,.highlight .ne,.highlight .nf,.highlight .nn{color:var(--md-code-hl-function-color)}.highlight .nd,.highlight .ni,.highlight .nl,.highlight .nt{color:var(--md-code-hl-keyword-color)}.highlight .c,.highlight .c1,.highlight .ch,.highlight .cm,.highlight .cs,.highlight .sd{color:var(--md-code-hl-comment-color)}.highlight .na,.highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi{color:var(--md-code-hl-variable-color)}.highlight .ge,.highlight .gh,.highlight .go,.highlight .gp,.highlight .gr,.highlight .gs,.highlight .gt,.highlight .gu{color:var(--md-code-hl-generic-color)}.highlight .gd,.highlight .gi{border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{background-color:var(--md-code-hl-color--light);box-shadow:2px 0 0 0 var(--md-code-hl-color) inset;display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em}.highlight span.filename{background-color:var(--md-code-bg-color);border-bottom:.05rem solid var(--md-default-fg-color--lightest);border-top-left-radius:.1rem;border-top-right-radius:.1rem;display:flow-root;font-size:.85em;font-weight:700;margin-top:1em;padding:.6617647059em 1.1764705882em;position:relative}.highlight span.filename+pre{margin-top:0}.highlight span.filename+pre>code{border-top-left-radius:0;border-top-right-radius:0}.highlight [data-linenos]:before{background-color:var(--md-code-bg-color);box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;color:var(--md-default-fg-color--light);content:attr(data-linenos);float:left;left:-1.1764705882em;margin-left:-1.1764705882em;margin-right:1.1764705882em;padding-left:1.1764705882em;position:sticky;-webkit-user-select:none;user-select:none;z-index:3}.highlight code a[id]{position:absolute;visibility:hidden}.highlight code[data-md-copying]{display:initial}.highlight code[data-md-copying] .hll{display:contents}.highlight code[data-md-copying] .md-annotation{display:none}.highlighttable{display:flow-root}.highlighttable tbody,.highlighttable td{display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable th.filename{flex-grow:1;padding:0;text-align:left}.highlighttable th.filename span.filename{margin-top:0}.highlighttable .linenos{background-color:var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-top-left-radius:.1rem;font-size:.85em;padding:.7720588235em 0 .7720588235em 1.1764705882em;-webkit-user-select:none;user-select:none}.highlighttable .linenodiv{box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .linenodiv span[class]{padding-right:.5882352941em}.highlighttable .code{flex:1;min-width:0}.linenodiv a{color:inherit}.md-typeset .highlighttable{direction:ltr;margin:1em 0}.md-typeset .highlighttable>tbody>tr>.code>div>pre>code{border-bottom-left-radius:0;border-top-left-radius:0}.md-typeset .highlight+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset .highlight+.result:after{clear:both;content:"";display:block}@media screen and (max-width:44.984375em){.md-content__inner>.highlight{margin:1em -.8rem}.md-content__inner>.highlight>.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.code>div>pre>code,.md-content__inner>.highlight>.highlighttable>tbody>tr>.filename span.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.linenos,.md-content__inner>.highlight>pre>code{border-radius:0}.md-content__inner>.highlight+.result{border-left-width:0;border-radius:0;border-right-width:0;margin-left:-.8rem;margin-right:-.8rem}}.md-typeset .keys kbd:after,.md-typeset .keys kbd:before{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys span{color:var(--md-default-fg-color--light);padding:0 .2em}.md-typeset .keys .key-alt:before,.md-typeset .keys .key-left-alt:before,.md-typeset .keys .key-right-alt:before{content:"⎇";padding-right:.4em}.md-typeset .keys .key-command:before,.md-typeset .keys .key-left-command:before,.md-typeset .keys .key-right-command:before{content:"⌘";padding-right:.4em}.md-typeset .keys .key-control:before,.md-typeset .keys .key-left-control:before,.md-typeset .keys .key-right-control:before{content:"⌃";padding-right:.4em}.md-typeset .keys .key-left-meta:before,.md-typeset .keys .key-meta:before,.md-typeset .keys .key-right-meta:before{content:"◆";padding-right:.4em}.md-typeset .keys .key-left-option:before,.md-typeset .keys .key-option:before,.md-typeset .keys .key-right-option:before{content:"⌥";padding-right:.4em}.md-typeset .keys .key-left-shift:before,.md-typeset .keys .key-right-shift:before,.md-typeset .keys .key-shift:before{content:"⇧";padding-right:.4em}.md-typeset .keys .key-left-super:before,.md-typeset .keys .key-right-super:before,.md-typeset .keys .key-super:before{content:"❖";padding-right:.4em}.md-typeset .keys .key-left-windows:before,.md-typeset .keys .key-right-windows:before,.md-typeset .keys .key-windows:before{content:"⊞";padding-right:.4em}.md-typeset .keys .key-arrow-down:before{content:"↓";padding-right:.4em}.md-typeset .keys .key-arrow-left:before{content:"←";padding-right:.4em}.md-typeset .keys .key-arrow-right:before{content:"→";padding-right:.4em}.md-typeset .keys .key-arrow-up:before{content:"↑";padding-right:.4em}.md-typeset .keys .key-backspace:before{content:"⌫";padding-right:.4em}.md-typeset .keys .key-backtab:before{content:"⇤";padding-right:.4em}.md-typeset .keys .key-caps-lock:before{content:"⇪";padding-right:.4em}.md-typeset .keys .key-clear:before{content:"⌧";padding-right:.4em}.md-typeset .keys .key-context-menu:before{content:"☰";padding-right:.4em}.md-typeset .keys .key-delete:before{content:"⌦";padding-right:.4em}.md-typeset .keys .key-eject:before{content:"⏏";padding-right:.4em}.md-typeset .keys .key-end:before{content:"⤓";padding-right:.4em}.md-typeset .keys .key-escape:before{content:"⎋";padding-right:.4em}.md-typeset .keys .key-home:before{content:"⤒";padding-right:.4em}.md-typeset .keys .key-insert:before{content:"⎀";padding-right:.4em}.md-typeset .keys .key-page-down:before{content:"⇟";padding-right:.4em}.md-typeset .keys .key-page-up:before{content:"⇞";padding-right:.4em}.md-typeset .keys .key-print-screen:before{content:"⎙";padding-right:.4em}.md-typeset .keys .key-tab:after{content:"⇥";padding-left:.4em}.md-typeset .keys .key-num-enter:after{content:"⌤";padding-left:.4em}.md-typeset .keys .key-enter:after{content:"⏎";padding-left:.4em}:root{--md-tabbed-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-tabbed-icon--next:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .tabbed-set{border-radius:.1rem;display:flex;flex-flow:column wrap;margin:1em 0;position:relative}.md-typeset .tabbed-set>input{height:0;opacity:0;position:absolute;width:0}.md-typeset .tabbed-set>input:target{--md-scroll-offset:0.625em}.md-typeset .tabbed-set>input.focus-visible~.tabbed-labels:before{background-color:var(--md-accent-fg-color)}.md-typeset .tabbed-labels{-ms-overflow-style:none;box-shadow:0 -.05rem var(--md-default-fg-color--lightest) inset;display:flex;max-width:100%;overflow:auto;scrollbar-width:none}@media print{.md-typeset .tabbed-labels{display:contents}}@media screen{.js .md-typeset .tabbed-labels{position:relative}.js .md-typeset .tabbed-labels:before{background:var(--md-default-fg-color);bottom:0;content:"";display:block;height:2px;left:0;position:absolute;transform:translateX(var(--md-indicator-x));transition:width 225ms,background-color .25s,transform .25s;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--md-indicator-width)}}.md-typeset .tabbed-labels::-webkit-scrollbar{display:none}.md-typeset .tabbed-labels>label{border-bottom:.1rem solid #0000;border-radius:.1rem .1rem 0 0;color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;font-size:.64rem;font-weight:700;padding:.78125em 1.25em .625em;scroll-margin-inline-start:1rem;transition:background-color .25s,color .25s;white-space:nowrap;width:auto}@media print{.md-typeset .tabbed-labels>label:first-child{order:1}.md-typeset .tabbed-labels>label:nth-child(2){order:2}.md-typeset .tabbed-labels>label:nth-child(3){order:3}.md-typeset .tabbed-labels>label:nth-child(4){order:4}.md-typeset .tabbed-labels>label:nth-child(5){order:5}.md-typeset .tabbed-labels>label:nth-child(6){order:6}.md-typeset .tabbed-labels>label:nth-child(7){order:7}.md-typeset .tabbed-labels>label:nth-child(8){order:8}.md-typeset .tabbed-labels>label:nth-child(9){order:9}.md-typeset .tabbed-labels>label:nth-child(10){order:10}.md-typeset .tabbed-labels>label:nth-child(11){order:11}.md-typeset .tabbed-labels>label:nth-child(12){order:12}.md-typeset .tabbed-labels>label:nth-child(13){order:13}.md-typeset .tabbed-labels>label:nth-child(14){order:14}.md-typeset .tabbed-labels>label:nth-child(15){order:15}.md-typeset .tabbed-labels>label:nth-child(16){order:16}.md-typeset .tabbed-labels>label:nth-child(17){order:17}.md-typeset .tabbed-labels>label:nth-child(18){order:18}.md-typeset .tabbed-labels>label:nth-child(19){order:19}.md-typeset .tabbed-labels>label:nth-child(20){order:20}}.md-typeset .tabbed-labels>label:hover{color:var(--md-default-fg-color)}.md-typeset .tabbed-labels>label>[href]:first-child{color:inherit}.md-typeset .tabbed-labels--linked>label{padding:0}.md-typeset .tabbed-labels--linked>label>a{display:block;padding:.78125em 1.25em .625em}.md-typeset .tabbed-content{width:100%}@media print{.md-typeset .tabbed-content{display:contents}}.md-typeset .tabbed-block{display:none}@media print{.md-typeset .tabbed-block{display:block}.md-typeset .tabbed-block:first-child{order:1}.md-typeset .tabbed-block:nth-child(2){order:2}.md-typeset .tabbed-block:nth-child(3){order:3}.md-typeset .tabbed-block:nth-child(4){order:4}.md-typeset .tabbed-block:nth-child(5){order:5}.md-typeset .tabbed-block:nth-child(6){order:6}.md-typeset .tabbed-block:nth-child(7){order:7}.md-typeset .tabbed-block:nth-child(8){order:8}.md-typeset .tabbed-block:nth-child(9){order:9}.md-typeset .tabbed-block:nth-child(10){order:10}.md-typeset .tabbed-block:nth-child(11){order:11}.md-typeset .tabbed-block:nth-child(12){order:12}.md-typeset .tabbed-block:nth-child(13){order:13}.md-typeset .tabbed-block:nth-child(14){order:14}.md-typeset .tabbed-block:nth-child(15){order:15}.md-typeset .tabbed-block:nth-child(16){order:16}.md-typeset .tabbed-block:nth-child(17){order:17}.md-typeset .tabbed-block:nth-child(18){order:18}.md-typeset .tabbed-block:nth-child(19){order:19}.md-typeset .tabbed-block:nth-child(20){order:20}}.md-typeset .tabbed-block>.highlight:first-child>pre,.md-typeset .tabbed-block>pre:first-child{margin:0}.md-typeset .tabbed-block>.highlight:first-child>pre>code,.md-typeset .tabbed-block>pre:first-child>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child>.filename{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable{margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.filename span.filename,.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.linenos{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.code>div>pre>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child+.result{margin-top:-.125em}.md-typeset .tabbed-block>.tabbed-set{margin:0}.md-typeset .tabbed-button{align-self:center;border-radius:100%;color:var(--md-default-fg-color--light);cursor:pointer;display:block;height:.9rem;margin-top:.1rem;pointer-events:auto;transition:background-color .25s;width:.9rem}.md-typeset .tabbed-button:hover{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-typeset .tabbed-button:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-tabbed-icon--prev);mask-image:var(--md-tabbed-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color .25s,transform .25s;width:100%}.md-typeset .tabbed-control{background:linear-gradient(to right,var(--md-default-bg-color) 60%,#0000);display:flex;height:1.9rem;justify-content:start;pointer-events:none;position:absolute;transition:opacity 125ms;width:1.2rem}[dir=rtl] .md-typeset .tabbed-control{transform:rotate(180deg)}.md-typeset .tabbed-control[hidden]{opacity:0}.md-typeset .tabbed-control--next{background:linear-gradient(to left,var(--md-default-bg-color) 60%,#0000);justify-content:end;right:0}.md-typeset .tabbed-control--next .tabbed-button:after{-webkit-mask-image:var(--md-tabbed-icon--next);mask-image:var(--md-tabbed-icon--next)}@media screen and (max-width:44.984375em){[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels{padding-right:.8rem}.md-content__inner>.tabbed-set .tabbed-labels{margin:0 -.8rem;max-width:100vw;scroll-padding-inline-start:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-left:.8rem}.md-content__inner>.tabbed-set .tabbed-labels:after{content:""}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-right:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-left:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-right:-.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{width:2rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-left:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-right:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-left:-.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{width:2rem}}@media screen{.md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){color:var(--md-default-fg-color)}.md-typeset .no-js .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .no-js .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .no-js .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .no-js .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .no-js .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .no-js .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .no-js .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .no-js .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .no-js .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .no-js .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .no-js .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .no-js .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .no-js .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .no-js .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .no-js .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .no-js .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .no-js .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .no-js .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .no-js .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .no-js .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),.no-js .md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.no-js .md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.no-js .md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.no-js .md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.no-js .md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.no-js .md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.no-js .md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.no-js .md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.no-js .md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.no-js .md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.no-js .md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.no-js .md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.no-js .md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.no-js .md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.no-js .md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.no-js .md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.no-js .md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.no-js .md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.no-js .md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.no-js .md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){border-color:var(--md-default-fg-color)}}.md-typeset .tabbed-set>input:first-child.focus-visible~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10).focus-visible~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11).focus-visible~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12).focus-visible~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13).focus-visible~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14).focus-visible~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15).focus-visible~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16).focus-visible~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17).focus-visible~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18).focus-visible~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19).focus-visible~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2).focus-visible~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20).focus-visible~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3).focus-visible~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4).focus-visible~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5).focus-visible~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6).focus-visible~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7).focus-visible~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8).focus-visible~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9).focus-visible~.tabbed-labels>:nth-child(9){color:var(--md-accent-fg-color)}.md-typeset .tabbed-set>input:first-child:checked~.tabbed-content>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-content>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-content>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-content>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-content>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-content>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-content>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-content>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-content>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-content>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-content>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-content>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-content>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-content>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-content>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-content>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-content>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-content>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-content>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-content>:nth-child(9){display:block}:root{--md-tasklist-icon:url('data:image/svg+xml;charset=utf-8,');--md-tasklist-icon--checked:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .task-list-item{list-style-type:none;position:relative}[dir=ltr] .md-typeset .task-list-item [type=checkbox]{left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em}.md-typeset .task-list-control [type=checkbox]{opacity:0;z-index:-1}[dir=ltr] .md-typeset .task-list-indicator:before{left:-1.5em}[dir=rtl] .md-typeset .task-list-indicator:before{right:-1.5em}.md-typeset .task-list-indicator:before{background-color:var(--md-default-fg-color--lightest);content:"";height:1.25em;-webkit-mask-image:var(--md-tasklist-icon);mask-image:var(--md-tasklist-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.15em;width:1.25em}.md-typeset [type=checkbox]:checked+.task-list-indicator:before{background-color:#00e676;-webkit-mask-image:var(--md-tasklist-icon--checked);mask-image:var(--md-tasklist-icon--checked)}:root>*{--md-mermaid-font-family:var(--md-text-font-family),sans-serif;--md-mermaid-edge-color:var(--md-code-fg-color);--md-mermaid-node-bg-color:var(--md-accent-fg-color--transparent);--md-mermaid-node-fg-color:var(--md-accent-fg-color);--md-mermaid-label-bg-color:var(--md-default-bg-color);--md-mermaid-label-fg-color:var(--md-code-fg-color);--md-mermaid-sequence-actor-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-actor-fg-color:var(--md-mermaid-label-fg-color);--md-mermaid-sequence-actor-border-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-actor-line-color:var(--md-default-fg-color--lighter);--md-mermaid-sequence-actorman-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-actorman-line-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-box-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-box-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-label-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-label-fg-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-loop-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-loop-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-loop-border-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-message-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-message-line-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-note-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-note-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-note-border-color:var(--md-mermaid-label-fg-color);--md-mermaid-sequence-number-bg-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-number-fg-color:var(--md-accent-bg-color)}.mermaid{line-height:normal;margin:1em 0}.md-typeset .grid{grid-gap:.4rem;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,16rem),1fr));margin:1em 0}.md-typeset .grid.cards>ol,.md-typeset .grid.cards>ul{display:contents}.md-typeset .grid.cards>ol>li,.md-typeset .grid.cards>ul>li,.md-typeset .grid>.card{border:.05rem solid var(--md-default-fg-color--lightest);border-radius:.1rem;display:block;margin:0;padding:.8rem;transition:border .25s,box-shadow .25s}.md-typeset .grid.cards>ol>li:focus-within,.md-typeset .grid.cards>ol>li:hover,.md-typeset .grid.cards>ul>li:focus-within,.md-typeset .grid.cards>ul>li:hover,.md-typeset .grid>.card:focus-within,.md-typeset .grid>.card:hover{border-color:#0000;box-shadow:var(--md-shadow-z2)}.md-typeset .grid.cards>ol>li>hr,.md-typeset .grid.cards>ul>li>hr,.md-typeset .grid>.card>hr{margin-bottom:1em;margin-top:1em}.md-typeset .grid.cards>ol>li>:first-child,.md-typeset .grid.cards>ul>li>:first-child,.md-typeset .grid>.card>:first-child{margin-top:0}.md-typeset .grid.cards>ol>li>:last-child,.md-typeset .grid.cards>ul>li>:last-child,.md-typeset .grid>.card>:last-child{margin-bottom:0}.md-typeset .grid>*,.md-typeset .grid>.admonition,.md-typeset .grid>.highlight>*,.md-typeset .grid>.highlighttable,.md-typeset .grid>.md-typeset details,.md-typeset .grid>details,.md-typeset .grid>pre{margin-bottom:0;margin-top:0}.md-typeset .grid>.highlight>pre:only-child,.md-typeset .grid>.highlight>pre>code,.md-typeset .grid>.highlighttable,.md-typeset .grid>.highlighttable>tbody,.md-typeset .grid>.highlighttable>tbody>tr,.md-typeset .grid>.highlighttable>tbody>tr>.code,.md-typeset .grid>.highlighttable>tbody>tr>.code>.highlight,.md-typeset .grid>.highlighttable>tbody>tr>.code>.highlight>pre,.md-typeset .grid>.highlighttable>tbody>tr>.code>.highlight>pre>code{height:100%}.md-typeset .grid>.tabbed-set{margin-bottom:0;margin-top:0}@media screen and (min-width:45em){[dir=ltr] .md-typeset .inline{float:left}[dir=rtl] .md-typeset .inline{float:right}[dir=ltr] .md-typeset .inline{margin-right:.8rem}[dir=rtl] .md-typeset .inline{margin-left:.8rem}.md-typeset .inline{margin-bottom:.8rem;margin-top:0;width:11.7rem}[dir=ltr] .md-typeset .inline.end{float:right}[dir=rtl] .md-typeset .inline.end{float:left}[dir=ltr] .md-typeset .inline.end{margin-left:.8rem;margin-right:0}[dir=rtl] .md-typeset .inline.end{margin-left:0;margin-right:.8rem}} \ No newline at end of file diff --git a/1.13/assets/stylesheets/palette.ab4e12ef.min.css b/1.13/assets/stylesheets/palette.ab4e12ef.min.css new file mode 100644 index 000000000..75aaf8425 --- /dev/null +++ b/1.13/assets/stylesheets/palette.ab4e12ef.min.css @@ -0,0 +1 @@ +@media screen{[data-md-color-scheme=slate]{--md-default-fg-color:hsla(var(--md-hue),15%,90%,0.82);--md-default-fg-color--light:hsla(var(--md-hue),15%,90%,0.56);--md-default-fg-color--lighter:hsla(var(--md-hue),15%,90%,0.32);--md-default-fg-color--lightest:hsla(var(--md-hue),15%,90%,0.12);--md-default-bg-color:hsla(var(--md-hue),15%,14%,1);--md-default-bg-color--light:hsla(var(--md-hue),15%,14%,0.54);--md-default-bg-color--lighter:hsla(var(--md-hue),15%,14%,0.26);--md-default-bg-color--lightest:hsla(var(--md-hue),15%,14%,0.07);--md-code-fg-color:hsla(var(--md-hue),18%,86%,0.82);--md-code-bg-color:hsla(var(--md-hue),15%,18%,1);--md-code-bg-color--light:hsla(var(--md-hue),15%,18%,0.9);--md-code-bg-color--lighter:hsla(var(--md-hue),15%,18%,0.54);--md-code-hl-color:#2977ff;--md-code-hl-color--light:#2977ff1a;--md-code-hl-number-color:#e6695b;--md-code-hl-special-color:#f06090;--md-code-hl-function-color:#c973d9;--md-code-hl-constant-color:#9383e2;--md-code-hl-keyword-color:#6791e0;--md-code-hl-string-color:#2fb170;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-kbd-color:hsla(var(--md-hue),15%,90%,0.12);--md-typeset-kbd-accent-color:hsla(var(--md-hue),15%,90%,0.2);--md-typeset-kbd-border-color:hsla(var(--md-hue),15%,14%,1);--md-typeset-mark-color:#4287ff4d;--md-typeset-table-color:hsla(var(--md-hue),15%,95%,0.12);--md-typeset-table-color--light:hsla(var(--md-hue),15%,95%,0.035);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-footer-bg-color:hsla(var(--md-hue),15%,10%,0.87);--md-footer-bg-color--dark:hsla(var(--md-hue),15%,8%,1);--md-shadow-z1:0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;--md-shadow-z2:0 0.2rem 0.5rem #00000040,0 0 0.05rem #00000040;--md-shadow-z3:0 0.2rem 0.5rem #0006,0 0 0.05rem #00000059;color-scheme:dark}[data-md-color-scheme=slate] img[src$="#gh-light-mode-only"],[data-md-color-scheme=slate] img[src$="#only-light"]{display:none}[data-md-color-scheme=slate][data-md-color-primary=pink]{--md-typeset-a-color:#ed5487}[data-md-color-scheme=slate][data-md-color-primary=purple]{--md-typeset-a-color:#c46fd3}[data-md-color-scheme=slate][data-md-color-primary=deep-purple]{--md-typeset-a-color:#a47bea}[data-md-color-scheme=slate][data-md-color-primary=indigo]{--md-typeset-a-color:#5488e8}[data-md-color-scheme=slate][data-md-color-primary=teal]{--md-typeset-a-color:#00ccb8}[data-md-color-scheme=slate][data-md-color-primary=green]{--md-typeset-a-color:#71c174}[data-md-color-scheme=slate][data-md-color-primary=deep-orange]{--md-typeset-a-color:#ff764d}[data-md-color-scheme=slate][data-md-color-primary=brown]{--md-typeset-a-color:#c1775c}[data-md-color-scheme=slate][data-md-color-primary=black],[data-md-color-scheme=slate][data-md-color-primary=blue-grey],[data-md-color-scheme=slate][data-md-color-primary=grey],[data-md-color-scheme=slate][data-md-color-primary=white]{--md-typeset-a-color:#5e8bde}[data-md-color-switching] *,[data-md-color-switching] :after,[data-md-color-switching] :before{transition-duration:0ms!important}}[data-md-color-accent=red]{--md-accent-fg-color:#ff1947;--md-accent-fg-color--transparent:#ff19471a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=pink]{--md-accent-fg-color:#f50056;--md-accent-fg-color--transparent:#f500561a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=purple]{--md-accent-fg-color:#df41fb;--md-accent-fg-color--transparent:#df41fb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=deep-purple]{--md-accent-fg-color:#7c4dff;--md-accent-fg-color--transparent:#7c4dff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=indigo]{--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:#526cfe1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=blue]{--md-accent-fg-color:#4287ff;--md-accent-fg-color--transparent:#4287ff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-blue]{--md-accent-fg-color:#0091eb;--md-accent-fg-color--transparent:#0091eb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=cyan]{--md-accent-fg-color:#00bad6;--md-accent-fg-color--transparent:#00bad61a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=teal]{--md-accent-fg-color:#00bda4;--md-accent-fg-color--transparent:#00bda41a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=green]{--md-accent-fg-color:#00c753;--md-accent-fg-color--transparent:#00c7531a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-green]{--md-accent-fg-color:#63de17;--md-accent-fg-color--transparent:#63de171a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=lime]{--md-accent-fg-color:#b0eb00;--md-accent-fg-color--transparent:#b0eb001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=yellow]{--md-accent-fg-color:#ffd500;--md-accent-fg-color--transparent:#ffd5001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=amber]{--md-accent-fg-color:#fa0;--md-accent-fg-color--transparent:#ffaa001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=orange]{--md-accent-fg-color:#ff9100;--md-accent-fg-color--transparent:#ff91001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=deep-orange]{--md-accent-fg-color:#ff6e42;--md-accent-fg-color--transparent:#ff6e421a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-primary=red]{--md-primary-fg-color:#ef5552;--md-primary-fg-color--light:#e57171;--md-primary-fg-color--dark:#e53734;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=pink]{--md-primary-fg-color:#e92063;--md-primary-fg-color--light:#ec417a;--md-primary-fg-color--dark:#c3185d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=purple]{--md-primary-fg-color:#ab47bd;--md-primary-fg-color--light:#bb69c9;--md-primary-fg-color--dark:#8c24a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=deep-purple]{--md-primary-fg-color:#7e56c2;--md-primary-fg-color--light:#9574cd;--md-primary-fg-color--dark:#673ab6;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=indigo]{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=blue]{--md-primary-fg-color:#2094f3;--md-primary-fg-color--light:#42a5f5;--md-primary-fg-color--dark:#1975d2;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-blue]{--md-primary-fg-color:#02a6f2;--md-primary-fg-color--light:#28b5f6;--md-primary-fg-color--dark:#0287cf;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=cyan]{--md-primary-fg-color:#00bdd6;--md-primary-fg-color--light:#25c5da;--md-primary-fg-color--dark:#0097a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=teal]{--md-primary-fg-color:#009485;--md-primary-fg-color--light:#26a699;--md-primary-fg-color--dark:#007a6c;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=green]{--md-primary-fg-color:#4cae4f;--md-primary-fg-color--light:#68bb6c;--md-primary-fg-color--dark:#398e3d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-green]{--md-primary-fg-color:#8bc34b;--md-primary-fg-color--light:#9ccc66;--md-primary-fg-color--dark:#689f38;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=lime]{--md-primary-fg-color:#cbdc38;--md-primary-fg-color--light:#d3e156;--md-primary-fg-color--dark:#b0b52c;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=yellow]{--md-primary-fg-color:#ffec3d;--md-primary-fg-color--light:#ffee57;--md-primary-fg-color--dark:#fbc02d;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=amber]{--md-primary-fg-color:#ffc105;--md-primary-fg-color--light:#ffc929;--md-primary-fg-color--dark:#ffa200;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=orange]{--md-primary-fg-color:#ffa724;--md-primary-fg-color--light:#ffa724;--md-primary-fg-color--dark:#fa8900;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=deep-orange]{--md-primary-fg-color:#ff6e42;--md-primary-fg-color--light:#ff8a66;--md-primary-fg-color--dark:#f4511f;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=brown]{--md-primary-fg-color:#795649;--md-primary-fg-color--light:#8d6e62;--md-primary-fg-color--dark:#5d4037;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=grey]{--md-primary-fg-color:#757575;--md-primary-fg-color--light:#9e9e9e;--md-primary-fg-color--dark:#616161;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=blue-grey]{--md-primary-fg-color:#546d78;--md-primary-fg-color--light:#607c8a;--md-primary-fg-color--dark:#455a63;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=light-green]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#72ad2e}[data-md-color-primary=lime]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#8b990a}[data-md-color-primary=yellow]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#b8a500}[data-md-color-primary=amber]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#d19d00}[data-md-color-primary=orange]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#e68a00}[data-md-color-primary=white]{--md-primary-fg-color:hsla(var(--md-hue),0%,100%,1);--md-primary-fg-color--light:hsla(var(--md-hue),0%,100%,0.7);--md-primary-fg-color--dark:hsla(var(--md-hue),0%,0%,0.07);--md-primary-bg-color:hsla(var(--md-hue),0%,0%,0.87);--md-primary-bg-color--light:hsla(var(--md-hue),0%,0%,0.54);--md-typeset-a-color:#4051b5}[data-md-color-primary=white] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=white] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}@media screen and (min-width:60em){[data-md-color-primary=white] .md-search__form{background-color:hsla(var(--md-hue),0%,0%,.07)}[data-md-color-primary=white] .md-search__form:hover{background-color:hsla(var(--md-hue),0%,0%,.32)}[data-md-color-primary=white] .md-search__input+.md-search__icon{color:hsla(var(--md-hue),0%,0%,.87)}}@media screen and (min-width:76.25em){[data-md-color-primary=white] .md-tabs{border-bottom:.05rem solid #00000012}}[data-md-color-primary=black]{--md-primary-fg-color:hsla(var(--md-hue),15%,9%,1);--md-primary-fg-color--light:hsla(var(--md-hue),15%,9%,0.54);--md-primary-fg-color--dark:hsla(var(--md-hue),15%,9%,1);--md-primary-bg-color:hsla(var(--md-hue),15%,100%,1);--md-primary-bg-color--light:hsla(var(--md-hue),15%,100%,0.7);--md-typeset-a-color:#4051b5}[data-md-color-primary=black] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=black] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}[data-md-color-primary=black] .md-header{background-color:hsla(var(--md-hue),15%,9%,1)}@media screen and (max-width:59.984375em){[data-md-color-primary=black] .md-nav__source{background-color:hsla(var(--md-hue),15%,11%,.87)}}@media screen and (max-width:76.234375em){html [data-md-color-primary=black] .md-nav--primary .md-nav__title[for=__drawer]{background-color:hsla(var(--md-hue),15%,9%,1)}}@media screen and (min-width:76.25em){[data-md-color-primary=black] .md-tabs{background-color:hsla(var(--md-hue),15%,9%,1)}} \ No newline at end of file diff --git a/1.13/blog/2022/10/08/hatch-v160/index.html b/1.13/blog/2022/10/08/hatch-v160/index.html new file mode 100644 index 000000000..0dd3e5916 --- /dev/null +++ b/1.13/blog/2022/10/08/hatch-v160/index.html @@ -0,0 +1,26 @@ + Hatch v1.6.0 - Hatch

Hatch v1.6.0

Hatch v1.6.0 brings improvements to build environments, better handling of dynamic metadata, and support for tools like Visual Studio Code.

Build environments

Originally, the environment interface method for providing builder sub-environments was intended to be used in conjunction with some cleanup logic in order to provide a fresh setup every time. However, this is unnecessary in practice because build dependencies rarely change.

Without caching, repeat build environment use is slow which affects the following scenarios:

Now a new environment interface method build_environment_exists is used by Hatch to determine whether or not it has already been created, for implementations that have a caching mechanism.

The virtual environment type now uses this method to cache build environments.

Project metadata

Dynamically defined metadata is now supported everywhere, thanks to the new caching of virtual build environments.

A project metadata command is introduced that displays the fully resolved metadata. The output format is JSON unless a field is specified as an argument.

For example, if you checkout a project that is built by Hatch, like FastAPI, and run:

hatch project metadata readme
+

only the readme text will be displayed. If the content is in Markdown, then Rich will render it directly in your terminal:

FastAPI readme

Virtual environment location

The virtual environment type now uses a flat layout for storage in the configured virtual environment directory if the directory resides somewhere within the project root or if it is set to a .virtualenvs directory within the user's home directory.

For example, if you define the following Hatch configuration:

[dirs.env]
+virtual = ".hatch"
+

and the following matrix:

[[tool.hatch.envs.test.matrix]]
+python = ["3.7", "3.8", "3.9", "3.10", "3.11"]
+
[[envs.test.matrix]]
+python = ["3.7", "3.8", "3.9", "3.10", "3.11"]
+

then locating environments with the following command:

hatch env find test
+

will show that the general directory structure is:

.hatch
+├── test.py3.7
+├── test.py3.8
+├── test.py3.9
+├── test.py3.10
+└── test.py3.11
+

This flat structure is required for detection of virtual environments by tools like Visual Studio Code and PyCharm.

Additionally, the virtual environment type now supports a path option to specify an explicit path that all inherited environments will share, such as the common .venv.

Migration script improvements

The script used to migrate existing projects from setuptools has been improved to handle more edge cases that were encountered in the wild and now no longer modifies the formatting of existing pyproject.toml configuration.

Hatchling

Hatch now depends on Hatchling v1.11.0, which was also just released.

Environment version source

A new env version source is available that allows for the project version to be defined by an environment variable.

Relaxed version bumping

The standard version scheme now supports a validate-bump option that when set to false will forego the check when updating the version that the desired version is higher than the current version.

This use case comes from Project Jupyter:

A common pattern we use in Jupyter is to bump to a .dev0 minor version bump after making a release. If we have a bug fix that needs to go out in the interim, we'd rather not be forced to create a branch every time.

\ No newline at end of file diff --git a/1.13/blog/2023/12/11/hatch-v180/index.html b/1.13/blog/2023/12/11/hatch-v180/index.html new file mode 100644 index 000000000..e9e5d44cd --- /dev/null +++ b/1.13/blog/2023/12/11/hatch-v180/index.html @@ -0,0 +1,12 @@ + Hatch v1.8.0 - Hatch

Hatch v1.8.0

Hatch v1.8.0 brings Python distribution management, static analysis and formatting backed by Ruff, and binaries for every platform.

Installation made easy

One thing that has been a perpetual problem for Hatch and other Python applications is that Python itself is a dependency. You, and more importantly your users, need to in some way get Python before your software can even be used. The recommended way to go about that is platform-dependent and even differs based on your target audience. I viewed this as a central UX problem for Hatch and so severe that I took a bit of a hiatus to solve it.

Luckily, I have to my satisfaction solved this problem in the form of PyApp. It is a runtime installer for Python projects written in Rust. Apps are distributed as standalone executables as users have come to expect and bootstrapping occurs upon the first invocation. Here is an example of what you would see the first time you run a binary from this release:

Installation example

Now that we have binaries, creating installers for different platforms becomes trivial. Starting with this release not only are binaries available for every platform but also we have installers for Windows and macOS. The installer for macOS is signed using a certificate from the same account used to sign the official distributions from https://www.python.org, so users will not get any security pop-ups. Shout out to @ewdurbin for their extreme generosity in setting up multiple certificates in their free time!

These installers and binaries are now the recommended way to install and update Hatch. These binaries have built-in management so you can update to the latest version by running hatch self update.

Windows signing

In future we will sign the installers for Windows but I did not have time to look into how that works. macOS signing took way longer than I anticipated 😅

Python management

For a long time I and other users have desired that Hatch gain the ability to manage Python distributions. In my mind this was always blocked on a better installation experience because there was sort of a chicken-or-egg problem where you want a Python manager but you first need Python. No longer is that the case!

The new python command group allows for easy installation of various distributions to arbitrary locations which are then added to your PATH by default. Hatch supports CPython and PyPy distributions:

Available Python distributions

Virtual environment Python resolution

The virtual environment type is now far more intelligent when resolving the parent distribution to use and guarantees that, when no specific version is requested, the resolved distribution will always be compatible with the project.

Additionally, when a requested version cannot be found on PATH it will automatically be downloaded and managed internally.

Static analysis

There is a new fmt command, backed entirely by Ruff, that checks and fixes your code for formatting and linting issues.

Starting with this release, Hatch maintains default settings that are guaranteed to be up-to-date and represent best practices for programming in modern Python. The idea is to provide defaults that are so broadly applicable that the majority of users will maintain little if any of their own overrides.

The default behavior is internal management of settings to provide an OOTB experience that works. It is recommended however that you persist the default config file in version control so that other tools like IDEs can utilize your full configuration.

Since Ruff is now provided as a built-in feature, new project templates no longer have such configuration and are much less verbose.

Build improvements

Building projects that do not use Hatchling as a backend is now supported and such builds are managed with the standard build tool.

The bridge between Hatch and the Hatchling CLI has been removed. Previously, the builder would send serialized messages to Hatch that would contain the desired content and style for each line of output. This was done in an effort to allow builder and build hook plugins to output pretty messages without actually requiring a dependency like Rich. A problem that arises with this is that builders that invoke subprocesses will not display ANSI codes as one might expect and will lose out on the interactive experience of such invocations, like the built-in binary builder plugin calling cargo build. So now everything is simpler at the expense of no colored output without manual logic, or adding a dependency if you're a third-party plugin.

Faster environment usage

Spawning a shell or running commands within environments always first checks that your project's dependencies are satisfied and if not synchronizes the environment with what is defined. Previously, this had the potential to be quite slow for projects that have many dependencies.

Now the set of dependency definitions is hashed and no check is performed if the hash is the same as before, significantly speeding up environment usage in most cases.

Hatchling

Hatch now depends on Hatchling v1.19.0, which was also just released.

Better defaults

Hatchling is all about providing the best possible defaults, even at the expense of backward compatibility. In this release, there are two breaking changes that provide a much better user experience and were in fact requested by users.

  • Both the force-include option and the force_include_editable wheel build data setting now raise errors if source paths do not exist.
  • The wheel build target now raises an error when no file inclusion options have been defined and none of its heuristics to determine what to ship are satisfied.

Binary build target

A new binary build target is now stable that allows for the building of standalone binaries for projects. This is what Hatch itself uses for its binaries.

Meta

Why Hatch?

A new page has been introduced that discusses the value proposition of Hatch and Hatchling in comparison to alternatives. Currently, it only addresses a few features but in future this page will become more comprehensive.

Future

Upcoming features include a test command, commands to manage dependencies, and workspaces functionality similar to Cargo that will make managing monorepos far easier.

Next year there will be two large efforts that you should expect to see:

  1. A significant amount of my free time (and some at work) will be devoted to introducing lock file functionality in Hatch and trying to get whatever that happens to be standardized.

    I met with @brettcannon about his thoughts post-PEP 665 and about mousebender. I also met with the prefix.dev team about rip and was fortunate enough to be shown a demo before its official announcement.

    At the moment, the two options I see are to either go all in and contribute to mousebender or rely on the Prefix folks and use rip. The latter has the benefit of potentially supporting Conda as a side effect with the downside of being quite new with the spec firmly out of our control. The former has the benefit of being able to easily gain institutional support from the Python packaging team and each of our employers with the downside being a significant amount of work needing to be done.

  2. When @henryiii is able to get some free time away from teaching I plan to work with him once again and push very hard for the Python build ecosystem to adopt the extensionlib approach.

    I am of the opinion that the Python community has not fully completed the expressed outcome of PEP 517 in that build backends are still (for the most part) reliant on setuptools for building non-Python code bases.

    Basically, there are components that interact with compilers to produce extension modules and components that pack files into an archive which we call a build backend. These are two distinct pieces of functionality and my view is that there should be an API that allows backends to consume extension module builders to find out where things got created and where they should be shipped inside archives.

    In this hypothetical future any build backend would be able to trigger the building of extension modules based on user configuration.

Support

If you or your organization finds value in what Hatch provides, consider a sponsorship to assist with maintenance and more rapid development!

\ No newline at end of file diff --git a/1.13/blog/2023/12/18/hatch-v190/index.html b/1.13/blog/2023/12/18/hatch-v190/index.html new file mode 100644 index 000000000..b84c03b5f --- /dev/null +++ b/1.13/blog/2023/12/18/hatch-v190/index.html @@ -0,0 +1,16 @@ + Hatch v1.9.0 - Hatch

Hatch v1.9.0

Hatch v1.9.0 brings improvements to static analysis and important bug fixes.

Static analysis

The default version of Ruff has been increased to v0.1.8. This release brings formatting capabilities to docstrings and Hatch enables this by default with line length set to 80. This length was chosen as the default because it plays nicely with the rendering of the most popular themes for Python documentation, such as Material for MkDocs and Furo.

Additionally, it is now possible for projects to pin to specific versions of Ruff for upgrading at a later time:

[tool.hatch.envs.hatch-static-analysis]
+dependencies = ["ruff==X.Y.Z"]
+
[envs.hatch-static-analysis]
+dependencies = ["ruff==X.Y.Z"]
+

Notable fixes

  • Python resolution for environments that do not install the project is no longer bound by the project's Python requirement.
  • Fixed an edge case for out-of-the-box static analysis when there was existing configuration.
  • Compatibility checks for environments no longer occur if the environment is already created. This significantly increases the responsiveness of environment usage.
\ No newline at end of file diff --git a/1.13/blog/2024/05/02/hatch-v1100/index.html b/1.13/blog/2024/05/02/hatch-v1100/index.html new file mode 100644 index 000000000..876f81bb6 --- /dev/null +++ b/1.13/blog/2024/05/02/hatch-v1100/index.html @@ -0,0 +1,38 @@ + Hatch v1.10.0 - Hatch

Hatch v1.10.0

Hatch v1.10.0 brings a test command, support for UV, and a Python script runner.

Test command

The new test command allows you to easily run tests for your project on multiple versions of Python. The default behavior follows best practices, using pytest with select plugins for test execution and coverage.py for code coverage measurement.

The command is designed to be both simple to use while also satisfying the needs of most projects. For example, the following shows Hatch running tests for Jinja in all environments in the default matrix:

Testing Jinja example

Here is us testing Rich, with a bit of configuration:

Testing Rich example

See the tutorial for a detailed walk-through and the config reference for options.

UV

The package installer UV, brought to you by the same folks behind Ruff, is now supported. In any environment, you can set the installer option to uv to use UV in place of virtualenv & pip for virtual environment creation and dependency management, respectively. This often results in a significant performance benefit.

For example, if you wanted to enable this functionality for the default environment, you could set the following:

[tool.hatch.envs.default]
+installer = "uv"
+
[envs.default]
+installer = "uv"
+

Semi-internal environments like those used for testing and static analysis have this enabled by default.

See the how-to guide for more information about switching the installer.

Python script runner

The run command now supports executing Python scripts with inline metadata as standardized by PEP 723.

As an example, consider the following script:

# /// script
+# requires-python = ">=3.11"
+# dependencies = [
+#   "httpx",
+#   "rich",
+# ]
+# ///
+
+import httpx
+from rich.pretty import pprint
+
+resp = httpx.get("https://peps.python.org/api/peps.json")
+data = resp.json()
+pprint([(k, v["title"]) for k, v in data.items()][:10])
+

If you run the script for the first time as follows:

hatch run script.py
+

Hatch will create a dedicated environment for that script using a version of Python greater than or equal to 3.11 with dependencies httpx and rich.

Script running example

See the how-to guide for more information.

Static analysis

The environment used for static analysis is now completely configurable such that you can fully alter the underlying behavior of the fmt command (see the how-to).

Additionally, Ruff has been updated to version 1.4.0 and the rules selected by default have been updated accordingly. Check out their blog post about how the new hand-written parser has made it twice as fast!

Community highlights

Visual Studio Code

Visual Studio Code announced support for Hatch environments in their latest release. This means that you can now easily discover and select Hatch environments for your projects directly from the editor.

See the how-to guide for detailed instructions.

CMake build plugin

A new release of the extension module builder scikit-build-core has introduced a build plugin for Hatchling. This means that you can use Hatchling as your build backend while also shipping extension modules built with CMake.

To get started, add the dependency to your build requirements:

[build-system]
+requires = ["hatchling>=1.24.2", "scikit-build-core~=0.9.3"]
+build-backend = "hatchling.build"
+

Then explicitly enable the experimental option (acknowledging that the plugin will move to a dedicated package in the future):

[tool.hatch.build.targets.wheel.hooks.scikit-build]
+experimental = true
+
[build.targets.wheel.hooks.scikit-build]
+experimental = true
+

At this point, you can create your CMakeLists.txt file as usual and start building your extension modules with CMake! Check out the dedicated example project for a complete demonstration.

Meta

Docs

The efforts toward documentation improvements have increased substantially and the priorities have shifted. From now on expect to see far more tutorials and how-to guides rather than just reference material.

Future

Upcoming features include:

  • workspaces functionality similar to Cargo
  • commands to manage dependencies
  • Windows release artifacts signed by the PSF (just like macOS)
  • performance improvements for both the CLI and the Hatchling build system

Support

If you or your organization finds value in what Hatch provides, consider a sponsorship to assist with maintenance and more rapid development!

\ No newline at end of file diff --git a/1.13/blog/archive/2022/index.html b/1.13/blog/archive/2022/index.html new file mode 100644 index 000000000..1c61de665 --- /dev/null +++ b/1.13/blog/archive/2022/index.html @@ -0,0 +1,12 @@ + 2022 - Hatch

2022

\ No newline at end of file diff --git a/1.13/blog/archive/2023/index.html b/1.13/blog/archive/2023/index.html new file mode 100644 index 000000000..b1def9bae --- /dev/null +++ b/1.13/blog/archive/2023/index.html @@ -0,0 +1,12 @@ + 2023 - Hatch

2023

\ No newline at end of file diff --git a/1.13/blog/archive/2024/index.html b/1.13/blog/archive/2024/index.html new file mode 100644 index 000000000..4aeb02923 --- /dev/null +++ b/1.13/blog/archive/2024/index.html @@ -0,0 +1,12 @@ + 2024 - Hatch

2024

\ No newline at end of file diff --git a/1.13/blog/category/release/index.html b/1.13/blog/category/release/index.html new file mode 100644 index 000000000..e66aa7e02 --- /dev/null +++ b/1.13/blog/category/release/index.html @@ -0,0 +1,12 @@ + Release - Hatch

Release

\ No newline at end of file diff --git a/1.13/blog/index.html b/1.13/blog/index.html new file mode 100644 index 000000000..63d431c6c --- /dev/null +++ b/1.13/blog/index.html @@ -0,0 +1,12 @@ + Blog - Hatch

Blog

\ No newline at end of file diff --git a/1.13/blog/release-hatch-1100/run-script.gif b/1.13/blog/release-hatch-1100/run-script.gif new file mode 100644 index 000000000..e0a6afd9e Binary files /dev/null and b/1.13/blog/release-hatch-1100/run-script.gif differ diff --git a/1.13/blog/release-hatch-1100/testing-jinja.gif b/1.13/blog/release-hatch-1100/testing-jinja.gif new file mode 100644 index 000000000..4b4de5312 Binary files /dev/null and b/1.13/blog/release-hatch-1100/testing-jinja.gif differ diff --git a/1.13/blog/release-hatch-1100/testing-rich.gif b/1.13/blog/release-hatch-1100/testing-rich.gif new file mode 100644 index 000000000..8bf53f51e Binary files /dev/null and b/1.13/blog/release-hatch-1100/testing-rich.gif differ diff --git a/1.13/blog/release-hatch-160/rich-readme.png b/1.13/blog/release-hatch-160/rich-readme.png new file mode 100644 index 000000000..f85c38b10 Binary files /dev/null and b/1.13/blog/release-hatch-160/rich-readme.png differ diff --git a/1.13/blog/release-hatch-180/available-pythons.png b/1.13/blog/release-hatch-180/available-pythons.png new file mode 100644 index 000000000..05fcf78ba Binary files /dev/null and b/1.13/blog/release-hatch-180/available-pythons.png differ diff --git a/1.13/blog/release-hatch-180/install-demo.gif b/1.13/blog/release-hatch-180/install-demo.gif new file mode 100644 index 000000000..f533c42db Binary files /dev/null and b/1.13/blog/release-hatch-180/install-demo.gif differ diff --git a/1.13/build/index.html b/1.13/build/index.html new file mode 100644 index 000000000..473ef301c --- /dev/null +++ b/1.13/build/index.html @@ -0,0 +1,41 @@ + Builds - Hatch

Builds


Configuration

Builds are configured using the tool.hatch.build table. Every target is defined by a section within tool.hatch.build.targets, for example:

[tool.hatch.build.targets.sdist]
+exclude = [
+  "/.github",
+  "/docs",
+]
+
+[tool.hatch.build.targets.wheel]
+packages = ["src/foo"]
+
[build.targets.sdist]
+exclude = [
+  "/.github",
+  "/docs",
+]
+
+[build.targets.wheel]
+packages = ["src/foo"]
+

Building

Invoking the build command without any arguments will build the sdist and wheel targets:

$ hatch build
+[sdist]
+dist/hatch_demo-1rc0.tar.gz
+
+[wheel]
+dist/hatch_demo-1rc0-py3-none-any.whl
+

To only build specific targets, use the -t/--target option:

$ hatch build -t wheel
+[wheel]
+dist/hatch_demo-1rc0-py3-none-any.whl
+

If the target supports multiple versions, you can specify the exact versions to build by appending a colon followed by the desired versions separated by commas:

$ hatch -v build -t wheel:standard
+[wheel]
+Building `wheel` version `standard`
+dist/hatch_demo-1rc0-py3-none-any.whl
+

Packaging ecosystem

Hatch complies with modern Python packaging specs and therefore your projects can be used by other tools with Hatch serving as just the build backend.

So you could use tox as an alternative to Hatch's environment management, or cibuildwheel to distribute packages for every platform, and they both will transparently use Hatch without any extra modification.

\ No newline at end of file diff --git a/1.13/cli/about/index.html b/1.13/cli/about/index.html new file mode 100644 index 000000000..39bcedadd --- /dev/null +++ b/1.13/cli/about/index.html @@ -0,0 +1,17 @@ + CLI usage - Hatch

CLI usage


Verbosity

The amount of displayed output is controlled solely by the -v/--verbose (environment variable HATCH_VERBOSE) and -q/--quiet (environment variable HATCH_QUIET) root options.

The levels are documented here.

Project awareness

No matter the mode, Hatch will always change to the project's root directory for entering or running commands in environments.

Tab completion

Completion is achieved by saving a script and then executing it as a part of your shell's startup sequence.

Afterward, you'll need to start a new shell in order for the changes to take effect.

Save the script somewhere:

_HATCH_COMPLETE=bash_source hatch > ~/.hatch-complete.bash
+

Source the file in ~/.bashrc (or ~/.bash_profile if on macOS):

. ~/.hatch-complete.bash
+

Save the script somewhere:

_HATCH_COMPLETE=zsh_source hatch > ~/.hatch-complete.zsh
+

Source the file in ~/.zshrc:

. ~/.hatch-complete.zsh
+

Save the script in ~/.config/fish/completions:

_HATCH_COMPLETE=fish_source hatch > ~/.config/fish/completions/hatch.fish
+
\ No newline at end of file diff --git a/1.13/cli/reference/index.html b/1.13/cli/reference/index.html new file mode 100644 index 000000000..776afffd7 --- /dev/null +++ b/1.13/cli/reference/index.html @@ -0,0 +1,79 @@ + Reference - Hatch

hatch

Usage:

hatch [OPTIONS] COMMAND [ARGS]...
+

Options:

Name Type Description Default
--env, -e text The name of the environment to use [env var: HATCH_ENV] default
--project, -p text The name of the project to work on [env var: HATCH_PROJECT] None
--verbose, -v integer range (0 and above) Increase verbosity (can be used additively) [env var: HATCH_VERBOSE] 0
--quiet, -q integer range (0 and above) Decrease verbosity (can be used additively) [env var: HATCH_QUIET] 0
--color / --no-color boolean Whether or not to display colored output (default is auto-detection) [env vars: FORCE_COLOR/NO_COLOR] None
--interactive / --no-interactive boolean Whether or not to allow features like prompts and progress bars (default is auto-detection) [env var: HATCH_INTERACTIVE] None
--data-dir text The path to a custom directory used to persist data [env var: HATCH_DATA_DIR] None
--cache-dir text The path to a custom directory used to cache data [env var: HATCH_CACHE_DIR] None
--config text The path to a custom config file to use [env var: HATCH_CONFIG] None
--version boolean Show the version and exit. False
--help boolean Show this message and exit. False

hatch build

Build a project.

Usage:

hatch build [OPTIONS] [LOCATION]
+

Options:

Name Type Description Default
--target, -t text The target to build, overriding project defaults. This may be selected multiple times e.g. -t sdist -t wheel None
--hooks-only boolean Whether or not to only execute build hooks [env var: HATCH_BUILD_HOOKS_ONLY] False
--no-hooks boolean Whether or not to disable build hooks [env var: HATCH_BUILD_NO_HOOKS] False
--ext boolean Whether or not to only execute build hooks for distributing binary Python packages, such as compiling extensions. Equivalent to --hooks-only -t wheel False
--clean, -c boolean Whether or not existing artifacts should first be removed [env var: HATCH_BUILD_CLEAN] False
--clean-hooks-after boolean Whether or not build hook artifacts should be removed after each build [env var: HATCH_BUILD_CLEAN_HOOKS_AFTER] False
--help boolean Show this message and exit. False

hatch clean

Remove build artifacts.

Usage:

hatch clean [OPTIONS] [LOCATION]
+

Options:

Name Type Description Default
--target, -t text The target with which to remove artifacts, overriding project defaults. This may be selected multiple times e.g. -t sdist -t wheel None
--hooks-only boolean Whether or not to only remove artifacts from build hooks [env var: HATCH_BUILD_HOOKS_ONLY] False
--no-hooks boolean Whether or not to ignore artifacts from build hooks [env var: HATCH_BUILD_NO_HOOKS] False
--ext boolean Whether or not to only remove artifacts from build hooks for distributing binary Python packages, such as compiled extensions. Equivalent to --hooks-only -t wheel False
--help boolean Show this message and exit. False

hatch config

Manage the config file

Usage:

hatch config [OPTIONS] COMMAND [ARGS]...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch config explore

Open the config location in your file manager.

Usage:

hatch config explore [OPTIONS]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch config find

Show the location of the config file.

Usage:

hatch config find [OPTIONS]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch config restore

Restore the config file to default settings.

Usage:

hatch config restore [OPTIONS]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch config set

Assign values to config file entries. If the value is omitted, you will be prompted, with the input hidden if it is sensitive.

Usage:

hatch config set [OPTIONS] KEY [VALUE]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch config show

Show the contents of the config file.

Usage:

hatch config show [OPTIONS]
+

Options:

Name Type Description Default
--all, -a boolean Do not scrub secret fields False
--help boolean Show this message and exit. False

hatch config update

Update the config file with any new fields.

Usage:

hatch config update [OPTIONS]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch dep

Manage environment dependencies

Usage:

hatch dep [OPTIONS] COMMAND [ARGS]...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch dep hash

Output a hash of the currently defined dependencies.

Usage:

hatch dep hash [OPTIONS]
+

Options:

Name Type Description Default
--project-only, -p boolean Whether or not to exclude environment dependencies False
--env-only, -e boolean Whether or not to exclude project dependencies False
--help boolean Show this message and exit. False

hatch dep show

Display dependencies in various formats

Usage:

hatch dep show [OPTIONS] COMMAND [ARGS]...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch dep show requirements

Enumerate dependencies as a list of requirements.

Usage:

hatch dep show requirements [OPTIONS]
+

Options:

Name Type Description Default
--project-only, -p boolean Whether or not to exclude environment dependencies False
--env-only, -e boolean Whether or not to exclude project dependencies False
--feature, -f text Whether or not to only show the dependencies of the specified features None
--all boolean Whether or not to include the dependencies of all features False
--help boolean Show this message and exit. False

hatch dep show table

Enumerate dependencies in a tabular format.

Usage:

hatch dep show table [OPTIONS]
+

Options:

Name Type Description Default
--project-only, -p boolean Whether or not to exclude environment dependencies False
--env-only, -e boolean Whether or not to exclude project dependencies False
--lines, -l boolean Whether or not to show lines between table rows False
--ascii boolean Whether or not to only use ASCII characters False
--help boolean Show this message and exit. False

hatch env

Manage project environments

Usage:

hatch env [OPTIONS] COMMAND [ARGS]...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch env create

Create environments.

Usage:

hatch env create [OPTIONS] [ENV_NAME]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch env find

Locate environments.

Usage:

hatch env find [OPTIONS] [ENV_NAME]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch env prune

Remove all environments.

Usage:

hatch env prune [OPTIONS]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch env remove

Remove environments.

Usage:

hatch env remove [OPTIONS] [ENV_NAME]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch env run

Run commands within project environments.

The -e/--env option overrides the equivalent root option and the HATCH_ENV environment variable.

The -i/--include and -x/--exclude options may be used to include or exclude certain variables, optionally followed by specific comma-separated values, and may be selected multiple times. For example, if you have the following configuration:

[[tool.hatch.envs.test.matrix]]
+python = ["3.9", "3.10"]
+version = ["42", "3.14", "9000"]
+
[[envs.test.matrix]]
+python = ["3.9", "3.10"]
+version = ["42", "3.14", "9000"]
+

then running:

hatch env run -i py=3.10 -x version=9000 test:pytest
+

would execute pytest in the environments test.py3.10-42 and test.py3.10-3.14. Note that py may be used as an alias for python.

Note

The inclusion option is treated as an intersection while the exclusion option is treated as a union i.e. an environment must match all of the included variables to be selected while matching any of the excluded variables will prevent selection.

Usage:

hatch env run [OPTIONS] ARGS...
+

Options:

Name Type Description Default
--env, -e text The environments to target None
--include, -i text The matrix variables to include None
--exclude, -x text The matrix variables to exclude None
--filter, -f text The JSON data used to select environments None
--force-continue boolean Run every command and if there were any errors exit with the first code False
--ignore-compat boolean Ignore incompatibility when selecting specific environments False
--help boolean Show this message and exit. False

hatch env show

Show the available environments.

Usage:

hatch env show [OPTIONS] [ENVS]...
+

Options:

Name Type Description Default
--ascii boolean Whether or not to only use ASCII characters False
--json boolean Whether or not to output in JSON format False
--internal, -i boolean Show internal environments False
--help boolean Show this message and exit. False

hatch fmt

Format and lint source code.

Usage:

hatch fmt [OPTIONS] [ARGS]...
+

Options:

Name Type Description Default
--check boolean Only check for errors rather than fixing them False
--linter, -l boolean Only run the linter False
--formatter, -f boolean Only run the formatter False
--sync boolean Sync the default config file with the current version of Hatch False
--help boolean Show this message and exit. False

hatch new

Create or initialize a project.

Usage:

hatch new [OPTIONS] [NAME] [LOCATION]
+

Options:

Name Type Description Default
--interactive, -i boolean Interactively choose details about the project False
--cli boolean Give the project a command line interface False
--init boolean Initialize an existing project False
--help boolean Show this message and exit. False

hatch project

View project information

Usage:

hatch project [OPTIONS] COMMAND [ARGS]...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch project metadata

Display project metadata.

If you want to view the raw readme file without rendering, you can use a JSON parser like jq:

hatch project metadata | jq -r .readme
+

Usage:

hatch project metadata [OPTIONS] [FIELD]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch publish

Publish build artifacts.

Usage:

hatch publish [OPTIONS] [ARTIFACTS]...
+

Options:

Name Type Description Default
--repo, -r text The repository with which to publish artifacts [env var: HATCH_INDEX_REPO] None
--user, -u text The user with which to authenticate [env var: HATCH_INDEX_USER] None
--auth, -a text The credentials to use for authentication [env var: HATCH_INDEX_AUTH] None
--ca-cert text The path to a CA bundle [env var: HATCH_INDEX_CA_CERT] None
--client-cert text The path to a client certificate, optionally containing the private key [env var: HATCH_INDEX_CLIENT_CERT] None
--client-key text The path to the client certificate's private key [env var: HATCH_INDEX_CLIENT_KEY] None
--no-prompt, -n boolean Disable prompts, such as for missing required fields False
--initialize-auth boolean Save first-time authentication information even if nothing was published False
--publisher, -p text The publisher plugin to use (default is index) [env var: HATCH_PUBLISHER] index
--option, -o text Options to pass to the publisher plugin. This may be selected multiple times e.g. -o foo=bar -o baz=23 [env var: HATCH_PUBLISHER_OPTIONS] None
--yes, -y boolean Confirm without prompting when the plugin is disabled False
--help boolean Show this message and exit. False

hatch python

Manage Python installations

Usage:

hatch python [OPTIONS] COMMAND [ARGS]...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch python find

Locate Python binaries.

Usage:

hatch python find [OPTIONS] NAME
+

Options:

Name Type Description Default
-p, --parent boolean Show the parent directory of the Python binary False
--dir, -d text The directory in which distributions reside None
--help boolean Show this message and exit. False

hatch python install

Install Python distributions.

You may select all to install all compatible distributions:

hatch python install all
+

You can set custom sources for distributions by setting the HATCH_PYTHON_SOURCE_<NAME> environment variable where <NAME> is the uppercased version of the distribution name with periods replaced by underscores e.g. HATCH_PYTHON_SOURCE_PYPY3_10.

Usage:

hatch python install [OPTIONS] NAMES...
+

Options:

Name Type Description Default
--private boolean Do not add distributions to the user PATH False
--update, -u boolean Update existing installations False
--dir, -d text The directory in which to install distributions, overriding configuration None
--help boolean Show this message and exit. False

hatch python remove

Remove Python distributions.

You may select all to remove all installed distributions:

hatch python remove all
+

Usage:

hatch python remove [OPTIONS] NAMES...
+

Options:

Name Type Description Default
--dir, -d text The directory in which distributions reside None
--help boolean Show this message and exit. False

hatch python show

Show the available Python distributions.

Usage:

hatch python show [OPTIONS]
+

Options:

Name Type Description Default
--ascii boolean Whether or not to only use ASCII characters False
--dir, -d text The directory in which distributions reside None
--help boolean Show this message and exit. False

hatch python update

Update Python distributions.

You may select all to update all installed distributions:

hatch python update all
+

Usage:

hatch python update [OPTIONS] NAMES...
+

Options:

Name Type Description Default
--dir, -d text The directory in which distributions reside None
--help boolean Show this message and exit. False

hatch run

Run commands within project environments. This is a convenience wrapper around the env run command.

If the first argument contains a colon, then the preceding component will be interpreted as the name of the environment to target, overriding the -e/--env root option and the HATCH_ENV environment variable.

If the environment provides matrices, then you may also provide leading arguments starting with a + or - to select or exclude certain variables, optionally followed by specific comma-separated values. For example, if you have the following configuration:

[[tool.hatch.envs.test.matrix]]
+python = ["3.9", "3.10"]
+version = ["42", "3.14", "9000"]
+
[[envs.test.matrix]]
+python = ["3.9", "3.10"]
+version = ["42", "3.14", "9000"]
+

then running:

hatch run +py=3.10 -version=9000 test:pytest
+

would execute pytest in the environments test.py3.10-42 and test.py3.10-3.14. Note that py may be used as an alias for python.

Note

Inclusions are treated as an intersection while exclusions are treated as a union i.e. an environment must match all of the included variables to be selected while matching any of the excluded variables will prevent selection.

Usage:

hatch run [OPTIONS] [ENV:]ARGS...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch self

Manage Hatch

Usage:

hatch self [OPTIONS] COMMAND [ARGS]...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch self report

Generate a pre-populated GitHub issue.

Usage:

hatch self report [OPTIONS]
+

Options:

Name Type Description Default
--no-open, -n boolean Show the URL instead of opening it False
--help boolean Show this message and exit. False

hatch self restore

Restore the installation

Usage:

hatch self restore [OPTIONS] [ARGS]...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch self update

Install the latest version

Usage:

hatch self update [OPTIONS] [ARGS]...
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch shell

Enter a shell within a project's environment.

Usage:

hatch shell [OPTIONS] [ENV_NAME]
+

Options:

Name Type Description Default
--name text N/A None
--path text N/A None
--help boolean Show this message and exit. False

hatch status

Show information about the current environment.

Usage:

hatch status [OPTIONS]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False

hatch test

Run tests using the hatch-test environment matrix.

If no filtering options are selected, then tests will be run in the first compatible environment found in the matrix with priority given to those matching the current interpreter.

The -i/--include and -x/--exclude options may be used to include or exclude certain variables, optionally followed by specific comma-separated values, and may be selected multiple times. For example, if you have the following configuration:

[[tool.hatch.envs.hatch-test.matrix]]
+python = ["3.9", "3.10"]
+version = ["42", "3.14", "9000"]
+
[[envs.hatch-test.matrix]]
+python = ["3.9", "3.10"]
+version = ["42", "3.14", "9000"]
+

then running:

hatch test -i py=3.10 -x version=9000
+

would run tests in the environments hatch-test.py3.10-42 and hatch-test.py3.10-3.14.

The -py/--python option is a shortcut for specifying the inclusion -i py=....

Note

The inclusion option is treated as an intersection while the exclusion option is treated as a union i.e. an environment must match all of the included variables to be selected while matching any of the excluded variables will prevent selection.

Usage:

hatch test [OPTIONS] [ARGS]...
+

Options:

Name Type Description Default
--randomize, -r boolean Randomize the order of test execution False
--parallel, -p boolean Parallelize test execution False
--retries integer Number of times to retry failed tests None
--retry-delay float Seconds to wait between retries None
--cover, -c boolean Measure code coverage False
--cover-quiet boolean Disable coverage reporting after tests, implicitly enabling --cover False
--all, -a boolean Test all environments in the matrix False
--python, -py text The Python versions to test, equivalent to: -i py=... None
--include, -i text The matrix variables to include None
--exclude, -x text The matrix variables to exclude None
--show, -s boolean Show information about environments in the matrix False
--help boolean Show this message and exit. False

hatch version

View or set a project's version.

Usage:

hatch version [OPTIONS] [DESIRED_VERSION]
+

Options:

Name Type Description Default
--help boolean Show this message and exit. False
\ No newline at end of file diff --git a/1.13/community/contributing/index.html b/1.13/community/contributing/index.html new file mode 100644 index 000000000..43c9d16af --- /dev/null +++ b/1.13/community/contributing/index.html @@ -0,0 +1,21 @@ + Contributing - Hatch

Contributing

The usual process to make a contribution is to:

  1. Check for existing related issues
  2. Fork the repository and create a new branch
  3. Make your changes
  4. Make sure formatting, linting and tests passes.
  5. Add tests if possible to cover the lines you added.
  6. Commit, and send a Pull Request.

Clone the repository

Clone the hatch repository, cd into it, and create a new branch for your contribution:

cd hatch
+git checkout -b add-my-contribution
+

Run the tests

Run the test suite while developing:

hatch run dev
+

Run the test suite with coverage report:

hatch run cov
+

Run the extended test suite with coverage:

hatch run full
+

Lint

Run automated formatting:

hatch run lint:fmt
+

Run full linting and type checking:

hatch run lint:all
+

Docs

Start the documentation in development:

hatch run docs:serve
+

Build and validate the documentation website:

hatch run docs:build-check
+
\ No newline at end of file diff --git a/1.13/community/highlights/index.html b/1.13/community/highlights/index.html new file mode 100644 index 000000000..f4cd4fe3d --- /dev/null +++ b/1.13/community/highlights/index.html @@ -0,0 +1,12 @@ + Community highlights - Hatch
\ No newline at end of file diff --git a/1.13/community/users/index.html b/1.13/community/users/index.html new file mode 100644 index 000000000..c28dd66e7 --- /dev/null +++ b/1.13/community/users/index.html @@ -0,0 +1,12 @@ + Users - Hatch

Users


The following is not intended to be a complete enumeration. Be sure to view the development version of this page for an up-to-date listing.

Projects

aiogram | Apache Airflow | argon2-cffi | attrs | Black | coffea | Colorama | Django Anymail | Django Debug Toolbar | Django NYT | Django OTP | Django OTP Agents | Django OTP Twilio | Django OTP YubiKey | Django Places | Django Wiki | FastAPI | filelock | Fluentd | github3.py | Gradio | HTTPX | iCalendar for Humans | LinkChecker | Litestar | Material for MkDocs | MicroPython | MkDocs | openSUSE | Nox | Packit | pipx | platformdirs | Pydantic | Pygments | PyHamcrest | PyMdown Extensions | Python JSON Schema | Rye | SALib | Spack | Starlette | structlog | tox | Twisted | urllib3 | Uvicorn | virtualenv | Voilà | XGBoost | Ypy | yt-dlp

Industry

Organizations

Government

Academia

Research

Security

Crypto

\ No newline at end of file diff --git a/1.13/config/build/index.html b/1.13/config/build/index.html new file mode 100644 index 000000000..073d63ae1 --- /dev/null +++ b/1.13/config/build/index.html @@ -0,0 +1,177 @@ + Build configuration - Hatch

Build configuration


Build targets are defined as sections within tool.hatch.build.targets:

[tool.hatch.build.targets.<TARGET_NAME>]
+
[build.targets.<TARGET_NAME>]
+

Tip

Although not recommended, you may define global configuration in the tool.hatch.build table. Keys may then be overridden by target config.

Build system

To be compatible with the broader Python packaging ecosystem, you must define the build system as follows:

[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+

The version of hatchling defined here will be used to build all targets.

Hatchling is a standards-compliant1 build backend and is a dependency of Hatch itself.

File selection

VCS

By default, Hatch will respect the first .gitignore or .hgignore file found in your project's root directory or parent directories. Set ignore-vcs to true to disable this behavior:

[tool.hatch.build.targets.sdist]
+ignore-vcs = true
+
[build.targets.sdist]
+ignore-vcs = true
+

Note

For .hgignore files only glob syntax is supported.

Patterns

You can set the include and exclude options to select exactly which files will be shipped in each build, with exclude taking precedence. Every entry represents a Git-style glob pattern.

For example, the following configuration:

[tool.hatch.build.targets.sdist]
+include = [
+  "pkg/*.py",
+  "/tests",
+]
+exclude = [
+  "*.json",
+  "pkg/_compat.py",
+]
+
[build.targets.sdist]
+include = [
+  "pkg/*.py",
+  "/tests",
+]
+exclude = [
+  "*.json",
+  "pkg/_compat.py",
+]
+

will exclude every file with a .json extension, and will include everything under a tests directory located at the root and every file with a .py extension that is directly under a pkg directory located at the root except for _compat.py.

Artifacts

If you want to include files that are ignored by your VCS, such as those that might be created by build hooks, you can use the artifacts option. This option is semantically equivalent to include.

Note that artifacts are not affected by the exclude option. Artifacts can be excluded by using more explicit paths or by using the ! negation operator. When using the ! operator, the negated pattern(s) must come after the more generic ones.

[tool.hatch.build.targets.wheel]
+artifacts = [
+  "*.so",
+  "*.dll",
+  "!/foo/*.so",
+]
+
[build.targets.wheel]
+artifacts = [
+  "*.so",
+  "*.dll",
+  "!/foo/*.so",
+]
+

Explicit selection

Generic

You can use the only-include option to prevent directory traversal starting at the project root and only select specific relative paths to directories or files. Using this option ignores any defined include patterns.

[tool.hatch.build.targets.sdist]
+only-include = ["pkg", "tests/unit"]
+
[build.targets.sdist]
+only-include = ["pkg", "tests/unit"]
+

Packages

The packages option is semantically equivalent to only-include (which takes precedence) except that the shipped path will be collapsed to only include the final component.

So for example, if you want to ship a package foo that is stored in a directory src you would do:

[tool.hatch.build.targets.wheel]
+packages = ["src/foo"]
+
[build.targets.wheel]
+packages = ["src/foo"]
+

Forced inclusion

The force-include option allows you to select specific files or directories from anywhere on the file system that should be included and map them to the desired relative distribution path.

For example, if there was a directory alongside the project root named artifacts containing a file named lib.so and a file named lib.h in your home directory, you could ship both files in a pkg directory with the following configuration:

[tool.hatch.build.targets.wheel.force-include]
+"../artifacts" = "pkg"
+"~/lib.h" = "pkg/lib.h"
+
[build.targets.wheel.force-include]
+"../artifacts" = "pkg"
+"~/lib.h" = "pkg/lib.h"
+

Note

  • Files must be mapped exactly to their desired paths, not to directories.
  • The contents of directory sources are recursively included.
  • To map directory contents directly to the root use / (a forward slash).
  • Sources that do not exist will raise an error.

Warning

Files included using this option will overwrite any file path that was already included by other file selection options.

Default file selection

If no file selection options are provided, then what gets included is determined by each build target.

Excluding files outside packages

If you want to exclude non-artifact files that do not reside within a Python package, set only-packages to true:

[tool.hatch.build.targets.wheel]
+only-packages = true
+
[build.targets.wheel]
+only-packages = true
+

Rewriting paths

You can rewrite relative paths to directories with the sources option. For example, the following configuration:

[tool.hatch.build.targets.wheel.sources]
+"src/foo" = "bar"
+
[build.targets.wheel.sources]
+"src/foo" = "bar"
+

would distribute the file src/foo/file.ext as bar/file.ext.

If you want to remove path prefixes entirely, rather than setting each to an empty string, you can define sources as an array:

[tool.hatch.build.targets.wheel]
+sources = ["src"]
+
[build.targets.wheel]
+sources = ["src"]
+

If you want to add a prefix to paths, you can use an empty string. For example, the following configuration:

[tool.hatch.build.targets.wheel.sources]
+"" = "foo"
+
[build.targets.wheel.sources]
+"" = "foo"
+

would distribute the file bar/file.ext as foo/bar/file.ext.

The packages option itself relies on sources. Defining packages = ["src/foo"] for the wheel target is equivalent to the following:

[tool.hatch.build.targets.wheel]
+only-include = ["src/foo"]
+sources = ["src"]
+
[build.targets.wheel]
+only-include = ["src/foo"]
+sources = ["src"]
+

Performance

All encountered directories are traversed by default. To skip non-artifact directories that are excluded, set skip-excluded-dirs to true:

[tool.hatch.build]
+skip-excluded-dirs = true
+
[build]
+skip-excluded-dirs = true
+

Warning

This may result in not shipping desired files. For example, if you want to include the file a/b/c.txt but your VCS ignores a/b, the file c.txt will not be seen because its parent directory will not be entered. In such cases you can use the force-include option.

Reproducible builds

By default, build targets will build in a reproducible manner provided that they support that behavior. To disable this, set reproducible to false:

[tool.hatch.build]
+reproducible = false
+
[build]
+reproducible = false
+

When enabled, the SOURCE_DATE_EPOCH environment variable will be used for all build timestamps. If not set, then Hatch will use an unchanging default value.

Output directory

When the output directory is not provided to the build command, the dist directory will be used by default. You can change the default to a different directory using a relative or absolute path like so:

[tool.hatch.build]
+directory = "<PATH>"
+
[build]
+directory = "<PATH>"
+

Dev mode

By default for dev mode environment installations or editable installs, the wheel target will determine which directories should be added to Python's search path based on the selected files.

If you want to override this detection or perhaps instruct other build targets as well, you can use the dev-mode-dirs option:

[tool.hatch.build]
+dev-mode-dirs = ["."]
+
[build]
+dev-mode-dirs = ["."]
+

If you don't want to add entire directories to Python's search path, you can enable a more targeted mechanism with the mutually exclusive dev-mode-exact option:

[tool.hatch.build]
+dev-mode-exact = true
+
[build]
+dev-mode-exact = true
+

Warning

The dev-mode-exact mechanism is not supported by static analysis tools & IDEs, therefore functionality such as autocompletion is unlikely to work.

Build targets

A build target can be provided by any builder plugin. There are three built-in build targets: wheel, sdist, and custom.

Dependencies

You can specify additional dependencies that will be installed in each build environment, such as for third party builders:

[tool.hatch.build.targets.your-target-name]
+dependencies = [
+  "your-builder-plugin"
+]
+
[build.targets.your-target-name]
+dependencies = [
+  "your-builder-plugin"
+]
+

You can also declare dependence on the project's runtime dependencies with the require-runtime-dependencies option:

[tool.hatch.build.targets.your-target-name]
+require-runtime-dependencies = true
+
[build.targets.your-target-name]
+require-runtime-dependencies = true
+

Additionally, you may declare dependence on specific runtime features of the project with the require-runtime-features option:

[tool.hatch.build.targets.your-target-name]
+require-runtime-features = [
+  "feature1",
+  "feature2",
+]
+
[build.targets.your-target-name]
+require-runtime-features = [
+  "feature1",
+  "feature2",
+]
+

Versions

If a build target supports multiple build strategies or if there are major changes over time, you can specify exactly which versions you want to build using the versions option:

[tool.hatch.build.targets.<TARGET_NAME>]
+versions = [
+  "v1",
+  "beta-feature",
+]
+
[build.targets.<TARGET_NAME>]
+versions = [
+  "v1",
+  "beta-feature",
+]
+

See the wheel target for a real world example.

Build hooks

A build hook defines code that will be executed at various stages of the build process and can be provided by any build hook plugin. There is one built-in build hook: custom.

Build hooks can be applied either globally:

[tool.hatch.build.hooks.<HOOK_NAME>]
+
[build.hooks.<HOOK_NAME>]
+

or to specific build targets:

[tool.hatch.build.targets.<TARGET_NAME>.hooks.<HOOK_NAME>]
+
[build.targets.<TARGET_NAME>.hooks.<HOOK_NAME>]
+

Dependencies

You can specify additional dependencies that will be installed in each build environment, such as for third party build hooks:

[tool.hatch.build.hooks.your-hook-name]
+dependencies = [
+  "your-build-hook-plugin"
+]
+
[build.hooks.your-hook-name]
+dependencies = [
+  "your-build-hook-plugin"
+]
+

You can also declare dependence on the project's runtime dependencies with the require-runtime-dependencies option:

[tool.hatch.build.hooks.your-hook-name]
+require-runtime-dependencies = true
+
[build.hooks.your-hook-name]
+require-runtime-dependencies = true
+

Additionally, you may declare dependence on specific runtime features of the project with the require-runtime-features option:

[tool.hatch.build.hooks.your-hook-name]
+require-runtime-features = [
+  "feature1",
+  "feature2",
+]
+
[build.hooks.your-hook-name]
+require-runtime-features = [
+  "feature1",
+  "feature2",
+]
+

Order of execution

For each build target, build hooks execute in the order in which they are defined, starting with global hooks.

As an example, for the following configuration:

[tool.hatch.build.targets.foo.hooks.hook2]
+
+[tool.hatch.build.hooks.hook3]
+[tool.hatch.build.hooks.hook1]
+
[build.targets.foo.hooks.hook2]
+
+[build.hooks.hook3]
+[build.hooks.hook1]
+

When target foo is built, build hook hook3 will be executed first, followed by hook1, and then finally hook2.

Conditional execution

If you want to disable a build hook by default and control its use by environment variables, you can do so by setting the enable-by-default option to false:

[tool.hatch.build.hooks.<HOOK_NAME>]
+enable-by-default = false
+
[build.hooks.<HOOK_NAME>]
+enable-by-default = false
+

Environment variables

Variable Default Description
HATCH_BUILD_CLEAN false Whether or not existing artifacts should first be removed
HATCH_BUILD_CLEAN_HOOKS_AFTER false Whether or not build hook artifacts should be removed after each build
HATCH_BUILD_HOOKS_ONLY false Whether or not to only execute build hooks
HATCH_BUILD_NO_HOOKS false Whether or not to disable all build hooks; this takes precedence over other options
HATCH_BUILD_HOOKS_ENABLE false Whether or not to enable all build hooks
HATCH_BUILD_HOOK_ENABLE_<HOOK_NAME> false Whether or not to enable the build hook named <HOOK_NAME>
HATCH_BUILD_LOCATION dist The location with which to build the targets; only used by the build command

  1. Support for PEP 517 and PEP 660 guarantees interoperability with other build tools. 

\ No newline at end of file diff --git a/1.13/config/context/index.html b/1.13/config/context/index.html new file mode 100644 index 000000000..e06eec603 --- /dev/null +++ b/1.13/config/context/index.html @@ -0,0 +1,24 @@ + Context formatting - Hatch

Context formatting


You can populate configuration with the values of certain supported fields using the syntax of Python's format strings. Each field interprets the modifier part after the colon differently, if at all.

Global fields

Any configuration that declares support for context formatting will always support these fields.

Paths

Field Description
root The root project directory
home The user's home directory

All paths support the following modifiers:

Modifier Description
uri The normalized absolute URI path prefixed by file:
real The path with all symbolic links resolved
parent The parent of the preceding path

Tip

The parent modifier can be chained and may be combined with either the uri or real modifier, with the latter placed at the end. For example:

[tool.hatch.envs.test]
+dependencies = [
+    "example-project @ {root:parent:parent:uri}/example-project",
+]
+
[envs.test]
+dependencies = [
+    "example-project @ {root:parent:parent:uri}/example-project",
+]
+

System separators

Field Description
/ \ on Windows, / otherwise
; ; on Windows, : otherwise

Environment variables

The env field and its modifier allow you to select the value of an environment variable. If the environment variable is not set, you must specify a default value as an additional modifier e.g. {env:PATH:DEFAULT}.

Field nesting

You can insert fields within others. For example, if you wanted a script that displays the value of the environment variable FOO, with a fallback to the environment variable BAR, with its own fallback to the user's home directory, you could do the following:

[tool.hatch.envs.test.scripts]
+display = "echo {env:FOO:{env:BAR:{home}}}"
+
[envs.test.scripts]
+display = "echo {env:FOO:{env:BAR:{home}}}"
+
\ No newline at end of file diff --git a/1.13/config/dependency/index.html b/1.13/config/dependency/index.html new file mode 100644 index 000000000..1011152f2 --- /dev/null +++ b/1.13/config/dependency/index.html @@ -0,0 +1,59 @@ + Dependency configuration - Hatch

Dependency configuration


Project dependencies are defined with PEP 508 strings using optional PEP 440 version specifiers.

Version specifiers

A version specifier consists of a series of version clauses, separated by commas. For example:

[project]
+...
+dependencies = [
+  "cryptography",
+  "click>=7, <9, != 8.0.0",
+  "python-dateutil==2.8.*",
+  "numpy~=1.21.4",
+]
+

The comma is equivalent to a logical AND operator: a candidate version must match all given version clauses in order to match the specifier as a whole.

Operators

Operators Function
~= Compatible release
== Version matching
!= Version exclusion
<=, >= Inclusive ordered comparison
<, > Exclusive ordered comparison
=== Arbitrary equality

Version matching

A version matching clause includes the version matching operator == and a version identifier.

By default, the version matching operator is based on a strict equality comparison: the specified version must be exactly the same as the requested version.

Clause Allowed versions
==1 1.0.0
==1.2 1.2.0

Prefix matching may be requested instead of strict comparison, by appending a trailing .* to the version identifier in the version matching clause. This means that additional trailing segments will be ignored when determining whether or not a version identifier matches the clause.

Clause Allowed versions
==1.* >=1.0.0, <2.0.0
==1.2.* >=1.2.0, <1.3.0

Compatible release

A compatible release clause consists of the compatible release operator ~= and a version identifier. It matches any candidate version that is expected to be compatible with the specified version.

For a given release identifier V.N, the compatible release clause is approximately equivalent to the following pair of comparison clauses:

>= V.N, == V.*
+

This operator cannot be used with a single segment version number such as ~=1.

Clause Allowed versions
~=1.2 >=1.2.0, <2.0.0
~=1.2.3 >=1.2.3, <1.3.0

Version exclusion

A version exclusion clause includes the version exclusion operator != and a version identifier.

The allowed version identifiers and comparison semantics are the same as those of the Version matching operator, except that the sense of any match is inverted.

Ordered comparison

Inclusive comparisons allow for the version identifier part of clauses whereas exclusive comparisons do not. For example, >=1.2 allows for version 1.2.0 while >1.2 does not.

Unlike the inclusive ordered comparisons <= and >=, the exclusive ordered comparisons < and > specifically exclude pre-releases, post-releases, and local versions of the specified version.

Arbitrary equality

Though heavily discouraged, arbitrary equality comparisons allow for simple string matching without any version semantics, for example ===foobar.

Environment markers

Environment markers allow for dependencies to only be installed when certain conditions are met.

For example, if you need to install the latest version of cryptography that is available for a given Python major version you could define the following:

cryptography==3.3.2; python_version < "3"
+cryptography>=35.0; python_version > "3"
+

Alternatively, if you only need it on Python 3 when running on Windows you could do:

cryptography; python_version ~= "3.0" and platform_system == "Windows"
+

The available environment markers are as follows.

Marker Python equivalent Examples
os_name import os
os.name
  • posix
  • java
sys_platform import sys
sys.platform
  • linux
  • win32
  • darwin
platform_machine import platform
platform.machine()
  • x86_64
platform_python_implementation import platform
platform.python_implementation()
  • CPython
  • Jython
platform_release import platform
platform.release()
  • 1.8.0_51
  • 3.14.1-x86_64-linode39
platform_system import platform
platform.system()
  • Linux
  • Windows
  • Darwin
platform_version import platform
platform.version()
  • 10.0.19041
  • #1 SMP Fri Apr 2 22:23:49 UTC 2021
python_version import platform
'.'.join(platform.python_version_tuple()[:2])
  • 2.7
  • 3.10
python_full_version import platform
platform.python_version()
  • 2.7.18
  • 3.11.0b1
implementation_name import sys
sys.implementation.name
  • cpython
implementation_version See here
  • 2.7.18
  • 3.11.0b1

Features

You can select groups of optional dependencies to install using the extras syntax. For example, if a dependency named foo defined the following:

[project.optional-dependencies]
+crypto = [
+  "PyJWT",
+  "cryptography",
+]
+fastjson = [
+  "orjson",
+]
+cli = [
+  "prompt-toolkit",
+  "colorama; platform_system == 'Windows'",
+]
+

You can select the cli and crypto features like so:

foo[cli,crypto]==1.*
+

Note that the features come immediately after the package name, before any version specifiers.

Self-referential

Feature groups can self-referentially extend others. For example, for a project called awesome-project, the dev feature group in the following pyproject.toml file would select everything in the crypto feature group, plus black:

[project]
+name = "awesome-project"
+
+[project.optional-dependencies]
+crypto = [
+  "PyJWT",
+  "cryptography",
+]
+dev = [
+  "awesome-project[crypto]",
+  "black",
+]
+

Direct references

Instead of using normal version specifiers and fetching packages from an index like PyPI, you can define exact sources using direct references with an explicit URI.

Direct references are usually not meant to be used for dependencies of a published project but rather are used for defining dependencies for an environment.

All direct reference types are prefixed by the package name like:

<NAME> @ <REFERENCE>
+

Version control systems

Various version control systems (VCS) are supported as long as the associated executable is available along your PATH.

VCS direct references are defined using one of the following formats:

<NAME> @ <SCHEME>://<PATH>
+<NAME> @ <SCHEME>://<PATH>@<REVISION>
+

You may also append a #subdirectory=<PATH> component for specifying the relative path to the Python package when it is not located at the root e.g. #subdirectory=lib/foo.

For more information, refer to this.

Supported VCS

Executable Schemes Revisions Example
git
  • git+file
  • git+https
  • git+ssh
  • git+http ⚠
  • git+git ⚠
  • git ⚠
  • Commit hash
  • Tag name
  • Branch name
proj @ git+https://github.com/org/proj.git@v1
Executable Schemes Revisions Example
hg
  • hg+file
  • hg+https
  • hg+ssh
  • hg+http ⚠
  • hg+static-http ⚠
  • Revision hash
  • Revision number
  • Tag name
  • Branch name
proj @ hg+file:///path/to/proj@v1
Executable Schemes Revisions Example
svn
  • svn+https
  • svn+ssh
  • svn+http ⚠
  • svn+svn ⚠
  • svn ⚠
  • Revision number
proj @ svn+file:///path/to/proj
Executable Schemes Revisions Example
bzr
  • bzr+https
  • bzr+ssh
  • bzr+sftp
  • bzr+lp
  • bzr+http ⚠
  • bzr+ftp ⚠
  • Revision number
  • Tag name
proj @ bzr+lp:proj@v1

Local

You can install local packages with the file scheme in the following format:

<NAME> @ file://<HOST>/<PATH>
+

The <HOST> is only used on Windows systems, where it can refer to a network share. If omitted it is assumed to be localhost and the third slash must still be present.

The <PATH> can refer to a source archive, a wheel, or a directory containing a Python package.

Type Unix Windows
Source archive proj @ file:///path/to/pkg.tar.gz proj @ file:///c:/path/to/pkg.tar.gz
Wheel proj @ file:///path/to/pkg.whl proj @ file:///c:/path/to/pkg.whl
Directory proj @ file:///path/to/pkg proj @ file:///c:/path/to/pkg

Tip

You may also specify paths relative to your project's root directory on all platforms by using context formatting:

<NAME> @ {root:uri}/pkg_inside_project
+<NAME> @ {root:parent:uri}/pkg_alongside_project
+

Remote

You can install source archives and wheels by simply referring to a URL:

black @ https://github.com/psf/black/archive/refs/tags/21.10b0.zip
+pytorch @ https://download.pytorch.org/whl/cu102/torch-1.10.0%2Bcu102-cp39-cp39-linux_x86_64.whl
+

An expected hash value may be specified by appending a #<HASH_ALGORITHM>=<EXPECTED_HASH> component:

requests @ https://github.com/psf/requests/archive/refs/tags/v2.26.0.zip#sha256=eb729a757f01c10546ebd179ae2aec852dd0d7f8ada2328ccf4558909d859985
+

If the hash differs from the expected hash, the installation will fail.

It is recommended that only hashes which are unconditionally provided by the latest version of the standard library's hashlib module be used for hashes. As of Python 3.10, that list consists of:

  • md5
  • sha1
  • sha224
  • sha256
  • sha384
  • sha512
  • blake2b
  • blake2s

Complex syntax

The following is an example that uses features and environment markers:

pkg[feature1,feature2] @ <REFERENCE> ; python_version < "3.7"
+

Note that the space before the semicolon is required.

\ No newline at end of file diff --git a/1.13/config/environment/advanced/index.html b/1.13/config/environment/advanced/index.html new file mode 100644 index 000000000..1a0f17af9 --- /dev/null +++ b/1.13/config/environment/advanced/index.html @@ -0,0 +1,237 @@ + Advanced environment configuration - Hatch

Advanced environment configuration


Context formatting

All environments support the following extra context formatting fields:

Field Description
env_name The name of the environment
env_type The type of environment
matrix Its modifier selects the value of that matrix variable. If the environment is not part of a matrix or was not generated with the variable, you must specify a default value as an additional modifier e.g. {matrix:version:v1.0.0}.
verbosity The integer verbosity value of Hatch. A flag modifier is supported that will render the value as a CLI flag e.g. -2 becomes -qq, 1 becomes -v, and 0 becomes an empty string. An additional flag integer modifier may be used to adjust the verbosity level. For example, if you wanted to make a command quiet by default, you could use {verbosity:flag:-1} within the command.
args For executed commands only, any extra command line arguments with an optional default modifier if none were provided

Matrix

Environments can define a series of matrices with the matrix option:

[tool.hatch.envs.test]
+dependencies = [
+  "pytest"
+]
+
+[[tool.hatch.envs.test.matrix]]
+python = ["3.10", "3.11"]
+version = ["42", "3.14"]
+
+[[tool.hatch.envs.test.matrix]]
+python = ["3.11", "3.12"]
+version = ["9000"]
+feature = ["foo", "bar"]
+
[envs.test]
+dependencies = [
+  "pytest"
+]
+
+[[envs.test.matrix]]
+python = ["3.10", "3.11"]
+version = ["42", "3.14"]
+
+[[envs.test.matrix]]
+python = ["3.11", "3.12"]
+version = ["9000"]
+feature = ["foo", "bar"]
+

Doing so will result in the product of each variable combination being its own environment.

Naming

The name of the generated environments will be the variable values of each combination separated by hyphens, altogether prefixed by <ENV_NAME>.. For example, the following configuration:

[[tool.hatch.envs.test.matrix]]
+version = ["42"]
+feature = ["foo", "bar"]
+
[[envs.test.matrix]]
+version = ["42"]
+feature = ["foo", "bar"]
+

would indicate the following unique environments:

test.42-foo
+test.42-bar
+

The exceptions to this format are described below.

Python variables

If the variables py or python are specified, then they will rank first in the product result and will be prefixed by py if the value is not. For example, the following configuration:

[[tool.hatch.envs.test.matrix]]
+version = ["42"]
+python = ["3.9", "pypy3"]
+
[[envs.test.matrix]]
+version = ["42"]
+python = ["3.9", "pypy3"]
+

would generate the following environments:

test.py3.9-42
+test.pypy3-42
+

Note

The value of this variable sets the Python version.

Name formatting

You can set the matrix-name-format option to modify how each variable part is formatted which recognizes the placeholders {variable} and {value}. For example, the following configuration:

[tool.hatch.envs.test]
+matrix-name-format = "{variable}_{value}"
+
+[[tool.hatch.envs.test.matrix]]
+version = ["42"]
+feature = ["foo", "bar"]
+
[envs.test]
+matrix-name-format = "{variable}_{value}"
+
+[[envs.test.matrix]]
+version = ["42"]
+feature = ["foo", "bar"]
+

would produce the following environments:

test.version_42-feature_foo
+test.version_42-feature_bar
+

By default this option is set to {value}.

Default environment

If the default environment defines matrices, then the generated names will not be prefixed by the environment name. This can be useful for projects that only need a single series of matrices without any standalone environments.

Selection

Rather than selecting a single generated environment, you can select the root environment to target all of them. For example, if you have the following configuration:

[tool.hatch.envs.test]
+dependencies = [
+  "coverage[toml]",
+  "pytest",
+  "pytest-cov",
+]
+
+[tool.hatch.envs.test.scripts]
+cov = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests'
+
+[[tool.hatch.envs.test.matrix]]
+python = ["3.11", "3.12"]
+version = ["42", "3.14"]
+
[envs.test]
+dependencies = [
+  "coverage[toml]",
+  "pytest",
+  "pytest-cov",
+]
+
+[envs.test.scripts]
+cov = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests'
+
+[[envs.test.matrix]]
+python = ["3.11", "3.12"]
+version = ["42", "3.14"]
+

you could then run your tests consecutively in all 4 environments with:

hatch run test:cov
+

Option overrides

You can modify options based on the conditions of different sources like matrix variables with the overrides table, using dotted key syntax for each declaration:

[tool.hatch.envs.<ENV_NAME>.overrides]
+<SOURCE>.<CONDITION>.<OPTION> = <VALUE>
+
[envs.<ENV_NAME>.overrides]
+<SOURCE>.<CONDITION>.<OPTION> = <VALUE>
+

The type of the selected option determines the types of values.

Platform overrides

Options can be modified based on the current platform using the platform source.

[tool.hatch.envs.test.overrides]
+platform.windows.scripts = [
+  'run=pytest -m "not io_uring"',
+]
+
[envs.test.overrides]
+platform.windows.scripts = [
+  'run=pytest -m "not io_uring"',
+]
+

The following platforms are supported:

  • linux
  • windows
  • macos

Environment variable overrides

Environment variables can modify options using the env source.

[tool.hatch.envs.test.overrides]
+env.GITHUB_ACTIONS.dev-mode = { value = false, if = ["true"] }
+
[envs.test.overrides]
+env.GITHUB_ACTIONS.dev-mode = { value = false, if = ["true"] }
+

Matrix variable overrides

The matrix variables used to generate each environment can be used to modify options within using the matrix source.

[tool.hatch.envs.test.overrides]
+matrix.version.env-vars = "PRODUCT_VERSION"
+matrix.auth.features = [
+  { value = "oauth", if = ["oauth2"] },
+  { value = "kerberos", if = ["kerberos"] },
+]
+
+[[tool.hatch.envs.test.matrix]]
+python = ["3.11", "3.12"]
+version = ["legacy", "latest"]
+auth = ["oauth2", "kerberos", "noauth"]
+
[envs.test.overrides]
+matrix.version.env-vars = "PRODUCT_VERSION"
+matrix.auth.features = [
+  { value = "oauth", if = ["oauth2"] },
+  { value = "kerberos", if = ["kerberos"] },
+]
+
+[[envs.test.matrix]]
+python = ["3.11", "3.12"]
+version = ["legacy", "latest"]
+auth = ["oauth2", "kerberos", "noauth"]
+

Name overrides

When a matrix is defined, the name source can be used for regular expression matching on the generated name, minus the prefix for non-default environments.

[tool.hatch.envs.test.overrides]
+name."^0".env-vars = "TESTING_UNSTABLE=true"
+
+[[tool.hatch.envs.test.matrix]]
+version = ["0.1.0", "0.2.0", "1.0.0"]
+
[envs.test.overrides]
+name."^0".env-vars = "TESTING_UNSTABLE=true"
+
+[[envs.test.matrix]]
+version = ["0.1.0", "0.2.0", "1.0.0"]
+

Types

  • Literal types like strings for the Python version or booleans for skipping installation can be set using the value itself, an inline table, or an array. For example:

    [tool.hatch.envs.test.overrides]
    +matrix.foo.python = "3.10"
    +matrix.bar.skip-install = { value = true, if = ["..."] }
    +env.CI.dev-mode = [
    +  { value = false, if = ["..."] },
    +  true,
    +]
    +
    [envs.test.overrides]
    +matrix.foo.python = "3.10"
    +matrix.bar.skip-install = { value = true, if = ["..."] }
    +env.CI.dev-mode = [
    +  { value = false, if = ["..."] },
    +  true,
    +]
    +

    For arrays, the first allowed value will be used.

  • Array types like dependencies or commands can be appended to using an array of strings or inline tables. For example:

    [tool.hatch.envs.test.overrides]
    +matrix.foo.dependencies = [
    +  "httpx",
    +  { value = "cryptography" },
    +]
    +
    [envs.test.overrides]
    +matrix.foo.dependencies = [
    +  "httpx",
    +  { value = "cryptography" },
    +]
    +
  • Mapping types like environment variables or scripts can have keys set using a string, or an array of strings or inline tables. For example:

    [tool.hatch.envs.test.overrides]
    +matrix.foo.env-vars = "KEY=VALUE"
    +matrix.bar.env-vars = [
    +  "KEY1=VALUE1",
    +  { key = "KEY2", value = "VALUE2" },
    +]
    +
    [envs.test.overrides]
    +matrix.foo.env-vars = "KEY=VALUE"
    +matrix.bar.env-vars = [
    +  "KEY1=VALUE1",
    +  { key = "KEY2", value = "VALUE2" },
    +]
    +

    If the value is missing (no = for strings, no value key for inline tables), then the value will be set to the value of the source condition.

Overwriting

Rather than supplementing the values within mapping types or array types, you can overwrite the option as a whole by prefixing the name with set-:

[tool.hatch.envs.test.overrides]
+matrix.foo.set-platforms = ["macos", "linux"]
+
[envs.test.overrides]
+matrix.foo.set-platforms = ["macos", "linux"]
+

When overwriting entire options or keys within mappings, override sources are applied in the following order:

  1. platform
  2. environment variables
  3. matrix variables
  4. names

Conditions

You may specify certain extra keys for any inline table that will determine whether or not to apply that entry. These modifiers may be combined with others and any negative evaluation will immediately cause the entry to be skipped.

Allowed values

The if key represents the allowed values for that condition. If the value of the condition is not listed, then that entry will not be applied:

[tool.hatch.envs.test.overrides]
+matrix.version.python = { value = "pypy", if = ["3.14"] }
+matrix.version.env-vars = [
+  { key = "KEY1", value = "VALUE1", if = ["42"] },
+  { key = "KEY2", value = "VALUE2", if = ["3.14"] },
+]
+
+[[tool.hatch.envs.test.matrix]]
+version = ["42", "3.14"]
+
[envs.test.overrides]
+matrix.version.python = { value = "pypy", if = ["3.14"] }
+matrix.version.env-vars = [
+  { key = "KEY1", value = "VALUE1", if = ["42"] },
+  { key = "KEY2", value = "VALUE2", if = ["3.14"] },
+]
+
+[[envs.test.matrix]]
+version = ["42", "3.14"]
+

Specific platforms

The platform key represents the desired platforms. If the current platform is not listed, then that entry will not be applied:

[tool.hatch.envs.test.overrides]
+env.EXPERIMENTAL.python = { value = "pypy", if = ["1"], platform = ["macos"] }
+matrix.version.env-vars = [
+  { key = "KEY1", value = "VALUE1", if = ["42"], platform = ["linux"] },
+  { key = "KEY2", value = "VALUE2", if = ["3.14"] },
+]
+
+[[tool.hatch.envs.test.matrix]]
+version = ["42", "3.14"]
+
[envs.test.overrides]
+env.EXPERIMENTAL.python = { value = "pypy", if = ["1"], platform = ["macos"] }
+matrix.version.env-vars = [
+  { key = "KEY1", value = "VALUE1", if = ["42"], platform = ["linux"] },
+  { key = "KEY2", value = "VALUE2", if = ["3.14"] },
+]
+
+[[envs.test.matrix]]
+version = ["42", "3.14"]
+

Required environment variables

The env key represents the required environment variables. If any of the listed environment variables are not set or the defined value does not match, then that entry will not be applied:

[tool.hatch.envs.test.overrides]
+platform.windows.python = { value = "pypy", env = ["EXPERIMENTAL"] }
+matrix.version.env-vars = [
+  { key = "KEY1", value = "VALUE1", if = ["42"], env = ["FOO", "BAR=BAZ"] },
+  { key = "KEY2", value = "VALUE2", if = ["3.14"] },
+]
+
+[[tool.hatch.envs.test.matrix]]
+version = ["42", "3.14"]
+
[envs.test.overrides]
+platform.windows.python = { value = "pypy", env = ["EXPERIMENTAL"] }
+matrix.version.env-vars = [
+  { key = "KEY1", value = "VALUE1", if = ["42"], env = ["FOO", "BAR=BAZ"] },
+  { key = "KEY2", value = "VALUE2", if = ["3.14"] },
+]
+
+[[envs.test.matrix]]
+version = ["42", "3.14"]
+
\ No newline at end of file diff --git a/1.13/config/environment/index.html b/1.13/config/environment/index.html new file mode 100644 index 000000000..cd8a1ec09 --- /dev/null +++ b/1.13/config/environment/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/config/environment/overview/index.html b/1.13/config/environment/overview/index.html new file mode 100644 index 000000000..92b910790 --- /dev/null +++ b/1.13/config/environment/overview/index.html @@ -0,0 +1,215 @@ + Environment configuration - Hatch

Environment configuration


All environments are defined as sections within the tool.hatch.envs table.

[tool.hatch.envs.<ENV_NAME>]
+
[envs.<ENV_NAME>]
+

The storage location for environments is completely configurable.

Unless an environment is explicitly selected on the command line, the default environment will be used. The type of this environment defaults to virtual.

Info

Environments prefixed by hatch- are used for special purposes e.g. testing.

Inheritance

All environments inherit from the environment defined by its template option, which defaults to default.

So for the following configuration:

[tool.hatch.envs.foo]
+type = "baz"
+skip-install = true
+
+[tool.hatch.envs.bar]
+template = "foo"
+skip-install = false
+
[envs.foo]
+type = "baz"
+skip-install = true
+
+[envs.bar]
+template = "foo"
+skip-install = false
+

the environment bar will be of type baz with skip-install set to false.

Note

Environments do not inherit matrices.

Self-referential environments

You can disable inheritance by setting template to the environment's own name:

[tool.hatch.envs.foo]
+template = "foo"
+
[envs.foo]
+template = "foo"
+

Detached environments

A common use case is standalone environments that do not require inheritance nor the installation of the project, such as for linting or sometimes building documentation. Enabling the detached option will make the environment self-referential and will skip project installation:

[tool.hatch.envs.lint]
+detached = true
+
[envs.lint]
+detached = true
+

Dependencies

You can install dependencies in addition to the ones defined by your project's metadata. Entries support context formatting.

[tool.hatch.envs.test]
+dependencies = [
+  "coverage[toml]",
+  "pytest",
+  "pytest-cov",
+  "pytest-mock",
+]
+
[envs.test]
+dependencies = [
+  "coverage[toml]",
+  "pytest",
+  "pytest-cov",
+  "pytest-mock",
+]
+

If you define environments with dependencies that only slightly differ from their inherited environments, you can use the extra-dependencies option to avoid redeclaring the dependencies option:

[tool.hatch.envs.default]
+dependencies = [
+  "foo",
+  "bar",
+]
+
+[tool.hatch.envs.experimental]
+extra-dependencies = [
+  "baz",
+]
+
[envs.default]
+dependencies = [
+  "foo",
+  "bar",
+]
+
+[envs.experimental]
+extra-dependencies = [
+  "baz",
+]
+

Tip

Hatch uses pip to install dependencies so any configuration it supports Hatch does as well. For example, if you wanted to only use a private repository you could set the PIP_INDEX_URL environment variable.

Installation

Features (extras)

If your project defines optional dependencies, you can select which groups to install using the features option:

[tool.hatch.envs.nightly]
+features = [
+  "server",
+  "grpc",
+]
+
[envs.nightly]
+features = [
+  "server",
+  "grpc",
+]
+

Note

Features/optional dependencies are also known as extras in other tools.

Dev mode

By default, environments will always reflect the current state of your project on disk. Set dev-mode to false to disable this behavior:

[tool.hatch.envs.static]
+dev-mode = false
+
[envs.static]
+dev-mode = false
+

Skip install

By default, environments will install your project during creation. To ignore this step, set skip-install to true:

[tool.hatch.envs.lint]
+skip-install = true
+
[envs.lint]
+skip-install = true
+

Environment variables

Defined

You can define environment variables with the env-vars option:

[tool.hatch.envs.docs]
+dependencies = [
+  "mkdocs"
+]
+[tool.hatch.envs.docs.env-vars]
+SOURCE_DATE_EPOCH = "1580601600"
+
[envs.docs]
+dependencies = [
+  "mkdocs"
+]
+[envs.docs.env-vars]
+SOURCE_DATE_EPOCH = "1580601600"
+

Values support context formatting.

Filters

By default, environments will have access to all environment variables. You can filter with wildcard patterns using the env-include/env-exclude options:

[tool.hatch.envs.<ENV_NAME>]
+env-include = [
+  "FOO*",
+]
+env-exclude = [
+  "BAR",
+]
+
[envs.<ENV_NAME>]
+env-include = [
+  "FOO*",
+]
+env-exclude = [
+  "BAR",
+]
+

Exclusion patterns take precedence but will never affect defined environment variables.

Scripts

You can define named scripts that may be executed or referenced at the beginning of other scripts. Context formatting is supported.

For example, in the following configuration:

[tool.hatch.envs.test]
+dependencies = [
+  "coverage[toml]",
+  "pytest",
+  "pytest-cov",
+  "pytest-mock",
+]
+[tool.hatch.envs.test.scripts]
+run-coverage = "pytest --cov-config=pyproject.toml --cov=pkg --cov=tests"
+run = "run-coverage --no-cov"
+
[envs.test]
+dependencies = [
+  "coverage[toml]",
+  "pytest",
+  "pytest-cov",
+  "pytest-mock",
+]
+[envs.test.scripts]
+run-coverage = "pytest --cov-config=pyproject.toml --cov=pkg --cov=tests"
+run = "run-coverage --no-cov"
+

the run script would be expanded to:

pytest --cov-config=pyproject.toml --cov=pkg --cov=tests --no-cov
+

Scripts can also be defined as an array of strings.

[tool.hatch.envs.style]
+detached = true
+dependencies = [
+  "flake8",
+  "black",
+  "isort",
+]
+[tool.hatch.envs.style.scripts]
+check = [
+  "flake8 .",
+  "black --check --diff .",
+  "isort --check-only --diff .",
+]
+fmt = [
+  "isort .",
+  "black .",
+  "check",
+]
+
[envs.style]
+detached = true
+dependencies = [
+  "flake8",
+  "black",
+  "isort",
+]
+[envs.style.scripts]
+check = [
+  "flake8 .",
+  "black --check --diff .",
+  "isort --check-only --diff .",
+]
+fmt = [
+  "isort .",
+  "black .",
+  "check",
+]
+

Similar to make, you can ignore the exit code of commands that start with - (a hyphen). For example, the script error defined by the following configuration would halt after the second command with 3 as the exit code:

[tool.hatch.envs.test.scripts]
+error = [
+  "- exit 1",
+  "exit 3",
+  "exit 0",
+]
+
[envs.test.scripts]
+error = [
+  "- exit 1",
+  "exit 3",
+  "exit 0",
+]
+

Extra scripts

Individual scripts inherit from parent environments just like options. To guarantee that individual scripts do not override those defined by parent environments, you can use the extra-scripts option instead which is only capable of adding scripts that have not been defined.

Commands

All commands are able to use any defined scripts. Also like scripts, context formatting is supported and the exit code of commands that start with a hyphen will be ignored.

Pre-install

You can run commands immediately before environments install your project.

[tool.hatch.envs.<ENV_NAME>]
+pre-install-commands = [
+  "...",
+]
+
[envs.<ENV_NAME>]
+pre-install-commands = [
+  "...",
+]
+

Post-install

You can run commands immediately after environments install your project.

[tool.hatch.envs.<ENV_NAME>]
+post-install-commands = [
+  "...",
+]
+
[envs.<ENV_NAME>]
+post-install-commands = [
+  "...",
+]
+

Python version

The python option specifies which version of Python to use, or an absolute path to a Python interpreter:

[tool.hatch.envs.<ENV_NAME>]
+python = "3.10"
+
[envs.<ENV_NAME>]
+python = "3.10"
+

All environment types should respect this option.

Supported platforms

The platforms option indicates the operating systems with which the environment is compatible:

[tool.hatch.envs.<ENV_NAME>]
+platforms = ["linux", "windows", "macos"]
+
[envs.<ENV_NAME>]
+platforms = ["linux", "windows", "macos"]
+

The following platforms are supported:

  • linux
  • windows
  • macos

If unspecified, the environment is assumed to be compatible with all platforms.

Description

The description option is purely informational and is displayed in the output of the env show command:

[tool.hatch.envs.<ENV_NAME>]
+description = """
+Lorem ipsum ...
+"""
+
[envs.<ENV_NAME>]
+description = """
+Lorem ipsum ...
+"""
+

Type

An environment's type determines which environment plugin will be used for management. The only built-in environment type is virtual, which uses virtual Python environments.

\ No newline at end of file diff --git a/1.13/config/hatch/index.html b/1.13/config/hatch/index.html new file mode 100644 index 000000000..920c50195 --- /dev/null +++ b/1.13/config/hatch/index.html @@ -0,0 +1,50 @@ + Hatch configuration - Hatch

Hatch configuration


Configuration for Hatch itself is stored in a config.toml file located by default in one of the following platform-specific directories.

Platform Path
macOS ~/Library/Application Support/hatch
Windows %USERPROFILE%\AppData\Local\hatch
Unix $XDG_CONFIG_HOME/hatch (the XDG_CONFIG_HOME environment variable default is ~/.config)

You can select a custom path to the file using the --config root option or by setting the HATCH_CONFIG environment variable.

The file can be managed by the config command group.

Mode

The mode key controls how Hatch selects the project to work on.

Local

mode = "local"
+

By default, Hatch will look for a pyproject.toml file in the current working directory and any parent directories. The directory storing the first found file will be considered the project root.

Project

mode = "project"
+project = "proj1"
+
+[projects]
+proj1 = "/path/to/project1"
+proj2 = {"location": "/path/to/project2"}
+
+[dirs]
+project = ["/path/to/monorepo1", "/path/to/monorepo2"]
+

In this mode, Hatch will only work on the selected project. The project is located using multiple heuristics:

  1. If the project is defined in the projects table then it must be a string, or an inline table with a location key, that is the full path to the project.
  2. If the project matches a subdirectory in any of the directories listed in dirs.project, then that will be used as the project root.

An error will occur if the project cannot be found.

You can use the config set command to change the project you are working on:

$ hatch config set project proj2
+New setting:
+project = "proj2"
+

The project can be selected on a per-command basis with the -p/--project (environment variable HATCH_PROJECT) root option.

Aware

mode = "aware"
+

This is essentially the local mode with a fallback to the project mode.

Shell

You can control the shell used to enter environments with the shell key.

If defined as a string, it must be the name of one of the supported shells and be available along your PATH.

shell = "fish"
+

If the executable name of your shell differs from the supported name, you can define the shell as a table with name and path keys.

[shell]
+name = "bash"
+path = "/bin/ash"
+

You can change the default arguments used to spawn most shells with the args key. The default for such supported shells is usually ["-i"].

[shell]
+name = "bash"
+args = ["--login"]
+

Supported

Shell Name Arguments macOS Windows Unix
Almquist shell ash ["-i"] ✅ ✅
Bash bash ["-i"] ✅ ✅ ✅
Command Prompt cmd ✅
C shell csh ["-i"] ✅ ✅
fish fish ["-i"] ✅ ✅
Nushell nu [] ✅ ✅ ✅
PowerShell pwsh, powershell ✅ ✅ ✅
tcsh tcsh ["-i"] ✅ ✅
xonsh xonsh ["-i"] ✅ ✅ ✅
Z shell zsh ["-i"] ✅ ✅

Default

Hatch will attempt to use the current shell based on parent processes. If the shell cannot be determined, then on Windows systems Hatch will use the SHELL environment variable, if present, followed by the COMSPEC environment variable, defaulting to cmd. On all other platforms only the SHELL environment variable will be used, defaulting to bash.

Directories

Data

[dirs]
+data = "..."
+

This is the directory that is used to persist data. By default it is set to one of the following platform-specific directories.

Platform Path
macOS ~/Library/Application Support/hatch
Windows %USERPROFILE%\AppData\Local\hatch
Unix $XDG_DATA_HOME/hatch (the XDG_DATA_HOME environment variable default is ~/.local/share)

You can select a custom path to the directory using the --data-dir root option or by setting the HATCH_DATA_DIR environment variable.

Cache

[dirs]
+cache = "..."
+

This is the directory that is used to cache data. By default it is set to one of the following platform-specific directories.

Platform Path
macOS ~/Library/Caches/hatch
Windows %USERPROFILE%\AppData\Local\hatch\Cache
Unix $XDG_CACHE_HOME/hatch (the XDG_CACHE_HOME environment variable default is ~/.cache)

You can select a custom path to the directory using the --cache-dir root option or by setting the HATCH_CACHE_DIR environment variable.

Environments

[dirs.env]
+<ENV_TYPE> = "..."
+

This determines where to store environments, with every key being the type of environment and the value being the desired storage location.

For example, if you wanted to store virtual environments in a .virtualenvs directory within your home directory, you could specify the following:

[dirs.env]
+virtual = "~/.virtualenvs"
+

Any environment variables are also expanded.

If the path is not absolute, then it will be relative to the project root. So if you wanted to use a directory named .hatch in each project directory, you could do:

[dirs.env]
+virtual = ".hatch"
+

Any type of environment that is not explicitly defined will default to <DATA_DIR>/env/<ENV_TYPE>.

Python installations

[dirs]
+python = "..."
+

This determines where to install specific versions of Python.

The following values have special meanings:

Value Path
isolated (default) <DATA_DIR>/pythons

Terminal

You can configure how all output is displayed using the terminal.styles table. These settings are also applied to all plugins.

[terminal.styles]
+error = "..."
+...
+

Cross-platform terminal capabilities are provided by Rich.

Output levels

The levels of output are as follows. Note that the verbosity indicates the minimum level at which the output is displayed.

Level Default Verbosity Description
debug bold 1 - 3 Messages that are not useful for most user experiences
error bold red -2 Messages indicating some unrecoverable error
info bold 0 Messages conveying basic information
success bold cyan 0 Messages indicating some positive outcome
waiting bold magenta 0 Messages shown before potentially time consuming operations
warning bold yellow -1 Messages conveying important information

See the documentation and color reference for guidance on valid values.

Spinner

You can select the sequence used for waiting animations with the spinner option.

[terminal.styles]
+spinner = "..."
+
\ No newline at end of file diff --git a/1.13/config/internal/static-analysis/index.html b/1.13/config/internal/static-analysis/index.html new file mode 100644 index 000000000..c45996efd --- /dev/null +++ b/1.13/config/internal/static-analysis/index.html @@ -0,0 +1,68 @@ + Static analysis configuration - Hatch

Static analysis configuration


Static analysis performed by the fmt command is (by default) backed entirely by Ruff.

Hatch provides default settings that user configuration can extend.

Extending config

When defining your configuration, be sure to use options that are prefixed by extend- such as extend-select, for example:

[tool.ruff.format]
+preview = true
+quote-style = "single"
+
+[tool.ruff.lint]
+preview = true
+extend-select = ["C901"]
+
+[tool.ruff.lint.extend-per-file-ignores]
+"docs/.hooks/*" = ["INP001", "T201"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["foo", "bar"]
+
[format]
+preview = true
+quote-style = "single"
+
+[lint]
+preview = true
+extend-select = ["C901"]
+
+[lint.extend-per-file-ignores]
+"docs/.hooks/*" = ["INP001", "T201"]
+
+[lint.isort]
+known-first-party = ["foo", "bar"]
+

Note

When not persisting config, there is no need to explicitly extend the defaults as Hatch automatically handles that.

Persistent config

If you want to store the default configuration in the project, set an explicit path like so:

[tool.hatch.envs.hatch-static-analysis]
+config-path = "ruff_defaults.toml"
+
[envs.hatch-static-analysis]
+config-path = "ruff_defaults.toml"
+

Then instruct Ruff to consider your configuration as an extension of the default file:

[tool.ruff]
+extend = "ruff_defaults.toml"
+
extend = "ruff_defaults.toml"
+

Anytime you wish to update the defaults (such as when upgrading Hatch), you must run the fmt command once with the --sync flag e.g.:

hatch fmt --check --sync
+

Tip

This is the recommended approach since it allows other tools like IDEs to use the default configuration.

No config

If you don't want Hatch to use any of its default configuration and rely entirely on yours, set the path to anything and then simply don't extend in your Ruff config:

[tool.hatch.envs.hatch-static-analysis]
+config-path = "none"
+
[envs.hatch-static-analysis]
+config-path = "none"
+

Customize behavior

You can fully alter the behavior of the environment used by the fmt command. See the how-to for a detailed example.

Dependencies

Pin the particular version of Ruff by explicitly defining the environment dependencies:

[tool.hatch.envs.hatch-static-analysis]
+dependencies = ["ruff==X.Y.Z"]
+
[envs.hatch-static-analysis]
+dependencies = ["ruff==X.Y.Z"]
+

Scripts

If you want to change the default commands that are executed, you can override the scripts. The following four scripts must be defined:

[tool.hatch.envs.hatch-static-analysis.scripts]
+format-check = "..."
+format-fix = "..."
+lint-check = "..."
+lint-fix = "..."
+
[envs.hatch-static-analysis.scripts]
+format-check = "..."
+format-fix = "..."
+lint-check = "..."
+lint-fix = "..."
+

The format-* scripts correspond to the --formatter/-f flag while the lint-* scripts correspond to the --linter/-l flag. The *-fix scripts run by default while the *-check scripts correspond to the --check flag.

Reminder

If you choose to use different tools for static analysis, be sure to update the required dependencies.

Installer

By default, UV is enabled. You may disable that behavior as follows:

[tool.hatch.envs.hatch-static-analysis]
+installer = "pip"
+
[envs.hatch-static-analysis]
+installer = "pip"
+

Default settings

Non-rule settings

Per-file ignored rules

Selected rules

The following rules are based on version 0.4.5 of Ruff. Rules with a P are only selected when preview mode is enabled.

There are 525 selected stable rules and 129 selected preview rules.

Selected rules

Unselected

There are 175 unselected rules.

Unselected rules
\ No newline at end of file diff --git a/1.13/config/internal/testing/index.html b/1.13/config/internal/testing/index.html new file mode 100644 index 000000000..040a2f1e7 --- /dev/null +++ b/1.13/config/internal/testing/index.html @@ -0,0 +1,92 @@ + Testing configuration - Hatch

Testing configuration


Check out the testing overview tutorial for a more comprehensive walk-through.

Settings

If an option has a corresponding test command flag, the flag will always take precedence.

Default arguments

You can define default arguments for the test command by setting the default-args option, which must be an array of strings. The following is the default configuration:

[tool.hatch.envs.hatch-test]
+default-args = ["tests"]
+
[envs.hatch-test]
+default-args = ["tests"]
+

Extra arguments

You can define extra internal arguments for test scripts by setting the extra-args option, which must be an array of strings. For example, if you wanted to increase the verbosity of pytest, you could set the following:

[tool.hatch.envs.hatch-test]
+extra-args = ["-vv"]
+
[envs.hatch-test]
+extra-args = ["-vv"]
+

Randomize test order

You can randomize the order of tests by enabling the randomize option which corresponds to the --randomize/-r flag:

[tool.hatch.envs.hatch-test]
+randomize = true
+
[envs.hatch-test]
+randomize = true
+

Parallelize test execution

You can parallelize test execution by enabling the parallel option which corresponds to the --parallel/-p flag:

[tool.hatch.envs.hatch-test]
+parallel = true
+
[envs.hatch-test]
+parallel = true
+

Retry failed tests

You can retry failed tests by setting the retries option which corresponds to the --retries flag:

[tool.hatch.envs.hatch-test]
+retries = 2
+
[envs.hatch-test]
+retries = 2
+

You can also set the number of seconds to wait between retries by setting the retry-delay option which corresponds to the --retry-delay flag:

[tool.hatch.envs.hatch-test]
+retry-delay = 1
+
[envs.hatch-test]
+retry-delay = 1
+

Customize environment

You can fully alter the behavior of the environment used by the test command.

Dependencies

You can define extra dependencies that your tests may require:

[tool.hatch.envs.hatch-test]
+extra-dependencies = [
+  "pyfakefs",
+  "pytest-asyncio",
+  "pytest-benchmark",
+  "pytest-memray",
+  "pytest-playwright",
+  "pytest-print",
+]
+
[envs.hatch-test]
+extra-dependencies = [
+  "pyfakefs",
+  "pytest-asyncio",
+  "pytest-benchmark",
+  "pytest-memray",
+  "pytest-playwright",
+  "pytest-print",
+]
+

The following is the default configuration:

[tool.hatch.envs.hatch-test]
+dependencies = [
+  "coverage-enable-subprocess==1.0",
+  "coverage[toml]~=7.4",
+  "pytest~=8.1",
+  "pytest-mock~=3.12",
+  "pytest-randomly~=3.15",
+  "pytest-rerunfailures~=14.0",
+  "pytest-xdist[psutil]~=3.5",
+]
+
[envs.hatch-test]
+dependencies = [
+  "coverage-enable-subprocess==1.0",
+  "coverage[toml]~=7.4",
+  "pytest~=8.1",
+  "pytest-mock~=3.12",
+  "pytest-randomly~=3.15",
+  "pytest-rerunfailures~=14.0",
+  "pytest-xdist[psutil]~=3.5",
+]
+

Matrix

You can override the default series of matrices:

[[tool.hatch.envs.hatch-test.matrix]]
+python = ["3.13", "3.12", "3.11", "3.10", "3.9", "3.8"]
+
[[envs.hatch-test.matrix]]
+python = ["3.13", "3.12", "3.11", "3.10", "3.9", "3.8"]
+

Scripts

If you want to change the default commands that are executed, you can override the scripts. The following default scripts must be redefined:

[tool.hatch.envs.hatch-test.scripts]
+run = "pytest{env:HATCH_TEST_ARGS:} {args}"
+run-cov = "coverage run -m pytest{env:HATCH_TEST_ARGS:} {args}"
+cov-combine = "coverage combine"
+cov-report = "coverage report"
+
[envs.hatch-test.scripts]
+run = "pytest{env:HATCH_TEST_ARGS:} {args}"
+run-cov = "coverage run -m pytest{env:HATCH_TEST_ARGS:} {args}"
+cov-combine = "coverage combine"
+cov-report = "coverage report"
+

The run script is the default behavior while the run-cov script is used instead when measuring code coverage. The cov-combine script runs after all tests complete when measuring code coverage, as well as the cov-report script when not using the --cover-quiet flag.

Note

The HATCH_TEST_ARGS environment variable is how the test command's flags are translated and internally populated without affecting the user's arguments. This is also the way that extra arguments are passed.

Installer

By default, UV is enabled. You may disable that behavior as follows:

[tool.hatch.envs.hatch-test]
+installer = "pip"
+
[envs.hatch-test]
+installer = "pip"
+
\ No newline at end of file diff --git a/1.13/config/metadata/index.html b/1.13/config/metadata/index.html new file mode 100644 index 000000000..f6a9ea97f --- /dev/null +++ b/1.13/config/metadata/index.html @@ -0,0 +1,105 @@ + Configuring project metadata - Hatch

Configuring project metadata


Project metadata is stored in a pyproject.toml file located at the root of a project's tree and is based entirely on the standard.

Name (required)

The name of the project.

[project]
+name = "your-app"
+

Version (required)

See the dedicated versioning section.

[project]
+...
+dynamic = ["version"]
+
+[tool.hatch.version]
+path = "..."
+
[project]
+...
+version = "0.0.1"
+

Description

A brief summary of the project.

[project]
+...
+description = '...'
+

Readme

The full description of the project.

The file extension must be .md, .rst, or .txt.

[project]
+...
+readme = "README.md"
+

The content-type field must be set to text/markdown, text/x-rst, or text/plain.

A charset field may also be set to instruct which encoding to use for reading the file, defaulting to utf-8.

[project]
+...
+readme = {"file" = "README.md", "content-type" = "text/markdown"}
+

The content-type field must be set to text/markdown or text/x-rst.

[project]
+...
+readme = {"text" = "...", "content-type" = "text/markdown"}
+

Note

If this is defined as a file, then it will always be included in source distributions for consistent builds.

Python support

The Python version requirements of the project.

[project]
+...
+requires-python = ">=3.8"
+

License

For more information, see PEP 639.

[project]
+...
+license = "Apache-2.0 OR MIT"
+
[project]
+...
+license-files = { paths = ["LICENSE.txt"] }
+
[project]
+...
+license-files = { globs = ["LICENSES/*"] }
+

Ownership

The people or organizations considered to be the authors or maintainers of the project. The exact meaning is open to interpretation; it may list the original or primary authors, current maintainers, or owners of the package. If the values are the same, prefer only the use of the authors field.

[project]
+...
+authors = [
+  { name = "...", email = "..." },
+]
+maintainers = [
+  { name = "...", email = "..." },
+]
+

Keywords

The keywords used to assist in the discovery of the project.

[project]
+...
+keywords = [
+  "...",
+]
+

Classifiers

The trove classifiers that apply to the project.

[project]
+...
+classifiers = [
+  "...",
+]
+

URLs

A table of URLs where the key is the URL label and the value is the URL itself.

[project.urls]
+Documentation = "..."
+"Source code" = "..."
+

Dependencies

See the dependency specification page for more information.

Entries support context formatting and disallow direct references by default.

Required

[project]
+...
+dependencies = [
+  "...",
+]
+

Optional

[project.optional-dependencies]
+option1 = [
+  "...",
+]
+option2 = [
+  "...",
+]
+

Entry points

Entry points are a mechanism for the project to advertise components it provides to be discovered and used by other code.

CLI

After installing projects that define CLI scripts, each key will be available along your PATH as a command that will call its associated object.

[project.scripts]
+cli-name = "pkg.subpkg:func"
+

Using the above example, running cli-name would essentially execute the following Python script:

import sys
+
+from pkg.subpkg import func
+
+sys.exit(func())
+

GUI

GUI scripts are exactly the same as CLI scripts except on Windows, where they are handled specially so that they can be started without a console.

[project.gui-scripts]
+gui-name = "pkg.subpkg:func"
+

Plugins

[project.entry-points.plugin-namespace]
+plugin-name1 = "pkg.subpkg1"
+plugin-name2 = "pkg.subpkg2:func"
+

Dynamic

If any metadata fields are set dynamically, like the version may be, then they must be listed here.

[project]
+...
+dynamic = [
+  "...",
+]
+

Metadata options

Allowing direct references

By default, dependencies are not allowed to define direct references. To disable this check, set allow-direct-references to true:

[tool.hatch.metadata]
+allow-direct-references = true
+
[metadata]
+allow-direct-references = true
+

Allowing ambiguous features

By default, names of optional dependencies are normalized to prevent ambiguity. To disable this normalization, set allow-ambiguous-features to true:

[tool.hatch.metadata]
+allow-ambiguous-features = true
+
[metadata]
+allow-ambiguous-features = true
+

Deprecated

This option temporarily exists to provide better interoperability with tools that do not yet support PEP 685 and will be removed in the first minor release after Jan 1, 2024.

\ No newline at end of file diff --git a/1.13/config/project-templates/index.html b/1.13/config/project-templates/index.html new file mode 100644 index 000000000..e45227190 --- /dev/null +++ b/1.13/config/project-templates/index.html @@ -0,0 +1,26 @@ + Project templates - Hatch

Project templates


You can control how new projects are created by the new command using Hatch's config file.

Author

[template]
+name = "..."
+email = "..."
+

Licenses

[template.licenses]
+headers = true
+default = [
+  "MIT",
+]
+

The list of licenses should be composed of SPDX identifiers. If multiple licenses are specified, then they will be placed in a LICENSES directory.

Options

Tests

This adds a tests directory with environments for testing and linting.

[template.plugins.default]
+tests = true
+

CI

This adds a GitHub Actions workflow that runs tests on all platforms using modern versions of Python.

[template.plugins.default]
+ci = false
+

src layout

See this blog post.

[template.plugins.default]
+src-layout = true
+

Feature flags

Command line interface

The --cli flag adds a CLI backed by Click that can also be invoked with python -m <PKG_NAME>.

\ No newline at end of file diff --git a/1.13/config/static-analysis/index.html b/1.13/config/static-analysis/index.html new file mode 100644 index 000000000..2faec24af --- /dev/null +++ b/1.13/config/static-analysis/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/environment/index.html b/1.13/environment/index.html new file mode 100644 index 000000000..c30d4c346 --- /dev/null +++ b/1.13/environment/index.html @@ -0,0 +1,103 @@ + Environments - Hatch

Environments


Environments are designed to allow for isolated workspaces for testing, building documentation, or anything else projects need.

Unless an environment is chosen explicitly, Hatch will use the default environment.

Tip

For a more comprehensive walk-through, see the Basic usage tutorial.

Creation

You can create environments by using the env create command. Let's enter the directory of the project we created in the setup phase:

$ hatch env create
+Creating environment: default
+Installing project in development mode
+Syncing dependencies
+

Tip

You never need to manually create environments as spawning a shell or running commands within one will automatically trigger creation.

Entering environments

You can spawn a shell within an environment by using the shell command.

$ hatch shell
+(hatch-demo) $
+

Now confirm the project has been installed:

(hatch-demo) $ pip show hatch-demo
+Name: hatch-demo
+Version: 0.0.1
+...
+

Finally, see where your environment's Python is located:

(hatch-demo) $ python -c "import sys;print(sys.executable)"
+...
+

You can type exit to leave the environment.

Command execution

The run command allows you to execute commands in an environment as if you had already entered it. For example, running the following command will output the same path as before:

hatch run python -c "import sys;print(sys.executable)"
+

Tip

Be sure to check out how to define scripts for your project.

Dependencies

Hatch ensures that environments are always compatible with the currently defined project dependencies (if installed and in dev mode) and environment dependencies.

To add cowsay as a dependency, open pyproject.toml and add it to the dependencies array:

[project]
+...
+dependencies = [
+  "cowsay"
+]
+

This dependency will be installed the next time you spawn a shell or run a command. For example:

$ hatch run cowsay -t "Hello, world!"
+Syncing dependencies
+  _____________
+| Hello, world! |
+  =============
+             \
+              \
+                ^__^
+                (oo)\_______
+                (__)\       )\/\
+                    ||----w |
+                    ||     ||
+

Note

The Syncing dependencies status will display temporarily when Hatch updates environments in response to any dependency changes that you make.

Selection

You can select which environment to enter or run commands in by using the -e/--env root option or by setting the HATCH_ENV environment variable.

The run command allows for more explicit selection by prepending <ENV_NAME>: to commands. For example, if you had the following configuration:

[tool.hatch.envs.docs]
+dependencies = [
+  "mkdocs"
+]
+[tool.hatch.envs.docs.scripts]
+build = "mkdocs build --clean --strict"
+serve = "mkdocs serve --dev-addr localhost:8000"
+
[envs.docs]
+dependencies = [
+  "mkdocs"
+]
+[envs.docs.scripts]
+build = "mkdocs build --clean --strict"
+serve = "mkdocs serve --dev-addr localhost:8000"
+

you could then serve your documentation by running:

hatch run docs:serve
+

Tip

If you've already entered an environment, commands will target it by default.

Matrix

Every environment can define its own set of matrices:

[tool.hatch.envs.test]
+dependencies = [
+  "pytest"
+]
+
+[[tool.hatch.envs.test.matrix]]
+python = ["3.10", "3.11"]
+version = ["42", "3.14"]
+
+[[tool.hatch.envs.test.matrix]]
+python = ["3.11", "3.12"]
+version = ["9000"]
+feature = ["foo", "bar"]
+
[envs.test]
+dependencies = [
+  "pytest"
+]
+
+[[envs.test.matrix]]
+python = ["3.10", "3.11"]
+version = ["42", "3.14"]
+
+[[envs.test.matrix]]
+python = ["3.11", "3.12"]
+version = ["9000"]
+feature = ["foo", "bar"]
+

Using the env show command would then display:

$ hatch env show --ascii
+     Standalone
++---------+---------+
+| Name    | Type    |
++=========+=========+
+| default | virtual |
++---------+---------+
+                        Matrices
++------+---------+----------------------+--------------+
+| Name | Type    | Envs                 | Dependencies |
++======+=========+======================+==============+
+| test | virtual | test.py3.10-42       | pytest       |
+|      |         | test.py3.10-3.14     |              |
+|      |         | test.py3.11-42       |              |
+|      |         | test.py3.11-3.14     |              |
+|      |         | test.py3.11-9000-foo |              |
+|      |         | test.py3.11-9000-bar |              |
+|      |         | test.py3.12-9000-foo |              |
+|      |         | test.py3.12-9000-bar |              |
++------+---------+----------------------+--------------+
+

Removal

You can remove a single environment or environment matrix by using the env remove command or all of a project's environments by using the env prune command.

\ No newline at end of file diff --git a/1.13/history/hatch/index.html b/1.13/history/hatch/index.html new file mode 100644 index 000000000..b69b279f2 --- /dev/null +++ b/1.13/history/hatch/index.html @@ -0,0 +1,12 @@ + Hatch history - Hatch

Hatch history


All notable changes to Hatch will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

1.13.0 - 2024-10-13

Added:

  • Support managing Python 3.13 distributions

1.12.0 - 2024-05-28

Changed:

  • The run/env run and test commands now treat inclusion variable options as an intersection rather than a union to allow for specific targeting of environments

Added:

  • Add ability to control the source of Python distributions
  • Upgrade Ruff to 0.4.5
  • Upgrade PyApp to 0.22.0 for binary builds

Fixed:

  • The fmt command no longer hides the commands that are being executed
  • Add default timeout for network requests, useful when installing Python distributions
  • Fix syntax highlighting contrast for the config show command

1.11.1 - 2024-05-23

Added:

  • Add official GitHub Action for installing Hatch

Fixed:

  • Fix terminal.styles.spinner configuration
  • Fix entry points in the pre-built distributions that binaries use

1.11.0 - 2024-05-14

Added:

  • Upgrade PyApp to 0.21.1 for binary builds

Fixed:

  • On Linux, install the highest compatible Python distribution variant based on CPU architecture rather than assuming recent hardware

1.10.0 - 2024-05-02

Changed:

  • The run/env run, fmt and shell commands now only change the current working directory to the project root if not already inside the project
  • The shell command now accepts a single argument to specify the environment to enter which overrides the standard choice mechanisms. The arguments determining shell options have been converted to flags.

Added:

  • Add test command
  • The run command can now execute scripts that define inline metadata for dependencies and Python version constraints
  • The virtual environment type now supports the ability to use UV in place of pip & virtualenv
  • Add self report command for submitting pre-populated bug reports to GitHub
  • The reserved environment used for static analysis is now completely configurable
  • Add the following methods to the environment interface for complete control over output during life cycle management: app_status_creation, app_status_pre_installation, app_status_post_installation, app_status_project_installation, app_status_dependency_state_check, app_status_dependency_installation_check, app_status_dependency_synchronization
  • Add binaries for 32-bit versions of Windows
  • Read configuration from any ~/.pypirc file for the index publisher
  • Use the Git user as the default username for new project URL metadata
  • Add HATCH_DEBUG environment variable that when enabled will show local variables in the case of unhandled tracebacks
  • The env show command now outputs data about all internal environments when using the --json flag
  • Upgrade default CPython distributions to 20240415
  • Upgrade default PyPy distributions to 7.3.15
  • Upgrade Ruff to 0.4.2
  • Upgrade PyApp to 0.19.0 for binary builds
  • Bump the minimum supported version of Hatchling to 1.24.2
  • Bump the minimum supported version of virtualenv to 20.26.1

Fixed:

  • Maintain consistent data paths for case insensitive file systems
  • When projects derive dependencies from metadata hooks, there is now by default a status indicator for when the hooks are executed for better responsiveness
  • Properly support projects with a pyproject.toml file but no project table e.g. applications
  • Fix the fmt command when automatically installing plugin dependencies
  • Fix dependency inheritance for the template of the types environment for new projects
  • Fix warnings related to tar file extraction on Python 3.12+ when unpacking Python distributions for installation
  • De-select Ruff rule E501 for the fmt command by default since it conflicts with the formatter
  • Fix colored output from build targets on the first run (build environment creation status indicator issue)
  • Set the packaging dependency version as >=23.2 to avoid its URL validation which can conflict with context formatting
  • Fix the exit code when there happens to be an unhandled exception
  • No longer capture both stdout and stderr streams when parsing metadata payloads from build environments
  • Fix the README.md file template for new projects to avoid Markdown linting issues

1.9.7 - 2024-04-24

Fixed:

  • Limit the maximum version of virtualenv due to a backward incompatible change
  • Upgrade PyApp to 0.12.0 for binary builds

1.9.4 - 2024-03-12

Fixed:

  • Limit the maximum version of Hatchling in anticipation of backward incompatible changes

1.9.3 - 2024-01-25

Fixed:

  • Fix loading of local plugins to account for newly released versions of a dependency

1.9.2 - 2024-01-21

Fixed:

  • Fix the default token variable name for publishing to PyPI

1.9.1 - 2023-12-25

Fixed:

  • Ensure that the dependency_hash method of the environment interface is called after sync_dependencies for cases where the hash is only known at that point, such as for dependency lockers
  • Only acknowledge the HATCH_PYTHON_VARIANT_* environment variables for Python resolution for supported platforms and architectures
  • Fix Python resolution when there are metadata hooks with unsatisfied dependencies

1.9.0 - 2023-12-19

Changed:

  • Environments prefixed by hatch- are now considered internal and used for special purposes such as configuration for static analysis

Added:

  • Enable docstring formatting by default for static analysis
  • Allow for overriding config of internal environments
  • Concretely state the expected API contract for the environment interface methods find and check_compatibility
  • Upgrade Ruff to 0.1.8
  • Bump the minimum supported version of Hatchling to 1.21.0

Fixed:

  • Ignore a project's Python requirement for environments where the project is not installed
  • When not persisting config for static analysis, properly manage internal settings when Ruff's top level table already exists
  • Ignore compatibility checks when environments have already been created, significantly improving performance of environment usage
  • Properly allow overriding of the path option for the virtual environment type
  • Fix nushell activation on non-Windows systems

1.8.1 - 2023-12-14

Fixed:

  • Fix regression in calling subprocesses with updated PATH
  • Fix automatic installation of environment plugins when running as a standalone binary
  • Change default location of Python installations

1.8.0 - 2023-12-11

Changed:

  • Drop support for Python 3.7
  • The get_build_process method of the environment interface has been removed; plugins should use the new run_builder method instead
  • Remove pyperclip dependency and the --copy flag of the config find command
  • When running the build command all output from builders is now displayed as-is in real time without the stripping of ANSI codes
  • Version information (for Hatch itself) is now derived from Git

Added:

  • Support Python 3.12
  • Add installers and standalone binaries
  • Add the ability to manage Python installations
  • Add fmt command
  • The virtual environment type can now automatically download requested versions of Python that are not installed
  • Add dependency_hash method to the environment interface
  • The state of installed dependencies for environments is saved as metadata so if dependency definitions have not changed then no checking is performed, which can be computationally expensive
  • The build command now supports backends other than Hatchling
  • Allow the use of features for environments when skip-install is enabled
  • The default is now __token__ when prompting for a username for the publish command
  • Add a new run_builder method to the environment interface
  • Bump the minimum supported version of Hatchling to 1.19.0
  • Bump the minimum supported version of click to 8.0.6

Fixed:

  • Fix nushell activation
  • Better handling of flat storage directory hierarchies for the virtual environment type
  • Display useful information when running the version command outside of a project rather than erroring
  • Fix the project metadata command by only capturing stdout from the backend
  • Properly support Google Artifact Registry
  • Fix parsing dependencies for environments when warnings are emitted

1.7.0 - 2023-04-03

Changed:

  • The src-layout project template option is now enabled by default
  • Non-critical output now goes to stderr

Added:

  • Add tool.hatch.env.requires configuration to automatically install dependencies for environment and environment collector plugins
  • Add custom environment collector
  • Improve syncing of dependencies provided through Git direct references
  • Add isolated_data_directory attribute to the environment interface
  • Increase the timeout for and add retries to the index publisher
  • Expand home and environment variables in configured cache and data directories
  • Improve readability of exceptions
  • Update project templates
  • Bump the minimum supported version of Hatchling to 1.14.0

Fixed:

  • Fix displaying the version with the version command when the version is static and build dependencies are unmet
  • Fix build environments for the virtual environment type when storing within a relative path
  • Work around System Integrity Protection on macOS when running commands
  • Allow setuptools metadata migration for projects without setup.py if setup.cfg is present
  • Handle additional edge cases for setuptools metadata migration
  • Support boolean values for the config set command

1.6.3 - 2022-10-24

Fixed:

  • Fix version command when the version is dynamic and build dependencies are unmet

1.6.2 - 2022-10-20

Fixed:

  • Fix getting dynamic metadata from hooks for environments when dependencies are not dynamic

1.6.1 - 2022-10-16

Fixed:

  • Computing the path to the user's home directory now gracefully falls back to ~ when it cannot be determined

1.6.0 - 2022-10-08

Changed:

  • The run_shell_command environment interface method now accepts arbitrary subprocess.Popen keyword arguments. This is not strictly breaking, but will be utilized in upcoming features.
  • The internal directory structure for storing virtual environments is now more nested. This is not breaking, but any local environments will be created anew.

Added:

  • Add project command group to view details about the project like PEP 621 metadata
  • Better support for auto-detection of environments by tools like Visual Studio Code now that the storage directory of virtual environments will be flat if Hatch's configured virtual environment directory resides somewhere within the project root or if it is set to a .virtualenvs directory within the user's home directory
  • Build environments for the virtual environment type are now cached for improved performance
  • Add build_environment_exists method to the environment interface for implementations that cache the build environment
  • Add path option to the virtual environment type
  • Add --initialize-auth flag to the index publisher to allow for the saving of authentication information before publishing
  • Support Bash on Windows for the shell command
  • The setuptools migration script no longer modifies the formatting of existing pyproject.toml configuration
  • Bump the minimum supported version of Hatchling to 1.11.0

Fixed:

  • Environments now respect dynamically defined project dependencies
  • The dep hash and all dep show commands now respect dynamically defined project dependencies
  • The env show, dep hash, and all dep show commands now honor context formatting
  • Fix matrix variable inclusion filtering of the run and env run commands when there are multiple possible variables
  • Build environment compatibility is now checked before use
  • Decreasing verbosity now has no affect on output that should always be displayed
  • Handle more edge cases in the setuptools migration script
  • Environments now respect user defined environment variables for context formatting
  • Update the scripts in the generated test environment template for new projects to reflect the documentation
  • Allow extra-dependencies in environment overrides
  • Depend on packaging explicitly rather than relying on it being a transitive dependency of Hatchling

1.5.0 - 2022-08-28

Added:

  • The index publisher now recognizes repository-specific options
  • Add the --ignore-compat flag to the env run command
  • Setting the HATCH_PYTHON environment variable to self will now force the use of the Python executable Hatch is running on for virtual environment creation

Fixed:

  • Fix the --force-continue flag of the env run command
  • Handle more edge cases in the setuptools migration script

1.4.2 - 2022-08-16

Fixed:

  • Fix check for updating static versions with the version command when metadata hooks are in use

1.4.1 - 2022-08-13

Fixed:

  • Fix non-detached inheritance disabling for environments

1.4.0 - 2022-08-06

Added:

  • The default Python for virtual environments now checks PATH before using the one Hatch is running on
  • Values for environment env-vars now support context formatting
  • Add name override for environments to allow for regular expression matching
  • The index publisher now better supports non-PyPI indices
  • Add certificate options to the index publisher
  • Display waiting text when checking dependencies and removing environments
  • Display help text the first time the shell command is executed
  • Update project templates with Python 3.11 and the latest versions of various GitHub Actions
  • Add support for Almquist (ash) shells
  • Add hyperlink as a dependency for better handling of package index URLs
  • Bump the minimum supported version of virtualenv to 20.16.2
  • Bump the minimum supported version of tomlkit to 0.11.1

Fixed:

  • Acknowledge extra-dependencies for the env show command
  • Fix locating executables within virtual environments on Debian
  • Fix managing the terminal size inside the shell command
  • Fix default code coverage file omission for the src-layout project template option

1.3.1 - 2022-07-11

Fixed:

  • Support -h/--help flag for the run command

1.3.0 - 2022-07-10

Changed:

  • Rename the default publishing plugin from pypi to the more generic index

Added:

  • Support the absence of pyproject.toml files, as is the case for apps and non-Python projects
  • Hide scripts that start with an underscore for the env show command by default
  • Ignoring the exit codes of commands by prefixing with hyphens now works with entire named scripts
  • Add a way to require confirmation for publishing
  • Add --force-continue flag to the env run command
  • Make tracebacks colorful and less verbose
  • When shell configuration has not been defined, attempt to use the current shell based on parent processes before resorting to the defaults
  • The shell name pwsh is now an alias for powershell
  • Remove atomicwrites dependency
  • Relax constraint on userpath dependency
  • Bump the minimum supported version of Hatchling to 1.4.1

Fixed:

  • Keep environments in sync with the dependencies of the selected features
  • Use utf-8 for all files generated for new projects
  • Escape special characters Git may return in the user name when writing generated files for new projects
  • Normalize the package name to lowercase in setuptools migration script
  • Fix parsing of source distributions during publishing

1.2.1 - 2022-05-30

Fixed:

  • Fix handling of top level data_files in setuptools migration script

1.2.0 - 2022-05-22

Changed:

  • The enter_shell environment plugin method now accepts an additional args parameter

Added:

  • Allow context string formatting for environment dependencies
  • Add environment context string formatting fields env_name, env_type, matrix, verbosity, and args
  • Support overriding the default arguments used to spawn shells on non-Windows systems
  • Bump the minimum supported version of Hatchling to 1.3.0

Fixed:

  • Improve setuptools migration script

1.1.2 - 2022-05-20

Fixed:

  • Bump the minimum supported version of Hatchling to 1.2.0
  • Update project metadata to reflect support for Python 3.11

1.1.1 - 2022-05-12

Fixed:

  • Fix setuptools migration script for non-Windows systems

1.1.0 - 2022-05-12

Changed:

  • In order to simplify the implementation of command execution for environment plugins, the run_shell_commands method has been replaced by the singular run_shell_command. A new command_context method has been added to more easily satisfy complex use cases.
  • The finalize_command environment plugin method has been removed in favor of the newly introduced context formatting functionality.

Added:

  • Add context formatting functionality i.e. the ability to insert values into configuration like environment variables and command line arguments
  • Any verbosity for command execution will now always display headers, even for single environments
  • Every executed command is now displayed when running multiple commands or when verbosity is enabled
  • Similar to make, ignore the exit code of executed commands that start with - (a hyphen)
  • Add ability for the --init flag of the new command to automatically migrate setuptools configuration
  • Update project metadata to reflect the adoption by PyPA and production stability

1.0.0 - 2022-04-28

This is the first stable release of Hatch v1, a complete rewrite. Enjoy!

\ No newline at end of file diff --git a/1.13/history/hatchling/index.html b/1.13/history/hatchling/index.html new file mode 100644 index 000000000..6a5281f85 --- /dev/null +++ b/1.13/history/hatchling/index.html @@ -0,0 +1,12 @@ + Hatchling history - Hatch

Hatchling history


All notable changes to Hatchling will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

Fixed:

  • Ignore manylinux/musllinux tags for the wheel target artifact name when enabling the infer_tag build data

1.24.2 - 2024-04-22

Fixed:

  • Add .venv to the list of directories that cannot be traversed
  • Output from the core Application utility now writes to stderr

1.24.1 - 2024-04-18

Fixed:

  • Maintain file permissions for shared-scripts option/shared_scripts build data of the wheel target

1.24.0 - 2024-04-16

Added:

  • Add shared_data and shared_scripts build data for the wheel target

1.23.0 - 2024-04-14

Added:

  • Add shared-scripts option for the wheel target

Fixed:

  • Support recursive optional dependencies
  • Set the packaging dependency version as >=23.2 to avoid its URL validation which can conflict with context formatting

1.22.5 - 2024-04-04

Fixed:

  • Fix reading metadata from source distributions when fields are dynamic but not part of core metadata like entry points

1.22.4 - 2024-03-23

Fixed:

  • Only read source distribution metadata for fields that are explicitly defined as dynamic

1.22.3 - 2024-03-19

Fixed:

  • Fix the custom build hook when using dynamic dependencies

1.22.2 - 2024-03-16

Fixed:

  • Fix regression when loading metadata from source distributions
  • Fix metadata hooks when building wheels from source distributions

1.22.1 - 2024-03-16

Fixed:

  • Update the default version of core metadata to 2.3

1.22.0 - 2024-03-16

Deprecated:

  • The app build target has been renamed to binary to reduce ambiguity with the name of an upcoming feature. The former name will still be usable for several minor releases.

Added:

  • Metadata for the wheel target now defaults to the PKG-INFO metadata within source distributions
  • Add dependencies method to the build hook interface so that hooks can themselves dynamically define dependencies
  • Update the default version of core metadata to 2.2
  • Update SPDX license information to version 3.23
  • Improve error message for when the default heuristics for wheel file inclusion fail

Fixed:

  • Properly support core metadata version 2.2
  • Remove editables as a direct dependency
  • Fix default wheel tag when the supported Python version declaration is strict
  • Load VCS ignore patterns first so that whitelisted patterns can be excluded by project configuration
  • Don't consider VCS ignore files that are outside of the VCS boundary
  • The sdist build target now gracefully ignores UNIX socket files
  • Begin ignoring certain files ubiquitously, like .DS_Store on macOS

1.21.1 - 2024-01-25

Fixed:

  • Fix loading of local plugins to account for newly released versions of a dependency

1.21.0 - 2023-12-18

Added:

  • Add parent context modifier for path fields

1.20.0 - 2023-12-13

Added:

  • Add bypass-selection option to the wheel build target to allow for empty (metadata-only) wheels

Fixed:

  • Fix regression in 1.19.1 that allowed exclude to count toward inclusion selection, thus bypassing the default inclusion selection heuristics
  • Fix writing optional dependency core metadata in situations where there are multiple environment markers

1.19.1 - 2023-12-12

Fixed:

  • Add better error message when the wheel build target cannot determine what to ship
  • Consider forced inclusion patterns and build-time artifacts as file selection since some build hooks generate the entire wheel contents without user configuration

1.19.0 - 2023-12-11

Changed:

  • An error will now be raised if a force-included path does not exist
  • An error will now be raised for the wheel build target if no file selection options are defined

Added:

  • Officially support Python 3.12
  • Allow using an empty string for the sources option to add a prefix to distribution paths

Fixed:

  • Properly handle non-zero version epoch for the standard version scheme
  • Fix the wheel build target for case insensitive file systems when the project metadata name does not match the directory name on disk
  • The app build target no longer has suppressed output
  • Prevent duplicate paths when projects require the sources option while build hooks overwrite included paths
  • Properly escape spaces for URI context formatting

1.18.0 - 2023-06-12

Changed:

  • Drop support for Python 3.7

Added:

  • Update the list of directories that are always excluded for builds

1.17.1 - 2023-06-03

Fixed:

  • Fix dev mode when the project has symlinks and file inclusion is defined with the packages or only-include options
  • Change the name of generated PTH files for dev mode so they come first lexicographically and therefore load first

1.17.0 - 2023-05-12

Added:

  • The app build target now embeds the project version in the name of binaries

1.16.1 - 2023-05-11

Fixed:

  • Fix determining the built executable path for the app build target option when using a local copy of PyApp when there is an explicit target triple set

1.16.0 - 2023-05-11

Added:

  • Add app build target option to build using a local copy of the PyApp repository

1.15.0 - 2023-05-09

Added:

  • Add app build target

1.14.1 - 2023-04-23

Fixed:

  • Fix internal archive root naming for the sdist target when strict-naming is disabled to match the file name in order to support the expectation of some frontends

1.14.0 - 2023-04-02

Added:

  • Add trove-classifiers as a dependency

Fixed:

  • Properly normalize metadata descriptions that contain line breaks

1.13.0 - 2023-02-09

Added:

  • Update the set of known trove classifiers to version 2023.2.8

1.12.2 - 2023-01-05

Fixed:

  • Add macos-max-compat option to the wheel target that is enabled by default to support the latest version 22.0 of the packaging library

1.12.1 - 2022-12-31

Fixed:

  • Fix minor regression in the PEP 517/660 function signatures that was discovered by Fedora

1.12.0 - 2022-12-30

Added:

  • Improve readability of exceptions
  • Add extra_metadata build data to the wheel target
  • Retroactively support License-Expression core metadata starting at version 2.1
  • Add more type hints
  • Update the set of known trove classifiers to version 2022.12.22
  • Update SPDX license information to version 3.19
  • Store Hatchling's metadata in pyproject.toml

Fixed:

  • Acknowledge the ARCHFLAGS environment variable on macOS for the wheel target when build hooks set the infer_tag build data to true
  • Fix dependency checking when encountering broken distributions
  • Fix the support-legacy option for the sdist target when using a src-layout project structure
  • Remove unnecessary encoding declaration in the default template for the version build hook

1.11.1 - 2022-10-19

Fixed:

  • Fix default file selection behavior of the wheel target when there is a single top-level module

1.11.0 - 2022-10-08

Added:

  • Add env version source to retrieve the version from an environment variable
  • Add validate-bump option to the standard version scheme

Fixed:

  • Use proper CSV formatting for the RECORD metadata file of the wheel target to avoid warnings during installation by pip if, for example, file names contain commas
  • Fix installations with pip for build hooks that modify runtime dependencies
  • Decreasing verbosity now has no affect on output that should always be displayed

1.10.0 - 2022-09-18

Added:

  • Add the following to the list of directories that cannot be traversed: __pypackages__, .hg, .hatch, .tox, .nox
  • Add deprecated option to allow ambiguous features

Fixed:

  • Improve tracking of dynamic metadata
  • Fix core metadata for entries in project.optional-dependencies that use direct references

1.9.0 - 2022-09-09

Changed:

  • File pattern matching now more closely resembles Git's behavior

Added:

  • Implement a minimal version of prepare_metadata_for_build_wheel and prepare_metadata_for_build_editable for non-frontend tools that only need to inspect a project's metadata
  • Add metadata command to view PEP 621 project metadata
  • Improve error messages for SPDX license errors
  • Retroactively support License-File for core metadata starting at version 2.1
  • Bump the minimum supported version of pathspec to 0.10.1

Fixed:

  • Allow the valid non-SPDX license values LicenseRef-Public-Domain and LicenseRef-Proprietary
  • Show the help text of the CLI when no subcommand is selected

1.8.1 - 2022-08-25

Fixed:

  • Fix default file inclusion for wheel build targets when both the project name and package directory name are not normalized

1.8.0 - 2022-08-16

Added:

  • Add get_known_classifiers method to metadata hooks

Fixed:

  • Fix check for updating static versions with the version command when metadata hooks are in use

1.7.1 - 2022-08-13

Fixed:

  • Fix the value of the relative_path attribute of included files, that some build plugins may use, when selecting explicit paths

1.7.0 - 2022-08-12

Added:

  • Add require-runtime-features option for builders and build hooks
  • Check for unknown trove classifiers
  • Update SPDX license information to version 3.18

Fixed:

  • Add better error message for wheel target dev mode installations that define path rewrites with the sources option
  • Note the allow-direct-references option in the relevant error messages

1.6.0 - 2022-07-23

Changed:

  • When no build targets are specified on the command line, now default to sdist and wheel targets rather than what happens to be defined in config
  • The code version source now only supports files with known extensions
  • Global build hooks now run before target-specific build hooks to better match expected behavior

Added:

  • The code version source now supports loading extension modules
  • Add search-paths option for the code version source

Fixed:

  • Fix removing sources using an empty string value in the mapping
  • The strict-naming option now also applies to the metadata directory of wheel targets

1.5.0 - 2022-07-11

Added:

  • Support the final draft of PEP 639
  • Add strict-naming option for sdist and wheel targets

Fixed:

  • Project names are now stored in sdist and wheel target core metadata exactly as defined in pyproject.toml without normalization to allow control of how PyPI displays them

1.4.1 - 2022-07-04

Fixed:

  • Fix forced inclusion of important files like licenses for sdist targets when using the explicit selection options
  • Don't sort project URL metadata so that the rendered order on PyPI can be controlled

1.4.0 - 2022-07-03

Changed:

  • The packages option uses the new only-include option to provide targeted inclusion, since that is desired most of the time. You can retain the old behavior by using the include and sources options together.

Added:

  • Support PEP 561 type hinting
  • Add version build hook
  • Add only-include option
  • The editable version of wheel targets now respects the force-include option by default
  • The force-include option now supports path rewriting with the sources option
  • The wheel target shared-data and extra-metadata options now respect file selection options
  • The wheel target now auto-detects single module layouts
  • Improve performance by never entering directories that are guaranteed to be undesirable like __pycache__ rather than excluding individual files within
  • Update SPDX license information to version 3.17

Fixed:

  • Don't write empty entry points file for wheel targets if there are no entry points defined
  • Allow metadata hooks to set the version in all cases
  • Prevent duplicate file entries from inclusion when using the force-include option

1.3.1 - 2022-05-30

Fixed:

  • Better populate global variables for the code version source

1.3.0 - 2022-05-22

Removed:

  • Remove unused global args context string formatting field

Added:

  • Improve error messages for the env context string formatting field

Fixed:

  • Fix uri context string formatting modifier on Windows

1.2.0 - 2022-05-20

Added:

  • Allow context formatting for project.dependencies and project.optional-dependencies

1.1.0 - 2022-05-19

Added:

  • Add uri and real context string formatting modifiers for file system paths

1.0.0 - 2022-05-17

Changed:

  • Drop support for Python 2

Added:

  • Improve error messaging for invalid versions
  • Update project metadata to reflect support for Python 3.11

0.25.1 - 2022-06-14

Fixed:

  • Fix support for Windows on Python 2 by removing its support for symlinks

0.25.0 - 2022-05-15

Added:

  • Add skip-excluded-dirs build option
  • Allow build data to add additional project dependencies for wheel and sdist build targets
  • Add force_include_editable build data for the wheel build target
  • Add build_hooks build data
  • Add support for Mercurial's .hgignore files when using glob syntax
  • Update project metadata to reflect the adoption by PyPA

Fixed:

  • Properly use underscores for the name of force_include build data
  • No longer greedily skip excluded directories by default

0.24.0 - 2022-04-28

This is the initial public release of the Hatchling build system. Support for Python 2 will be dropped in version 1.

\ No newline at end of file diff --git a/1.13/history/index.html b/1.13/history/index.html new file mode 100644 index 000000000..de75495f4 --- /dev/null +++ b/1.13/history/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/how-to/config/dynamic-metadata/index.html b/1.13/how-to/config/dynamic-metadata/index.html new file mode 100644 index 000000000..0b9e94801 --- /dev/null +++ b/1.13/how-to/config/dynamic-metadata/index.html @@ -0,0 +1,32 @@ + How to configure custom dynamic metadata - Hatch

How to configure custom dynamic metadata


If you have project metadata that is not appropriate for static entry into pyproject.toml you will need to provide a custom metadata hook to apply such data during builds.

Alternatives

Dynamic metadata is a way to have a single source of truth that will be available at build time and at run time. Another way to achieve that is to enter the build data statically and then look up the same information dynamically in the program or package, using importlib.metadata.

If the version field is the only metadata of concern, Hatchling provides a few built-in ways such as the regex version source and also third-party plugins. The approach here will also work, but is more complex.

Update project metadata

Change the [project] section of pyproject.toml:

  1. Define the dynamic field as an array of all the fields you will set dynamically e.g. dynamic = ["version", "license", "authors", "maintainers"]
  2. If any of those fields have static definitions in pyproject.toml, delete those definitions. It is verboten to define a field statically and dynamically.

Add a section to trigger loading of dynamic metadata plugins: [tool.hatch.metadata.hooks.custom]. Use exactly that name, regardless of the name of the class you will use or its PLUGIN_NAME. There doesn't need to be anything in the section.

If your plugin requires additional third-party packages to do its work, add them to the requires array in the [build-system] section of pyproject.toml.

Implement hook

The dynamic lookup must happen in a custom plugin that you write. The default expectation is that it is in a hatch_build.py file at the root of the project. Subclass MetadataHookInterface and implement update(); for example, here's plugin that reads metadata from a JSON file:

import json
+import os
+
+from hatchling.metadata.plugin.interface import MetadataHookInterface
+
+
+class JSONMetaDataHook(MetadataHookInterface):
+    def update(self, metadata):
+        src_file = os.path.join(self.root, "gnumeric", ".constants.json")
+        with open(src_file) as src:
+            constants = json.load(src)
+            metadata["version"] = constants["__version__"]
+            metadata["license"] = constants["__license__"]
+            metadata["authors"] = [
+                {"name": constants["__author__"], "email": constants["__author_email__"]},
+            ]
+
  1. You must import the MetadataHookInterface to subclass it.
  2. Do your operations inside the update method.
  3. metadata refers to project metadata.
  4. When writing to metadata, use list for TOML arrays. Note that if a list is expected, it is required even if there is a single element.
  5. Use dict for TOML tables e.g. authors.

If you want to store the hook in a different location, set the path option:

[tool.hatch.metadata.hooks.custom]
+path = "some/where.py"
+
[metadata.hooks.custom]
+path = "some/where.py"
+
\ No newline at end of file diff --git a/1.13/how-to/environment/dependency-resolution/index.html b/1.13/how-to/environment/dependency-resolution/index.html new file mode 100644 index 000000000..d59c23e0e --- /dev/null +++ b/1.13/how-to/environment/dependency-resolution/index.html @@ -0,0 +1,24 @@ + How to configure dependency resolution - Hatch

How to configure dependency resolution


Most Hatch environment types, like the default virtual, simply use pip to install dependencies. Therefore, you can use the standard environment variables that influence pip's behavior.

Here's an example of setting up the default environment to look at 2 private indices (using context formatting for authentication) before finally falling back to PyPI:

[tool.hatch.envs.default.env-vars]
+PIP_INDEX_URL = "https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group1_path>/-/packages/pypi/simple/"
+PIP_EXTRA_INDEX_URL = "https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group2_path>/-/packages/pypi/simple/ https://pypi.org/simple/"
+
[envs.default.env-vars]
+PIP_INDEX_URL = "https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group1_path>/-/packages/pypi/simple/"
+PIP_EXTRA_INDEX_URL = "https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group2_path>/-/packages/pypi/simple/ https://pypi.org/simple/"
+

UV

If you're using UV, a different set of environment variables are available to configure its behavior. The previous example would look like this instead:

[tool.hatch.envs.default.env-vars]
+UV_EXTRA_INDEX_URL = "https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group1_path>/-/packages/pypi/simple/"
+UV_INDEX_URL = "https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group2_path>/-/packages/pypi/simple/ https://pypi.org/simple/"
+
[envs.default.env-vars]
+UV_EXTRA_INDEX_URL = "https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group1_path>/-/packages/pypi/simple/"
+UV_INDEX_URL = "https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group2_path>/-/packages/pypi/simple/ https://pypi.org/simple/"
+

Tip

If you need precise control over the prioritization of package indices, then using UV is recommended because pip has no index order guarantee.

\ No newline at end of file diff --git a/1.13/how-to/environment/package-indices/index.html b/1.13/how-to/environment/package-indices/index.html new file mode 100644 index 000000000..b467a5101 --- /dev/null +++ b/1.13/how-to/environment/package-indices/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/how-to/environment/select-installer/index.html b/1.13/how-to/environment/select-installer/index.html new file mode 100644 index 000000000..81e6443ca --- /dev/null +++ b/1.13/how-to/environment/select-installer/index.html @@ -0,0 +1,44 @@ + How to select the installer - Hatch

How to select the installer


Enabling UV

The virtual environment type by default uses virtualenv for virtual environment creation and pip to install dependencies. You can speed up environment creation and dependency resolution by using UV instead of both of those tools.

caveat

UV is under active development and may not work for all dependencies.

To do so, set the installer option to uv. For example, if you wanted to enable this functionality for the default environment, you could set the following:

[tool.hatch.envs.default]
+installer = "uv"
+
[envs.default]
+installer = "uv"
+

Tip

All environments that enable UV will have the path to UV available as the HATCH_UV environment variable.

Configuring the version

The UV that is shared by all environments uses a specific version range that is known to work with Hatch. If you want to use a different version, you can override the dependencies for the internal hatch-uv environment:

[tool.hatch.envs.hatch-uv]
+dependencies = [
+  "uv>9000",
+]
+
[envs.hatch-uv]
+dependencies = [
+  "uv>9000",
+]
+

Externally managed

If you want to manage UV yourself, you can expose it to Hatch by setting the HATCH_ENV_TYPE_VIRTUAL_UV_PATH environment variable which should be the absolute path to a UV binary for Hatch to use instead. This implicitly enables UV.

Installer script alias

If you have scripts or commands that call pip, it may be useful to alias the uv pip command to pip so that you can use the same commands for both methods of configuration and retain your muscle memory. The following is an example of a matrix that conditionally enables UV and sets the alias:

[[tool.hatch.envs.example.matrix]]
+tool = ["uv", "pip"]
+
+[tool.hatch.envs.example.overrides]
+matrix.tool.installer = { value = "{matrix:tool}" }
+matrix.tool.scripts = [
+  { key = "pip", value = "{env:HATCH_UV} pip {args}", if = ["uv"] },
+]
+
[[envs.example.matrix]]
+tool = ["uv", "pip"]
+
+[envs.example.overrides]
+matrix.tool.installer = { value = "{matrix:tool}" }
+matrix.tool.scripts = [
+  { key = "pip", value = "{env:HATCH_UV} pip {args}", if = ["uv"] },
+]
+

Another common use case is to expose UV to all test environments. In this case, you often wouldn't want to modify the scripts mapping directly but rather add an extra script:

[tool.hatch.envs.hatch-test.extra-scripts]
+pip = "{env:HATCH_UV} pip {args}"
+
[envs.hatch-test.extra-scripts]
+pip = "{env:HATCH_UV} pip {args}"
+
\ No newline at end of file diff --git a/1.13/how-to/integrate/vscode/index.html b/1.13/how-to/integrate/vscode/index.html new file mode 100644 index 000000000..b70a55def --- /dev/null +++ b/1.13/how-to/integrate/vscode/index.html @@ -0,0 +1,16 @@ + How to use Hatch environments from Visual Studio Code - Hatch

How to use Hatch environments from Visual Studio Code


Visual Studio Code announced support for Hatch environment discovery in vscode-python's 2024.4 release.

For it to work, you should install Hatch globally. If you used the GUI installers on Windows or macOS, or your system package manager on e.g. Arch Linux or Fedora, this should be taken care of.

Setting up PATH

If you installed Hatch with pipx rather than system-wide, you might need to add $HOME/.local/bin to your PATH environment variable for your graphical session, not just your terminal. Check like this:

$ pgrep bin/code  # or some other graphical application
+1234
+$ cat /proc/1234/environ | tr '\0' '\n' | grep -E '^PATH='
+PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+

If the directory is not in there, you need to add it in your session startup script, in a way that depends on your desktop environment:

Project setup

  1. Make Hatch install the project and its dependencies to an environment using the env create command.

  2. Select an interpreter using the Python: Select Interpreter command:

    Select interpreter

  3. You should now be able to use the environment. For example, if you have the python.terminal.activateEnvironment setting set to true and you open a new terminal, the environment should be activated. Alternatively, you could press the "play" button to run a file in the environment:

    Run file

\ No newline at end of file diff --git a/1.13/how-to/integrate/vscode/run-file.png b/1.13/how-to/integrate/vscode/run-file.png new file mode 100644 index 000000000..84534d595 Binary files /dev/null and b/1.13/how-to/integrate/vscode/run-file.png differ diff --git a/1.13/how-to/integrate/vscode/select-interpreter.png b/1.13/how-to/integrate/vscode/select-interpreter.png new file mode 100644 index 000000000..943e51ecd Binary files /dev/null and b/1.13/how-to/integrate/vscode/select-interpreter.png differ diff --git a/1.13/how-to/meta/report-issues/index.html b/1.13/how-to/meta/report-issues/index.html new file mode 100644 index 000000000..fd8d0b63e --- /dev/null +++ b/1.13/how-to/meta/report-issues/index.html @@ -0,0 +1,15 @@ + How to report issues - Hatch

How to report issues


All reports regarding unexpected behavior should be generated with the self report command:

$ hatch self report
+

By default, this will open a new tab in your default browser with pre-populated information about your environment.

If Hatch is not installed alongside a web browser, you may also pass the --no-open/-n command which will output the URL with correct parameters for copying elsewhere:

$ hatch self report -n
+https://github.com/pypa/hatch/issues/new?body=%23%23+Current+behavior%0A%3C%21--+A+clear+and+concise+description+of+the+behavior.+--%3E%0A%0A%23%23+Expected+behavior%0A%3C%21--+A+clear+and+concise+description+of+what+you+expected+to+happen.+--%3E%0A%0A%23%23+Additional+context%0A%3C%21--+Add+any+other+context+about+the+problem+here.+If+applicable%2C+add+screenshots+to+help+explain.+--%3E%0A%0A%23%23+Debug%0A%0A%23%23%23+Installation%0A%0A-+Source%3A+pip%0A-+Version%3A+1.9.2.dev5%0A-+Platform%3A+Windows%0A-+Python+version%3A%0A++++%60%60%60%0A++++3.11.1+%28tags%2Fv3.11.1%3Aa7a450f%2C+Dec++6+2022%2C+19%3A58%3A39%29+%5BMSC+v.1934+64+bit+%28AMD64%29%5D%0A++++%60%60%60%0A%0A%23%23%23+Configuration%0A%0A%60%60%60toml%0Amode+%3D+%22local%22%0Ashell+%3D+%22nu%22%0A%60%60%60%0A
+
\ No newline at end of file diff --git a/1.13/how-to/plugins/testing-builds/index.html b/1.13/how-to/plugins/testing-builds/index.html new file mode 100644 index 000000000..4d8c482be --- /dev/null +++ b/1.13/how-to/plugins/testing-builds/index.html @@ -0,0 +1,73 @@ + Testing build plugins - Hatch

Testing build plugins


For testing Hatchling plugins, you'll usually want to generate a project to execute builds as a real user would. For example, as a minimal pytest fixture:

from pathlib import Path
+
+import pytest
+
+
+@pytest.fixture
+def new_project(tmp_path):
+    project_dir = tmp_path / 'my-app'
+    project_dir.mkdir()
+
+    project_file = project_dir / 'pyproject.toml'
+    project_file.write_text(
+        f"""\
+[build-system]
+requires = ["hatchling", "hatch-plugin-name @ {Path.cwd().as_uri()}"]
+build-backend = "hatchling.build"
+
+[project]
+name = "my-app"
+version = "0.1.0"
+""",
+        encoding='utf-8',
+    )
+    ...
+

The issue with this is that after the first test session, the project will be forever cached by pip based on the file path. Therefore, subsequent tests runs will never use updated code.

To invalidate the cache, copy your code to a new path for every test session:

import shutil
+from pathlib import Path
+from tempfile import TemporaryDirectory
+
+import pytest
+
+
+@pytest.fixture(scope='session')
+def plugin_dir():
+    with TemporaryDirectory() as d:
+        directory = Path(d, 'plugin')
+        shutil.copytree(
+            Path.cwd(), directory, ignore=shutil.ignore_patterns('.git')
+        )
+
+        yield directory.resolve()
+
+
+@pytest.fixture
+def new_project(tmp_path, plugin_dir):
+    project_dir = tmp_path / 'my-app'
+    project_dir.mkdir()
+
+    project_file = project_dir / 'pyproject.toml'
+    project_file.write_text(
+        f"""\
+[build-system]
+requires = ["hatchling", "hatch-plugin-name @ {plugin_dir.as_uri()}"]
+build-backend = "hatchling.build"
+
+[project]
+name = "my-app"
+version = "0.1.0"
+""",
+        encoding='utf-8',
+    )
+    ...
+

Note

This example chooses to ignore copying .git for performance reasons. You may want to ignore more patterns, or copy only specific paths like this plugin does.

\ No newline at end of file diff --git a/1.13/how-to/publish/auth/index.html b/1.13/how-to/publish/auth/index.html new file mode 100644 index 000000000..8c1beb6e2 --- /dev/null +++ b/1.13/how-to/publish/auth/index.html @@ -0,0 +1,12 @@ + How to authenticate for index publishing - Hatch

How to authenticate for index publishing


The username is derived from the following sources, in order of precedence:

  1. The --user / -u cli option.
  2. The HATCH_INDEX_USER environment variable.
  3. The repos tables.
  4. The ~/.pypirc file.
  5. The input to an interactive prompt.

As a fallback the value __token__ is applied.

The password is looked up in these:

  1. The ~/.pypirc file if the username was provided by it.
  2. The --auth / -a cli option.
  3. The HATCH_INDEX_AUTH environment variable.
  4. The repos tables.
  5. A variety of OS-level credentials services backed by keyring.
  6. The input to an interactive prompt.

If interactively provided credentials were used, the username will be stored in Hatch's cache and the password stored in the available keyring backed credentials stores.

For automated releasing to PyPI, it is recommended to use "Trusted Publishing" with OIDC (e.g. PyPA's pypi-publish GitHub Action) or per-project API tokens.

\ No newline at end of file diff --git a/1.13/how-to/publish/repo/index.html b/1.13/how-to/publish/repo/index.html new file mode 100644 index 000000000..c2c6e1f36 --- /dev/null +++ b/1.13/how-to/publish/repo/index.html @@ -0,0 +1,15 @@ + How to configure repositories for index publishing - Hatch

How to configure repositories for index publishing


You can select the repository with which to upload using the -r/--repo option or by setting the HATCH_INDEX_REPO environment variable.

Rather than specifying the full URL of a repository, you can use a named repository from a publish.index.repos table defined in Hatch's config file:

[publish.index.repos.private]
+url = "..."
+...
+

The following repository names are reserved by Hatch and cannot be overridden:

Name Repository
main https://upload.pypi.org/legacy/
test https://test.pypi.org/legacy/

The main repository is used by default.

\ No newline at end of file diff --git a/1.13/how-to/python/custom/index.html b/1.13/how-to/python/custom/index.html new file mode 100644 index 000000000..c19d05e1f --- /dev/null +++ b/1.13/how-to/python/custom/index.html @@ -0,0 +1,12 @@ + How to use custom Python distributions - Hatch

How to use custom Python distributions


The built-in Python management capabilities offer full support for using custom distributions.

Configuration

Configuring custom Python distributions is done entirely through three environment variables that must all be defined, for each desired distribution. In the following sections, the placeholder <NAME> is the uppercased version of the distribution name with periods replaced by underscores e.g. pypy3.10 would become PYPY3_10.

Source

The HATCH_PYTHON_CUSTOM_SOURCE_<NAME> variable is the URL to the distribution's archive. The value must end with the archive's real file extension, which is used to determine the extraction method.

The following extensions are supported:

Extensions Description
  • .tar.bz2
  • .bz2
A tar file with bzip2 compression
  • .tar.gz
  • .tgz
A tar file with gzip compression
  • .tar.zst
  • .tar.zstd
A tar file with Zstandard compression
  • .zip
A ZIP file with DEFLATE compression

Python path

The HATCH_PYTHON_CUSTOM_PATH_<NAME> variable is the path to the Python interpreter within the archive. This path is relative to the root of the archive and must be a Unix-style path, even on Windows.

Version

The HATCH_PYTHON_CUSTOM_VERSION_<NAME> variable is the version of the distribution. This value is used to determine whether updates are required and is displayed in the output of the python show command.

\ No newline at end of file diff --git a/1.13/how-to/run/python-scripts/index.html b/1.13/how-to/run/python-scripts/index.html new file mode 100644 index 000000000..54a19546a --- /dev/null +++ b/1.13/how-to/run/python-scripts/index.html @@ -0,0 +1,47 @@ + How to run Python scripts - Hatch

How to run Python scripts


The run command supports executing Python scripts with inline metadata, such that a dedicated environment is automatically created with the required dependencies and with the correct version of Python.

A script metadata block is a comment block that starts with # /// script and ends with # ///. Every line between those two lines must be a comment line that starts with # and contains a TOML document when the comment characters are removed.

The top-level fields are:

  • dependencies: A list of strings that specifies the runtime dependencies of the script. Each entry must be a valid dependency specifier.
  • requires-python: A string that specifies the Python version(s) with which the script is compatible. The value of this field must be a valid version specifier.

The following is an example of Python script with a valid metadata block:

# /// script
+# requires-python = ">=3.11"
+# dependencies = [
+#   "httpx",
+#   "rich",
+# ]
+# ///
+
+import httpx
+from rich.pretty import pprint
+
+resp = httpx.get("https://peps.python.org/api/peps.json")
+data = resp.json()
+pprint([(k, v["title"]) for k, v in data.items()][:10])
+

Run it directly:

$ hatch run /path/to/script.py
+Creating environment: SyB4bPbL
+Checking dependencies
+Syncing dependencies
+[
+│   ('1', 'PEP Purpose and Guidelines'),
+│   ('2', 'Procedure for Adding New Modules'),
+│   ('3', 'Guidelines for Handling Bug Reports'),
+│   ('4', 'Deprecation of Standard Modules'),
+│   ('5', 'Guidelines for Language Evolution'),
+│   ('6', 'Bug Fix Releases'),
+│   ('7', 'Style Guide for C Code'),
+│   ('8', 'Style Guide for Python Code'),
+│   ('9', 'Sample Plaintext PEP Template'),
+│   ('10', 'Voting Guidelines')
+]
+

notes

  • The informational text in this example is only temporarily shown in your terminal on the first run.
  • Although the environment name is based on the script's absolute path, the command line argument does not have to be.

Environment configuration

You may use the [tool.hatch] table directly to control the script's environment. For example, if you wanted to disable UV (which is enabled by default for scripts), you could add the following:

# /// script
+# ...
+# [tool.hatch]
+# installer = "pip"
+# ///
+
\ No newline at end of file diff --git a/1.13/how-to/static-analysis/behavior/index.html b/1.13/how-to/static-analysis/behavior/index.html new file mode 100644 index 000000000..da5a06d2f --- /dev/null +++ b/1.13/how-to/static-analysis/behavior/index.html @@ -0,0 +1,40 @@ + Customize static analysis behavior - Hatch

Customize static analysis behavior


You can fully alter the static analysis performed by the fmt command by modifying the reserved environment named hatch-static-analysis. For example, you could define the following if you wanted to replace the default behavior with a mix of Black, isort and basic flake8:

[tool.hatch.envs.hatch-static-analysis]
+dependencies = ["black", "flake8", "isort"]
+
+[tool.hatch.envs.hatch-static-analysis.scripts]
+format-check = [
+  "black --check --diff {args:.}",
+  "isort --check-only --diff {args:.}",
+]
+format-fix = [
+  "isort {args:.}",
+  "black {args:.}",
+]
+lint-check = "flake8 {args:.}"
+lint-fix = "lint-check"
+
[envs.hatch-static-analysis]
+dependencies = ["black", "flake8", "isort"]
+
+[envs.hatch-static-analysis.scripts]
+format-check = [
+  "black --check --diff {args:.}",
+  "isort --check-only --diff {args:.}",
+]
+format-fix = [
+  "isort {args:.}",
+  "black {args:.}",
+]
+lint-check = "flake8 {args:.}"
+lint-fix = "lint-check"
+

The format-* scripts correspond to the --formatter/-f flag while the lint-* scripts correspond to the --linter/-l flag. The *-fix scripts run by default while the *-check scripts correspond to the --check flag. Based on this example, the following shows how the various scripts influence behavior:

Command Expanded scripts
hatch fmt
  • flake8 .
  • isort .
  • black .
hatch fmt src tests
  • flake8 src tests
  • isort src tests
  • black src tests
hatch fmt -f
  • isort .
  • black .
hatch fmt -l
  • flake8 .
hatch fmt --check
  • flake8 .
  • black --check --diff .
  • isort --check-only --diff .
hatch fmt --check -f
  • black --check --diff .
  • isort --check-only --diff .
hatch fmt --check -l
  • flake8 .
\ No newline at end of file diff --git a/1.13/index.html b/1.13/index.html new file mode 100644 index 000000000..32e835aa4 --- /dev/null +++ b/1.13/index.html @@ -0,0 +1,12 @@ + Hatch - Hatch

Hatch

Hatch logo

CI/CD CI - Test CD - Build Hatch CD - Build Hatchling
Docs Docs - Release Docs - Dev
Package PyPI - Version PyPI - Python Version PyPI - Installs Release - Downloads
Meta Hatch project linting - Ruff types - Mypy License - MIT GitHub Sponsors

Hatch is a modern, extensible Python project manager. See the Why Hatch? page for more information.

  • Build system


    Reproducible builds by default with a rich ecosystem of plugins

    Configure builds

  • Environments


    Robust environment management with support for custom scripts and UV

    Getting started

  • Python management


    Choose between easy manual installations or automatic as part of environments

    Try it

  • Testing


    Test execution with known best practices

    Run

  • Static analysis


    Static analysis backed by Ruff with up-to-date, sane defaults

    Learn

  • Script runner


    Execute Python scripts with specific dependencies and Python versions

    Execute

  • Publishing


    Easily upload to PyPI or other indices

    See how

  • Versioning


    Streamlined workflow for bumping versions

    Managing versions

  • Project generation


    Create new projects from templates with known best practices

    Project setup

  • Responsive CLI


    Hatch is up to 3x faster than equivalent tools

    CLI reference

License

Hatch is distributed under the terms of the MIT license.

Documentation for specific MAJOR.MINOR versions can be chosen by using the dropdown on the top of every page. The dev version reflects changes that have not yet been released.

Also, desktop readers can use special keyboard shortcuts:

Keys Action
  • , (comma)
  • p
Navigate to the "previous" page
  • . (period)
  • n
Navigate to the "next" page
  • /
  • s
Display the search modal
\ No newline at end of file diff --git a/1.13/install/index.html b/1.13/install/index.html new file mode 100644 index 000000000..6060d4a03 --- /dev/null +++ b/1.13/install/index.html @@ -0,0 +1,34 @@ + Installation - Hatch

Installation


GitHub Actions

- name: Install Hatch
+  uses: pypa/hatch@install
+

Refer to the official action for more information.

Installers

  1. In your browser, download the .pkg file: hatch-universal.pkg
  2. Run your downloaded file and follow the on-screen instructions.
  3. Restart your terminal.
  4. To verify that the shell can find and run the hatch command in your PATH, use the following command.

    $ hatch --version
    +1.13.0
    +
  1. Download the file using the curl command. The -o option specifies the file name that the downloaded package is written to. In this example, the file is written to hatch-universal.pkg in the current directory.

    curl -Lo hatch-universal.pkg https://github.com/pypa/hatch/releases/latest/download/hatch-universal.pkg
    +
  2. Run the standard macOS installer program, specifying the downloaded .pkg file as the source. Use the -pkg parameter to specify the name of the package to install, and the -target / parameter for the drive in which to install the package. The files are installed to /usr/local/hatch, and an entry is created at /etc/paths.d/hatch that instructs shells to add the /usr/local/hatch directory to. You must include sudo on the command to grant write permissions to those folders.

    sudo installer -pkg ./hatch-universal.pkg -target /
    +
  3. Restart your terminal.

  4. To verify that the shell can find and run the hatch command in your PATH, use the following command.

    $ hatch --version
    +1.13.0
    +
  1. In your browser, download one the .msi files:
  2. Run your downloaded file and follow the on-screen instructions.
  3. Restart your terminal.
  4. To verify that the shell can find and run the hatch command in your PATH, use the following command.

    $ hatch --version
    +1.13.0
    +
  1. Download and run the installer using the standard Windows msiexec program, specifying one of the .msi files as the source. Use the /passive and /i parameters to request an unattended, normal installation.

    msiexec /passive /i https://github.com/pypa/hatch/releases/latest/download/hatch-x64.msi
    +
    msiexec /passive /i https://github.com/pypa/hatch/releases/latest/download/hatch-x86.msi
    +
  2. Restart your terminal.

  3. To verify that the shell can find and run the hatch command in your PATH, use the following command.

    $ hatch --version
    +1.13.0
    +

Standalone binaries

After downloading the archive corresponding to your platform and architecture, extract the binary to a directory that is on your PATH and rename to hatch.

pip

Hatch is available on PyPI and can be installed with pip.

pip install hatch
+

Warning

This method modifies the Python environment in which you choose to install. Consider instead using pipx to avoid dependency conflicts.

pipx

pipx allows for the global installation of Python applications in isolated environments.

pipx install hatch
+

Homebrew

See the formula for more details.

brew install hatch
+

Conda

See the feedstock for more details.

conda install -c conda-forge hatch
+

or with mamba:

mamba install hatch
+

Warning

This method modifies the Conda environment in which you choose to install. Consider instead using pipx or condax to avoid dependency conflicts.

MacPorts

See the port for more details.

sudo port install hatch
+

Fedora

The minimum supported version is 37, currently in development as Rawhide.

sudo dnf install hatch
+

Void Linux

xbps-install hatch
+

Build system availability

Hatchling is Hatch's build backend which you will never need to install manually. See its changelog for version information.

Packaging status

\ No newline at end of file diff --git a/1.13/intro/index.html b/1.13/intro/index.html new file mode 100644 index 000000000..d06ec9d52 --- /dev/null +++ b/1.13/intro/index.html @@ -0,0 +1,46 @@ + Introduction - Hatch

Introduction


Setup

Projects can be set up for use by Hatch using the new command.

New project

Let's say you want to create a project named Hatch Demo. You would run:

hatch new "Hatch Demo"
+

This would create the following structure in your current working directory:

hatch-demo
+├── src
+│   └── hatch_demo
+│       ├── __about__.py
+│       └── __init__.py
+├── tests
+│   └── __init__.py
+├── LICENSE.txt
+├── README.md
+└── pyproject.toml
+

Tip

There are many ways to customize project generation.

Existing project

To initialize an existing project, enter the directory containing the project and run the following:

hatch new --init
+

If your project has a setup.py file the command will automatically migrate setuptools configuration for you. Otherwise, this will interactively guide you through the setup process.

Project metadata

Next you'll want to define more of your project's metadata located in the pyproject.toml file. You can specify things like its license, the supported versions of Python, and URLs referring to various parts of your project, like documentation.

Dependencies

The last step of the setup process is to define any dependencies that you'd like your project to begin with.

Configuration

All project-specific configuration recognized by Hatch can be defined in either the pyproject.toml file, or a file named hatch.toml where options are not contained within the tool.hatch table:

[tool.hatch]
+option = "..."
+
+[tool.hatch.table1]
+option = "..."
+
+[tool.hatch.table2]
+option = "..."
+
option = "..."
+
+[table1]
+option = "..."
+
+[table2]
+option = "..."
+

Top level keys in the latter file take precedence when defined in both.

Tip

If you want to make your file more compact, you can use dotted keys, turning the above example into:

[tool.hatch]
+option = "..."
+table1.option = "..."
+table2.option = "..."
+
option = "..."
+table1.option = "..."
+table2.option = "..."
+
\ No newline at end of file diff --git a/1.13/meta/authors/index.html b/1.13/meta/authors/index.html new file mode 100644 index 000000000..bcc7dd145 --- /dev/null +++ b/1.13/meta/authors/index.html @@ -0,0 +1,12 @@ + Authors - Hatch

Authors


Maintainers

  • Ofek Lev

Contributors

  • Amjith Ramanujam
  • Arnaud Crowther
  • Chaojie
  • Chris Warrick
  • Lumír 'Frenzy' Balhar
  • Ofek Lev
  • Olga Matoula
  • Philip Blair
  • Robert Rosca
\ No newline at end of file diff --git a/1.13/meta/faq/index.html b/1.13/meta/faq/index.html new file mode 100644 index 000000000..a5da3e1b4 --- /dev/null +++ b/1.13/meta/faq/index.html @@ -0,0 +1,179 @@ + FAQ - Hatch

FAQ


Interoperability

Q: What is the risk of lock-in?

A: Not much! Other than the plugin system, everything uses Python's established standards by default. Project metadata is based entirely on the standard, the build system is compatible with PEP 517/PEP 660, versioning uses the scheme specified by PEP 440, dependencies are defined with PEP 508 strings, and environments use virtualenv.

Q: Must one use all features?

A: No, all features are optional! You can use just the build system, publish wheels and source distributions that were built by other tools, only use the environment management, etc.

Libraries vs applications

Q: Are workflows for both libraries and applications supported?

A: Yes, mostly! Applications can utilize environment management just like libraries, and plugins can be used to build projects in arbitrary formats or publish artifacts to arbitrary destinations.

The only caveat is that currently there is no support for re-creating an environment given a set of dependencies in a reproducible manner. Although a standard lock file format may be far off since PEP 665 was rejected, resolving capabilities are coming to pip. When that is stabilized, Hatch will add locking functionality and dedicated documentation for managing applications.

Tool migration

Q: How to migrate to Hatch?

Build system

import os
+from io import open
+
+from setuptools import find_packages, setup
+
+about = {}
+with open(os.path.join('src', 'foo', '__about__.py'), 'r', 'utf-8') as f:
+    exec(f.read(), about)
+
+with open('README.md', 'r', 'utf-8') as f:
+    readme = f.read()
+
+setup(
+    # Metadata
+    name='foo',
+    version=about['__version__'],
+    description='...',
+    long_description=readme,
+    long_description_content_type='text/markdown',
+    author='...',
+    author_email='...',
+    project_urls={
+        'Documentation': '...',
+        'Source': '...',
+    },
+    classifiers=[
+        '...',
+    ],
+    keywords=[
+        '...',
+    ],
+    python_requires='>=3.8',
+    install_requires=[
+        '...',
+    ],
+    extras_require={
+        'feature': ['...'],
+    },
+
+    # Packaging
+    packages=find_packages(where='src'),
+    package_dir={'': 'src'},
+    package_data={
+        'foo': ['py.typed'],
+    },
+    zip_safe=False,
+    entry_points={
+        'console_scripts': [
+            'foo = foo.cli:main',
+        ],
+    },
+)
+
graft tests
+
+global-exclude *.py[cod] __pycache__
+
[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[project]
+name = "foo"
+description = "..."
+readme = "README.md"
+authors = [
+  { name = "...", email = "..." },
+]
+classifiers = [
+  "...",
+]
+keywords = [
+  "...",
+]
+requires-python = ">=3.8"
+dependencies = [
+  "...",
+]
+dynamic = ["version"]
+
+[project.urls]
+Documentation = "..."
+Source = "..."
+
+[project.optional-dependencies]
+feature = ["..."]
+
+[project.scripts]
+foo = "foo.cli:main"
+
+[tool.hatch.version]
+path = "src/foo/__about__.py"
+
+[tool.hatch.build.targets.sdist]
+include = [
+  "/src",
+  "/tests",
+]
+

Environments

Invocation:

tox
+
[tox]
+envlist =
+    py{38,39}-{42,3.14}
+    py{39,310}-{9000}-{foo,bar}
+
+[testenv]
+usedevelop = true
+deps =
+    coverage[toml]
+    pytest
+    pytest-cov
+    foo: cryptography
+commands =
+    pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests {posargs}
+setenv =
+    3.14: PRODUCT_VERSION=3.14
+    42: PRODUCT_VERSION=42
+    9000: PRODUCT_VERSION=9000
+    {foo,bar}: EXPERIMENTAL=true
+

Invocation:

hatch run test
+
[tool.hatch.envs.default]
+dependencies = [
+  "coverage[toml]",
+  "pytest",
+  "pytest-cov",
+]
+
+[tool.hatch.envs.default.scripts]
+test = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests'
+
+[tool.hatch.envs.default.overrides]
+matrix.version.env-vars = "PRODUCT_VERSION"
+matrix.feature.env-vars = "EXPERIMENTAL=true"
+matrix.feature.dependencies = [
+  { value = "cryptography", if = ["foo"] },
+]
+
+[[tool.hatch.envs.default.matrix]]
+python = ["3.8", "3.9"]
+version = ["42", "3.14"]
+
+[[tool.hatch.envs.default.matrix]]
+python = ["3.9", "3.10"]
+version = ["9000"]
+feature = ["foo", "bar"]
+
[envs.default]
+dependencies = [
+  "coverage[toml]",
+  "pytest",
+  "pytest-cov",
+]
+
+[envs.default.scripts]
+test = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests'
+
+[envs.default.overrides]
+matrix.version.env-vars = "PRODUCT_VERSION"
+matrix.feature.env-vars = "EXPERIMENTAL=true"
+matrix.feature.dependencies = [
+  { value = "cryptography", if = ["foo"] },
+]
+
+[[envs.default.matrix]]
+python = ["3.8", "3.9"]
+version = ["42", "3.14"]
+
+[[envs.default.matrix]]
+python = ["3.9", "3.10"]
+version = ["9000"]
+feature = ["foo", "bar"]
+

Fast CLI?

The claim about being faster than other tools is based on timings that are always checked in CI.

Hatch achieves this by using lazy imports, lazily performing computation manually and with functools.cached_property, using hacks like not not ... instead of bool(...), etc.

\ No newline at end of file diff --git a/1.13/next-steps/index.html b/1.13/next-steps/index.html new file mode 100644 index 000000000..0e77227df --- /dev/null +++ b/1.13/next-steps/index.html @@ -0,0 +1,16 @@ + Next steps - Hatch

Next steps


Learn more

At this point you should have a basic understanding of how to use Hatch.

Now you may want to check out advanced configuration for environments or builds, set up your preferred shell, or read more about Hatch's CLI.

After that, check out the Hatch Showcase project to see examples of what is possible.

Finally, if you see a need, feel free to write a plugin for extended functionality.

Community

For any projects using Hatch, you may add its official badge somewhere prominent like the README.

Hatch project

[![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch)
+
.. image:: https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg
+   :alt: Hatch project
+   :target: https://github.com/pypa/hatch
+
\ No newline at end of file diff --git a/1.13/objects.inv b/1.13/objects.inv new file mode 100644 index 000000000..11ee19d74 Binary files /dev/null and b/1.13/objects.inv differ diff --git a/1.13/plugins/about/index.html b/1.13/plugins/about/index.html new file mode 100644 index 000000000..0aa0e2b0c --- /dev/null +++ b/1.13/plugins/about/index.html @@ -0,0 +1,34 @@ + Plugins - Hatch

Plugins


Hatch utilizes pluggy for its plugin functionality.

Overview

All plugins provide registration hooks that return one or more classes that inherit from a particular type interface.

Each registration hook must be decorated by Hatch's hook marker. For example, if you wanted to create a new kind of environment you could do:

from hatchling.plugin import hookimpl
+
+from .plugin import SpecialEnvironment
+
+
+@hookimpl
+def hatch_register_environment():
+    return SpecialEnvironment
+

The hooks can return a single class or a list of classes.

Every class must define an attribute called PLUGIN_NAME that users will select when they wish to use the plugin. So in the example above, the class might be defined like:

...
+class SpecialEnvironment(...):
+    PLUGIN_NAME = 'special'
+    ...
+

Project configuration

Naming

It is recommended that plugin project names are prefixed with hatch-. For example, if you wanted to make a plugin that provides some functionality for a product named foo you might do:

[project]
+name = "hatch-foo"
+

Discovery

You'll need to define your project as a Python plugin for Hatch:

[project.entry-points.hatch]
+foo = "pkg.hooks"
+

The name of the plugin should be the project name (excluding any hatch- prefix) and the path should represent the module that contains the registration hooks.

Classifier

Add Framework :: Hatch to your project's classifiers to make it easy to search for Hatch plugins:

[project]
+classifiers = [
+  ...
+  "Framework :: Hatch",
+  ...
+]
+

Types

Hatchling

These are all involved in building projects and therefore any defined dependencies are automatically installed in each build environment.

Hatch

These must be installed in the same environment as Hatch itself.

\ No newline at end of file diff --git a/1.13/plugins/build-hook/custom/index.html b/1.13/plugins/build-hook/custom/index.html new file mode 100644 index 000000000..cbe478321 --- /dev/null +++ b/1.13/plugins/build-hook/custom/index.html @@ -0,0 +1,21 @@ + Custom build hook - Hatch

Custom build hook


This is a custom class in a given Python file that inherits from the BuildHookInterface.

Configuration

The build hook plugin name is custom.

[tool.hatch.build.hooks.custom]
+[tool.hatch.build.targets.<TARGET_NAME>.hooks.custom]
+
[build.hooks.custom]
+[build.targets.<TARGET_NAME>.hooks.custom]
+

Options

Option Default Description
path hatch_build.py The path of the Python file

Example

from hatchling.builders.hooks.plugin.interface import BuildHookInterface
+
+
+class CustomBuildHook(BuildHookInterface):
+    ...
+

If multiple subclasses are found, you must define a function named get_build_hook that returns the desired build hook.

Note

Any defined PLUGIN_NAME is ignored and will always be custom.

\ No newline at end of file diff --git a/1.13/plugins/build-hook/index.html b/1.13/plugins/build-hook/index.html new file mode 100644 index 000000000..450e873c1 --- /dev/null +++ b/1.13/plugins/build-hook/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/plugins/build-hook/reference/index.html b/1.13/plugins/build-hook/reference/index.html new file mode 100644 index 000000000..57e9b86ae --- /dev/null +++ b/1.13/plugins/build-hook/reference/index.html @@ -0,0 +1,200 @@ + Build hook plugins - Hatch

Build hook plugins


A build hook provides code that will be executed at various stages of the build process. See the documentation for build hook configuration.

Known third-party

Overview

Build hooks run for every selected version of build targets.

The initialization stage occurs immediately before each build and the finalization stage occurs immediately after. Each stage has the opportunity to view or modify build data.

Build data

Build data is a simple mapping whose contents can influence the behavior of builds. Which fields exist and are recognized depends on each build target.

The following fields are always present and recognized by the build system itself:

Field Type Description
artifacts list[str] This is a list of extra artifact patterns and should generally only be appended to
force_include dict[str, str] This is a mapping of extra forced inclusion paths, with this mapping taking precedence in case of conflicts
build_hooks tuple[str, ...] This is an immutable sequence of the names of the configured build hooks and matches the order in which they run

Attention

While user-facing TOML options are hyphenated, build data fields should be named with underscores to allow plugins to use them as valid Python identifiers.

Notes

In some cases it may be necessary to use force_include rather than artifacts. For example, say that you want to install a lib.so directly at the root of site-packages and a project defines a package src/foo. If you create src/lib.so, there will never be a match because the directory traversal starts at src/foo rather than src. In that case you must do either:

build_data['force_include']['src/lib.so'] = 'src/lib.so'
+

or

build_data['force_include']['/absolute/path/to/src/lib.so'] = 'src/lib.so'
+

BuildHookInterface

Example usage:

from hatchling.builders.hooks.plugin.interface import BuildHookInterface
+
+
+class SpecialBuildHook(BuildHookInterface):
+    PLUGIN_NAME = 'special'
+    ...
+
from hatchling.plugin import hookimpl
+
+from .plugin import SpecialBuildHook
+
+
+@hookimpl
+def hatch_register_build_hook():
+    return SpecialBuildHook
+
Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
class BuildHookInterface(Generic[BuilderConfigBound]):  # no cov
+    """
+    Example usage:
+
+    ```python tab="plugin.py"
+    from hatchling.builders.hooks.plugin.interface import BuildHookInterface
+
+
+    class SpecialBuildHook(BuildHookInterface):
+        PLUGIN_NAME = 'special'
+        ...
+    ```
+
+    ```python tab="hooks.py"
+    from hatchling.plugin import hookimpl
+
+    from .plugin import SpecialBuildHook
+
+
+    @hookimpl
+    def hatch_register_build_hook():
+        return SpecialBuildHook
+    ```
+    """
+
+    PLUGIN_NAME = ''
+    """The name used for selection."""
+
+    def __init__(
+        self,
+        root: str,
+        config: dict[str, Any],
+        build_config: BuilderConfigBound,
+        metadata: ProjectMetadata,
+        directory: str,
+        target_name: str,
+        app: Application | None = None,
+    ) -> None:
+        self.__root = root
+        self.__config = config
+        self.__build_config = build_config
+        self.__metadata = metadata
+        self.__directory = directory
+        self.__target_name = target_name
+        self.__app = app
+
+    @property
+    def app(self) -> Application:
+        """
+        An instance of [Application](../utilities.md#hatchling.bridge.app.Application).
+        """
+        if self.__app is None:
+            from hatchling.bridge.app import Application
+
+            self.__app = cast(Application, Application().get_safe_application())
+
+        return self.__app
+
+    @property
+    def root(self) -> str:
+        """
+        The root of the project tree.
+        """
+        return self.__root
+
+    @property
+    def config(self) -> dict[str, Any]:
+        """
+        The cumulative hook configuration.
+
+        ```toml config-example
+        [tool.hatch.build.hooks.<PLUGIN_NAME>]
+        [tool.hatch.build.targets.<TARGET_NAME>.hooks.<PLUGIN_NAME>]
+        ```
+        """
+        return self.__config
+
+    @property
+    def metadata(self) -> ProjectMetadata:
+        # Undocumented for now
+        return self.__metadata
+
+    @property
+    def build_config(self) -> BuilderConfigBound:
+        """
+        An instance of [BuilderConfig](../utilities.md#hatchling.builders.config.BuilderConfig).
+        """
+        return self.__build_config
+
+    @property
+    def directory(self) -> str:
+        """
+        The build directory.
+        """
+        return self.__directory
+
+    @property
+    def target_name(self) -> str:
+        """
+        The plugin name of the build target.
+        """
+        return self.__target_name
+
+    def dependencies(self) -> list[str]:  # noqa: PLR6301
+        """
+        A list of extra [dependencies](../../config/dependency.md) that must be installed
+        prior to builds.
+
+        !!! warning
+            - For this to have any effect the hook dependency itself cannot be dynamic and
+                must always be defined in `build-system.requires`.
+            - As the hook must be imported to call this method, imports that require these
+                dependencies must be evaluated lazily.
+        """
+        return []
+
+    def clean(self, versions: list[str]) -> None:
+        """
+        This occurs before the build process if the `-c`/`--clean` flag was passed to
+        the [`build`](../../cli/reference.md#hatch-build) command, or when invoking
+        the [`clean`](../../cli/reference.md#hatch-clean) command.
+        """
+
+    def initialize(self, version: str, build_data: dict[str, Any]) -> None:
+        """
+        This occurs immediately before each build.
+
+        Any modifications to the build data will be seen by the build target.
+        """
+
+    def finalize(self, version: str, build_data: dict[str, Any], artifact_path: str) -> None:
+        """
+        This occurs immediately after each build and will not run if the `--hooks-only` flag
+        was passed to the [`build`](../../cli/reference.md#hatch-build) command.
+
+        The build data will reflect any modifications done by the target during the build.
+        """
+

PLUGIN_NAME = '' class-attribute instance-attribute

The name used for selection.

app: Application property

An instance of Application.

root: str property

The root of the project tree.

config: dict[str, Any] property

The cumulative hook configuration.

[tool.hatch.build.hooks.<PLUGIN_NAME>]
+[tool.hatch.build.targets.<TARGET_NAME>.hooks.<PLUGIN_NAME>]
+
[build.hooks.<PLUGIN_NAME>]
+[build.targets.<TARGET_NAME>.hooks.<PLUGIN_NAME>]
+

build_config: BuilderConfigBound property

An instance of BuilderConfig.

target_name: str property

The plugin name of the build target.

directory: str property

The build directory.

dependencies() -> list[str]

A list of extra dependencies that must be installed prior to builds.

Warning

  • For this to have any effect the hook dependency itself cannot be dynamic and must always be defined in build-system.requires.
  • As the hook must be imported to call this method, imports that require these dependencies must be evaluated lazily.
Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
def dependencies(self) -> list[str]:  # noqa: PLR6301
+    """
+    A list of extra [dependencies](../../config/dependency.md) that must be installed
+    prior to builds.
+
+    !!! warning
+        - For this to have any effect the hook dependency itself cannot be dynamic and
+            must always be defined in `build-system.requires`.
+        - As the hook must be imported to call this method, imports that require these
+            dependencies must be evaluated lazily.
+    """
+    return []
+

clean(versions: list[str]) -> None

This occurs before the build process if the -c/--clean flag was passed to the build command, or when invoking the clean command.

Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
def clean(self, versions: list[str]) -> None:
+    """
+    This occurs before the build process if the `-c`/`--clean` flag was passed to
+    the [`build`](../../cli/reference.md#hatch-build) command, or when invoking
+    the [`clean`](../../cli/reference.md#hatch-clean) command.
+    """
+

initialize(version: str, build_data: dict[str, Any]) -> None

This occurs immediately before each build.

Any modifications to the build data will be seen by the build target.

Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
+    """
+    This occurs immediately before each build.
+
+    Any modifications to the build data will be seen by the build target.
+    """
+

finalize(version: str, build_data: dict[str, Any], artifact_path: str) -> None

This occurs immediately after each build and will not run if the --hooks-only flag was passed to the build command.

The build data will reflect any modifications done by the target during the build.

Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
def finalize(self, version: str, build_data: dict[str, Any], artifact_path: str) -> None:
+    """
+    This occurs immediately after each build and will not run if the `--hooks-only` flag
+    was passed to the [`build`](../../cli/reference.md#hatch-build) command.
+
+    The build data will reflect any modifications done by the target during the build.
+    """
+
\ No newline at end of file diff --git a/1.13/plugins/build-hook/version/index.html b/1.13/plugins/build-hook/version/index.html new file mode 100644 index 000000000..4e8add8ef --- /dev/null +++ b/1.13/plugins/build-hook/version/index.html @@ -0,0 +1,16 @@ + Version build hook - Hatch

Version build hook


This writes the project's version to a file.

Configuration

The build hook plugin name is version.

[tool.hatch.build.hooks.version]
+[tool.hatch.build.targets.<TARGET_NAME>.hooks.version]
+
[build.hooks.version]
+[build.targets.<TARGET_NAME>.hooks.version]
+

Options

Option Description
path (required) A relative path to the desired file
template A string representing the entire contents of path that will be formatted with a version variable
pattern Rather than updating the entire file, a regular expression may be used that has a named group called version that represents the version. If set to true, a pattern will be used that looks for a variable named __version__ or VERSION that is set to a string containing the version, optionally prefixed with the lowercase letter v.
\ No newline at end of file diff --git a/1.13/plugins/builder/app/index.html b/1.13/plugins/builder/app/index.html new file mode 100644 index 000000000..ddc5927bf --- /dev/null +++ b/1.13/plugins/builder/app/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/plugins/builder/binary/index.html b/1.13/plugins/builder/binary/index.html new file mode 100644 index 000000000..98980e474 --- /dev/null +++ b/1.13/plugins/builder/binary/index.html @@ -0,0 +1,14 @@ + Binary builder - Hatch

Binary builder


This uses PyApp to build an application that is able to bootstrap itself at runtime.

Note

This requires an installation of Rust.

Configuration

The builder plugin name is binary.

[tool.hatch.build.targets.binary]
+
[build.targets.binary]
+

Options

Option Default Description
scripts all defined An array of defined script names to limit what gets built
python-version latest compatible Python minor version The Python version ID to use
pyapp-version The version of PyApp to use

Build behavior

If any scripts are defined then each one will be built (limited by the scripts option). Otherwise, a single executable will be built based on the project name assuming there is an equivalently named module with a __main__.py file.

Every executable will be built inside an app directory in the output directory.

If the CARGO environment variable is set then that path will be used as the executable for performing builds.

If the CARGO_BUILD_TARGET environment variable is set then its value will be appended to the file name stems.

If the PYAPP_REPO environment variable is set then a local build will be performed inside that directory rather than installing from crates.io. Note that this is required if the CARGO environment variable refers to cross.

\ No newline at end of file diff --git a/1.13/plugins/builder/custom/index.html b/1.13/plugins/builder/custom/index.html new file mode 100644 index 000000000..746ff3997 --- /dev/null +++ b/1.13/plugins/builder/custom/index.html @@ -0,0 +1,19 @@ + Custom builder - Hatch

Custom builder


This is a custom class in a given Python file that inherits from the BuilderInterface.

Configuration

The builder plugin name is custom.

[tool.hatch.build.targets.custom]
+
[build.targets.custom]
+

Options

Option Default Description
path hatch_build.py The path of the Python file

Example

from hatchling.builders.plugin.interface import BuilderInterface
+
+
+class CustomBuilder(BuilderInterface):
+    ...
+

If multiple subclasses are found, you must define a function named get_builder that returns the desired builder.

Note

Any defined PLUGIN_NAME is ignored and will always be custom.

\ No newline at end of file diff --git a/1.13/plugins/builder/index.html b/1.13/plugins/builder/index.html new file mode 100644 index 000000000..450e873c1 --- /dev/null +++ b/1.13/plugins/builder/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/plugins/builder/reference/index.html b/1.13/plugins/builder/reference/index.html new file mode 100644 index 000000000..b9489eef4 --- /dev/null +++ b/1.13/plugins/builder/reference/index.html @@ -0,0 +1,489 @@ + Builder plugins - Hatch

Builder plugins


See the documentation for build configuration.

Known third-party

  • hatch-aws - used for building AWS Lambda functions with SAM
  • hatch-zipped-directory - used for building ZIP archives for installation into various foreign package installation systems

BuilderInterface

Example usage:

from hatchling.builders.plugin.interface import BuilderInterface
+
+
+class SpecialBuilder(BuilderInterface):
+    PLUGIN_NAME = 'special'
+    ...
+
from hatchling.plugin import hookimpl
+
+from .plugin import SpecialBuilder
+
+
+@hookimpl
+def hatch_register_builder():
+    return SpecialBuilder
+
Source code in backend/src/hatchling/builders/plugin/interface.py
class BuilderInterface(ABC, Generic[BuilderConfigBound, PluginManagerBound]):
+    """
+    Example usage:
+
+    ```python tab="plugin.py"
+    from hatchling.builders.plugin.interface import BuilderInterface
+
+
+    class SpecialBuilder(BuilderInterface):
+        PLUGIN_NAME = 'special'
+        ...
+    ```
+
+    ```python tab="hooks.py"
+    from hatchling.plugin import hookimpl
+
+    from .plugin import SpecialBuilder
+
+
+    @hookimpl
+    def hatch_register_builder():
+        return SpecialBuilder
+    ```
+    """
+
+    PLUGIN_NAME = ''
+    """The name used for selection."""
+
+    def __init__(
+        self,
+        root: str,
+        plugin_manager: PluginManagerBound | None = None,
+        config: dict[str, Any] | None = None,
+        metadata: ProjectMetadata | None = None,
+        app: Application | None = None,
+    ) -> None:
+        self.__root = root
+        self.__plugin_manager = cast(PluginManagerBound, plugin_manager)
+        self.__raw_config = config
+        self.__metadata = metadata
+        self.__app = app
+        self.__config = cast(BuilderConfigBound, None)
+        self.__project_config: dict[str, Any] | None = None
+        self.__hatch_config: dict[str, Any] | None = None
+        self.__build_config: dict[str, Any] | None = None
+        self.__build_targets: list[str] | None = None
+        self.__target_config: dict[str, Any] | None = None
+
+        # Metadata
+        self.__project_id: str | None = None
+
+    def build(
+        self,
+        *,
+        directory: str | None = None,
+        versions: list[str] | None = None,
+        hooks_only: bool | None = None,
+        clean: bool | None = None,
+        clean_hooks_after: bool | None = None,
+        clean_only: bool | None = False,
+    ) -> Generator[str, None, None]:
+        # Fail early for invalid project metadata
+        self.metadata.validate_fields()
+
+        if directory is None:
+            directory = (
+                self.config.normalize_build_directory(os.environ[BuildEnvVars.LOCATION])
+                if BuildEnvVars.LOCATION in os.environ
+                else self.config.directory
+            )
+
+        if not os.path.isdir(directory):
+            os.makedirs(directory)
+
+        version_api = self.get_version_api()
+
+        versions = versions or self.config.versions
+        if versions:
+            unknown_versions = set(versions) - set(version_api)
+            if unknown_versions:
+                message = (
+                    f'Unknown versions for target `{self.PLUGIN_NAME}`: {", ".join(map(str, sorted(unknown_versions)))}'
+                )
+                raise ValueError(message)
+
+        if hooks_only is None:
+            hooks_only = env_var_enabled(BuildEnvVars.HOOKS_ONLY)
+
+        configured_build_hooks = self.get_build_hooks(directory)
+        build_hooks = list(configured_build_hooks.values())
+
+        if clean_only:
+            clean = True
+        elif clean is None:
+            clean = env_var_enabled(BuildEnvVars.CLEAN)
+        if clean:
+            if not hooks_only:
+                self.clean(directory, versions)
+
+            for build_hook in build_hooks:
+                build_hook.clean(versions)
+
+            if clean_only:
+                return
+
+        if clean_hooks_after is None:
+            clean_hooks_after = env_var_enabled(BuildEnvVars.CLEAN_HOOKS_AFTER)
+
+        for version in versions:
+            self.app.display_debug(f'Building `{self.PLUGIN_NAME}` version `{version}`')
+
+            build_data = self.get_default_build_data()
+            self.set_build_data_defaults(build_data)
+
+            # Allow inspection of configured build hooks and the order in which they run
+            build_data['build_hooks'] = tuple(configured_build_hooks)
+
+            # Execute all `initialize` build hooks
+            for build_hook in build_hooks:
+                build_hook.initialize(version, build_data)
+
+            if hooks_only:
+                self.app.display_debug(f'Only ran build hooks for `{self.PLUGIN_NAME}` version `{version}`')
+                continue
+
+            # Build the artifact
+            with self.config.set_build_data(build_data):
+                artifact = version_api[version](directory, **build_data)
+
+            # Execute all `finalize` build hooks
+            for build_hook in build_hooks:
+                build_hook.finalize(version, build_data, artifact)
+
+            if clean_hooks_after:
+                for build_hook in build_hooks:
+                    build_hook.clean([version])
+
+            yield artifact
+
+    def recurse_included_files(self) -> Iterable[IncludedFile]:
+        """
+        Returns a consistently generated series of file objects for every file that should be distributed. Each file
+        object has three `str` attributes:
+
+        - `path` - the absolute path
+        - `relative_path` - the path relative to the project root; will be an empty string for external files
+        - `distribution_path` - the path to be distributed as
+        """
+        yield from self.recurse_selected_project_files()
+        yield from self.recurse_forced_files(self.config.get_force_include())
+
+    def recurse_selected_project_files(self) -> Iterable[IncludedFile]:
+        if self.config.only_include:
+            yield from self.recurse_explicit_files(self.config.only_include)
+        else:
+            yield from self.recurse_project_files()
+
+    def recurse_project_files(self) -> Iterable[IncludedFile]:
+        for root, dirs, files in safe_walk(self.root):
+            relative_path = get_relative_path(root, self.root)
+
+            dirs[:] = sorted(d for d in dirs if not self.config.directory_is_excluded(d, relative_path))
+
+            files.sort()
+            is_package = '__init__.py' in files
+            for f in files:
+                if f in EXCLUDED_FILES:
+                    continue
+
+                relative_file_path = os.path.join(relative_path, f)
+                distribution_path = self.config.get_distribution_path(relative_file_path)
+                if self.config.path_is_reserved(distribution_path):
+                    continue
+
+                if self.config.include_path(relative_file_path, is_package=is_package):
+                    yield IncludedFile(
+                        os.path.join(root, f), relative_file_path, self.config.get_distribution_path(relative_file_path)
+                    )
+
+    def recurse_forced_files(self, inclusion_map: dict[str, str]) -> Iterable[IncludedFile]:
+        for source, target_path in inclusion_map.items():
+            external = not source.startswith(self.root)
+            if os.path.isfile(source):
+                yield IncludedFile(
+                    source,
+                    '' if external else os.path.relpath(source, self.root),
+                    self.config.get_distribution_path(target_path),
+                )
+            elif os.path.isdir(source):
+                for root, dirs, files in safe_walk(source):
+                    relative_directory = get_relative_path(root, source)
+
+                    dirs[:] = sorted(d for d in dirs if d not in EXCLUDED_DIRECTORIES)
+
+                    files.sort()
+                    for f in files:
+                        if f in EXCLUDED_FILES:
+                            continue
+
+                        relative_file_path = os.path.join(target_path, relative_directory, f)
+                        distribution_path = self.config.get_distribution_path(relative_file_path)
+                        if not self.config.path_is_reserved(distribution_path):
+                            yield IncludedFile(
+                                os.path.join(root, f),
+                                '' if external else relative_file_path,
+                                distribution_path,
+                            )
+            else:
+                msg = f'Forced include not found: {source}'
+                raise FileNotFoundError(msg)
+
+    def recurse_explicit_files(self, inclusion_map: dict[str, str]) -> Iterable[IncludedFile]:
+        for source, target_path in inclusion_map.items():
+            external = not source.startswith(self.root)
+            if os.path.isfile(source):
+                distribution_path = self.config.get_distribution_path(target_path)
+                if not self.config.path_is_reserved(distribution_path):
+                    yield IncludedFile(
+                        source,
+                        '' if external else os.path.relpath(source, self.root),
+                        self.config.get_distribution_path(target_path),
+                    )
+            elif os.path.isdir(source):
+                for root, dirs, files in safe_walk(source):
+                    relative_directory = get_relative_path(root, source)
+
+                    dirs[:] = sorted(d for d in dirs if d not in EXCLUDED_DIRECTORIES)
+
+                    files.sort()
+                    is_package = '__init__.py' in files
+                    for f in files:
+                        if f in EXCLUDED_FILES:
+                            continue
+
+                        relative_file_path = os.path.join(target_path, relative_directory, f)
+                        distribution_path = self.config.get_distribution_path(relative_file_path)
+                        if self.config.path_is_reserved(distribution_path):
+                            continue
+
+                        if self.config.include_path(relative_file_path, explicit=True, is_package=is_package):
+                            yield IncludedFile(
+                                os.path.join(root, f), '' if external else relative_file_path, distribution_path
+                            )
+
+    @property
+    def root(self) -> str:
+        """
+        The root of the project tree.
+        """
+        return self.__root
+
+    @property
+    def plugin_manager(self) -> PluginManagerBound:
+        if self.__plugin_manager is None:
+            from hatchling.plugin.manager import PluginManager
+
+            self.__plugin_manager = PluginManager()
+
+        return self.__plugin_manager
+
+    @property
+    def metadata(self) -> ProjectMetadata:
+        if self.__metadata is None:
+            from hatchling.metadata.core import ProjectMetadata
+
+            self.__metadata = ProjectMetadata(self.root, self.plugin_manager, self.__raw_config)
+
+        return self.__metadata
+
+    @property
+    def app(self) -> Application:
+        """
+        An instance of [Application](../utilities.md#hatchling.bridge.app.Application).
+        """
+        if self.__app is None:
+            from hatchling.bridge.app import Application
+
+            self.__app = cast(Application, Application().get_safe_application())
+
+        return self.__app
+
+    @property
+    def raw_config(self) -> dict[str, Any]:
+        if self.__raw_config is None:
+            self.__raw_config = self.metadata.config
+
+        return self.__raw_config
+
+    @property
+    def project_config(self) -> dict[str, Any]:
+        if self.__project_config is None:
+            self.__project_config = self.metadata.core.config
+
+        return self.__project_config
+
+    @property
+    def hatch_config(self) -> dict[str, Any]:
+        if self.__hatch_config is None:
+            self.__hatch_config = self.metadata.hatch.config
+
+        return self.__hatch_config
+
+    @property
+    def config(self) -> BuilderConfigBound:
+        """
+        An instance of [BuilderConfig](../utilities.md#hatchling.builders.config.BuilderConfig).
+        """
+        if self.__config is None:
+            self.__config = self.get_config_class()(
+                self, self.root, self.PLUGIN_NAME, self.build_config, self.target_config
+            )
+
+        return self.__config
+
+    @property
+    def build_config(self) -> dict[str, Any]:
+        """
+        ```toml config-example
+        [tool.hatch.build]
+        ```
+        """
+        if self.__build_config is None:
+            self.__build_config = self.metadata.hatch.build_config
+
+        return self.__build_config
+
+    @property
+    def target_config(self) -> dict[str, Any]:
+        """
+        ```toml config-example
+        [tool.hatch.build.targets.<PLUGIN_NAME>]
+        ```
+        """
+        if self.__target_config is None:
+            target_config: dict[str, Any] = self.metadata.hatch.build_targets.get(self.PLUGIN_NAME, {})
+            if not isinstance(target_config, dict):
+                message = f'Field `tool.hatch.build.targets.{self.PLUGIN_NAME}` must be a table'
+                raise TypeError(message)
+
+            self.__target_config = target_config
+
+        return self.__target_config
+
+    @property
+    def project_id(self) -> str:
+        if self.__project_id is None:
+            self.__project_id = f'{self.normalize_file_name_component(self.metadata.core.name)}-{self.metadata.version}'
+
+        return self.__project_id
+
+    def get_build_hooks(self, directory: str) -> dict[str, BuildHookInterface]:
+        configured_build_hooks = {}
+        for hook_name, config in self.config.hook_config.items():
+            build_hook = self.plugin_manager.build_hook.get(hook_name)
+            if build_hook is None:
+                from hatchling.plugin.exceptions import UnknownPluginError
+
+                message = f'Unknown build hook: {hook_name}'
+                raise UnknownPluginError(message)
+
+            configured_build_hooks[hook_name] = build_hook(
+                self.root, config, self.config, self.metadata, directory, self.PLUGIN_NAME, self.app
+            )
+
+        return configured_build_hooks
+
+    @abstractmethod
+    def get_version_api(self) -> dict[str, Callable]:
+        """
+        A mapping of `str` versions to a callable that is used for building.
+        Each callable must have the following signature:
+
+        ```python
+        def ...(build_dir: str, build_data: dict) -> str:
+        ```
+
+        The return value must be the absolute path to the built artifact.
+        """
+
+    def get_default_versions(self) -> list[str]:
+        """
+        A list of versions to build when users do not specify any, defaulting to all versions.
+        """
+        return list(self.get_version_api())
+
+    def get_default_build_data(self) -> dict[str, Any]:  # noqa: PLR6301
+        """
+        A mapping that can be modified by [build hooks](../build-hook/reference.md) to influence the behavior of builds.
+        """
+        return {}
+
+    def set_build_data_defaults(self, build_data: dict[str, Any]) -> None:  # noqa: PLR6301
+        build_data.setdefault('artifacts', [])
+        build_data.setdefault('force_include', {})
+
+    def clean(self, directory: str, versions: list[str]) -> None:
+        """
+        Called before builds if the `-c`/`--clean` flag was passed to the
+        [`build`](../../cli/reference.md#hatch-build) command.
+        """
+
+    @classmethod
+    def get_config_class(cls) -> type[BuilderConfig]:
+        """
+        Must return a subclass of [BuilderConfig](../utilities.md#hatchling.builders.config.BuilderConfig).
+        """
+        return BuilderConfig
+
+    @staticmethod
+    def normalize_file_name_component(file_name: str) -> str:
+        """
+        https://peps.python.org/pep-0427/#escaping-and-unicode
+        """
+        return re.sub(r'[^\w\d.]+', '_', file_name, flags=re.UNICODE)
+

PLUGIN_NAME = '' class-attribute instance-attribute

The name used for selection.

app: Application property

An instance of Application.

root: str property

The root of the project tree.

build_config: dict[str, Any] property

[tool.hatch.build]
+
[build]
+

target_config: dict[str, Any] property

[tool.hatch.build.targets.<PLUGIN_NAME>]
+
[build.targets.<PLUGIN_NAME>]
+

config: BuilderConfigBound property

An instance of BuilderConfig.

get_config_class() -> type[BuilderConfig] classmethod

Must return a subclass of BuilderConfig.

Source code in backend/src/hatchling/builders/plugin/interface.py
@classmethod
+def get_config_class(cls) -> type[BuilderConfig]:
+    """
+    Must return a subclass of [BuilderConfig](../utilities.md#hatchling.builders.config.BuilderConfig).
+    """
+    return BuilderConfig
+

get_version_api() -> dict[str, Callable] abstractmethod

A mapping of str versions to a callable that is used for building. Each callable must have the following signature:

def ...(build_dir: str, build_data: dict) -> str:
+

The return value must be the absolute path to the built artifact.

Source code in backend/src/hatchling/builders/plugin/interface.py
@abstractmethod
+def get_version_api(self) -> dict[str, Callable]:
+    """
+    A mapping of `str` versions to a callable that is used for building.
+    Each callable must have the following signature:
+
+    ```python
+    def ...(build_dir: str, build_data: dict) -> str:
+    ```
+
+    The return value must be the absolute path to the built artifact.
+    """
+

get_default_versions() -> list[str]

A list of versions to build when users do not specify any, defaulting to all versions.

Source code in backend/src/hatchling/builders/plugin/interface.py
def get_default_versions(self) -> list[str]:
+    """
+    A list of versions to build when users do not specify any, defaulting to all versions.
+    """
+    return list(self.get_version_api())
+

clean(directory: str, versions: list[str]) -> None

Called before builds if the -c/--clean flag was passed to the build command.

Source code in backend/src/hatchling/builders/plugin/interface.py
def clean(self, directory: str, versions: list[str]) -> None:
+    """
+    Called before builds if the `-c`/`--clean` flag was passed to the
+    [`build`](../../cli/reference.md#hatch-build) command.
+    """
+

recurse_included_files() -> Iterable[IncludedFile]

Returns a consistently generated series of file objects for every file that should be distributed. Each file object has three str attributes:

  • path - the absolute path
  • relative_path - the path relative to the project root; will be an empty string for external files
  • distribution_path - the path to be distributed as
Source code in backend/src/hatchling/builders/plugin/interface.py
def recurse_included_files(self) -> Iterable[IncludedFile]:
+    """
+    Returns a consistently generated series of file objects for every file that should be distributed. Each file
+    object has three `str` attributes:
+
+    - `path` - the absolute path
+    - `relative_path` - the path relative to the project root; will be an empty string for external files
+    - `distribution_path` - the path to be distributed as
+    """
+    yield from self.recurse_selected_project_files()
+    yield from self.recurse_forced_files(self.config.get_force_include())
+

get_default_build_data() -> dict[str, Any]

A mapping that can be modified by build hooks to influence the behavior of builds.

Source code in backend/src/hatchling/builders/plugin/interface.py
def get_default_build_data(self) -> dict[str, Any]:  # noqa: PLR6301
+    """
+    A mapping that can be modified by [build hooks](../build-hook/reference.md) to influence the behavior of builds.
+    """
+    return {}
+
\ No newline at end of file diff --git a/1.13/plugins/builder/sdist/index.html b/1.13/plugins/builder/sdist/index.html new file mode 100644 index 000000000..407685513 --- /dev/null +++ b/1.13/plugins/builder/sdist/index.html @@ -0,0 +1,14 @@ + Source distribution builder - Hatch

Source distribution builder


A source distribution, or sdist, is an archive of Python "source code". Although largely unspecified, by convention it should include everything that is required to build a wheel without making network requests.

Configuration

The builder plugin name is sdist.

[tool.hatch.build.targets.sdist]
+
[build.targets.sdist]
+

Options

Option Default Description
core-metadata-version "2.3" The version of core metadata to use
strict-naming true Whether or not file names should contain the normalized version of the project name
support-legacy false Whether or not to include a setup.py file to support legacy installation mechanisms

Versions

Version Description
standard (default) The latest conventional format

Default file selection

When the user has not set any file selection options, all files that are not ignored by your VCS will be included.

Note

The following files are always included and cannot be excluded:

  • /pyproject.toml
  • /hatch.toml
  • /hatch_build.py
  • /.gitignore or /.hgignore
  • Any defined readme file
  • All defined license-files

Reproducibility

Reproducible builds are supported.

Build data

This is data that can be modified by build hooks.

Data Default Description
dependencies Extra project dependencies
\ No newline at end of file diff --git a/1.13/plugins/builder/wheel/index.html b/1.13/plugins/builder/wheel/index.html new file mode 100644 index 000000000..3a05b087d --- /dev/null +++ b/1.13/plugins/builder/wheel/index.html @@ -0,0 +1,14 @@ + Wheel builder - Hatch

Wheel builder


A wheel is a binary distribution of a Python package that can be installed directly into an environment.

Configuration

The builder plugin name is wheel.

[tool.hatch.build.targets.wheel]
+
[build.targets.wheel]
+

Options

Option Default Description
core-metadata-version "2.3" The version of core metadata to use
shared-data A mapping similar to the forced inclusion option corresponding to the data subdirectory within the standard data directory that will be installed globally in a given Python environment, usually under sys.prefix
shared-scripts A mapping similar to the forced inclusion option corresponding to the scripts subdirectory within the standard data directory that will be installed in a given Python environment, usually under Scripts on Windows or bin otherwise, and would normally be available on PATH
extra-metadata A mapping similar to the forced inclusion option corresponding to extra metadata that will be shipped in a directory named extra_metadata
strict-naming true Whether or not file names should contain the normalized version of the project name
macos-max-compat false Whether or not on macOS, when build hooks have set the infer_tag build data, the wheel name should signal broad support rather than specific versions for newer SDK versions.

Note: This option will eventually be removed.
bypass-selection false Whether or not to suppress the error when one has not defined any file selection options and all heuristics have failed to determine what to ship

Versions

Version Description
standard (default) The latest standardized format
editable A wheel that only ships .pth files or import hooks for real-time development

Default file selection

When the user has not set any file selection options, the project name will be used to determine the package to ship in the following heuristic order:

  1. <NAME>/__init__.py
  2. src/<NAME>/__init__.py
  3. <NAME>.py
  4. <NAMESPACE>/<NAME>/__init__.py

If none of these heuristics are satisfied, an error will be raised.

Reproducibility

Reproducible builds are supported.

Build data

This is data that can be modified by build hooks.

Data Default Description
tag The full tag part of the filename (e.g. py3-none-any), defaulting to a cross-platform wheel with the supported major versions of Python based on project metadata
infer_tag False When tag is not set, this may be enabled to use the one most specific to the platform, Python interpreter, and ABI
pure_python True Whether or not to write metadata indicating that the package does not contain any platform-specific files
dependencies Extra project dependencies
shared_data Additional shared-data entries, which take precedence in case of conflicts
shared_scripts Additional shared-scripts entries, which take precedence in case of conflicts
extra_metadata Additional extra-metadata entries, which take precedence in case of conflicts
force_include_editable Similar to the force_include option but specifically for the editable version and takes precedence
\ No newline at end of file diff --git a/1.13/plugins/environment-collector/custom/index.html b/1.13/plugins/environment-collector/custom/index.html new file mode 100644 index 000000000..479c99d5b --- /dev/null +++ b/1.13/plugins/environment-collector/custom/index.html @@ -0,0 +1,19 @@ + Custom environment collector - Hatch

Custom environment collector


This is a custom class in a given Python file that inherits from the EnvironmentCollectorInterface.

Configuration

The environment collector plugin name is custom.

[tool.hatch.env.collectors.custom]
+
[env.collectors.custom]
+

Options

Option Default Description
path hatch_plugins.py The path of the Python file

Example

    from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface
+
+
+    class CustomEnvironmentCollector(EnvironmentCollectorInterface):
+        ...
+

If multiple subclasses are found, you must define a function named get_environment_collector that returns the desired environment collector.

Note

Any defined PLUGIN_NAME is ignored and will always be custom.

\ No newline at end of file diff --git a/1.13/plugins/environment-collector/default/index.html b/1.13/plugins/environment-collector/default/index.html new file mode 100644 index 000000000..f37518969 --- /dev/null +++ b/1.13/plugins/environment-collector/default/index.html @@ -0,0 +1,14 @@ + Default environment collector - Hatch

Default environment collector


This adds the default environment with type set to virtual and will always be applied.

Configuration

The environment collector plugin name is default.

[tool.hatch.env.collectors.default]
+
[env.collectors.default]
+

Options

There are no options available currently.

\ No newline at end of file diff --git a/1.13/plugins/environment-collector/index.html b/1.13/plugins/environment-collector/index.html new file mode 100644 index 000000000..450e873c1 --- /dev/null +++ b/1.13/plugins/environment-collector/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/plugins/environment-collector/reference/index.html b/1.13/plugins/environment-collector/reference/index.html new file mode 100644 index 000000000..a9acb5c88 --- /dev/null +++ b/1.13/plugins/environment-collector/reference/index.html @@ -0,0 +1,124 @@ + Environment collector plugins - Hatch

Environment collector plugins


Environment collectors allow for dynamically modifying environments or adding environments beyond those defined in config. Users can override default values provided by each environment.

Known third-party

Installation

Any required environment collectors that are not built-in must be manually installed alongside Hatch or listed in the tool.hatch.env.requires array for automatic management:

[tool.hatch.env]
+requires = [
+  "...",
+]
+
[env]
+requires = [
+  "...",
+]
+

EnvironmentCollectorInterface

Example usage:

    from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface
+
+
+    class SpecialEnvironmentCollector(EnvironmentCollectorInterface):
+        PLUGIN_NAME = 'special'
+        ...
+
    from hatchling.plugin import hookimpl
+
+    from .plugin import SpecialEnvironmentCollector
+
+
+    @hookimpl
+    def hatch_register_environment_collector():
+        return SpecialEnvironmentCollector
+
Source code in src/hatch/env/collectors/plugin/interface.py
class EnvironmentCollectorInterface:
+    """
+    Example usage:
+
+    ```python tab="plugin.py"
+        from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface
+
+
+        class SpecialEnvironmentCollector(EnvironmentCollectorInterface):
+            PLUGIN_NAME = 'special'
+            ...
+    ```
+
+    ```python tab="hooks.py"
+        from hatchling.plugin import hookimpl
+
+        from .plugin import SpecialEnvironmentCollector
+
+
+        @hookimpl
+        def hatch_register_environment_collector():
+            return SpecialEnvironmentCollector
+    ```
+    """
+
+    PLUGIN_NAME = ''
+    """The name used for selection."""
+
+    def __init__(self, root, config):
+        self.__root = root
+        self.__config = config
+
+    @property
+    def root(self):
+        """
+        The root of the project tree as a path-like object.
+        """
+        return self.__root
+
+    @property
+    def config(self) -> dict:
+        """
+        ```toml config-example
+        [tool.hatch.env.collectors.<PLUGIN_NAME>]
+        ```
+        """
+        return self.__config
+
+    def get_initial_config(self) -> dict[str, dict]:  # noqa: PLR6301
+        """
+        Returns configuration for environments keyed by the environment or matrix name.
+        """
+        return {}
+
+    def finalize_config(self, config: dict[str, dict]):
+        """
+        Finalizes configuration for environments keyed by the environment or matrix name. This will override
+        any user-defined settings and any collectors that ran before this call.
+
+        This is called before matrices are turned into concrete environments.
+        """
+
+    def finalize_environments(self, config: dict[str, dict]):
+        """
+        Finalizes configuration for environments keyed by the environment name. This will override
+        any user-defined settings and any collectors that ran before this call.
+
+        This is called after matrices are turned into concrete environments.
+        """
+

PLUGIN_NAME = '' class-attribute instance-attribute

The name used for selection.

root property

The root of the project tree as a path-like object.

config: dict property

[tool.hatch.env.collectors.<PLUGIN_NAME>]
+
[env.collectors.<PLUGIN_NAME>]
+

get_initial_config() -> dict[str, dict]

Returns configuration for environments keyed by the environment or matrix name.

Source code in src/hatch/env/collectors/plugin/interface.py
def get_initial_config(self) -> dict[str, dict]:  # noqa: PLR6301
+    """
+    Returns configuration for environments keyed by the environment or matrix name.
+    """
+    return {}
+

finalize_config(config: dict[str, dict])

Finalizes configuration for environments keyed by the environment or matrix name. This will override any user-defined settings and any collectors that ran before this call.

This is called before matrices are turned into concrete environments.

Source code in src/hatch/env/collectors/plugin/interface.py
def finalize_config(self, config: dict[str, dict]):
+    """
+    Finalizes configuration for environments keyed by the environment or matrix name. This will override
+    any user-defined settings and any collectors that ran before this call.
+
+    This is called before matrices are turned into concrete environments.
+    """
+

finalize_environments(config: dict[str, dict])

Finalizes configuration for environments keyed by the environment name. This will override any user-defined settings and any collectors that ran before this call.

This is called after matrices are turned into concrete environments.

Source code in src/hatch/env/collectors/plugin/interface.py
def finalize_environments(self, config: dict[str, dict]):
+    """
+    Finalizes configuration for environments keyed by the environment name. This will override
+    any user-defined settings and any collectors that ran before this call.
+
+    This is called after matrices are turned into concrete environments.
+    """
+
\ No newline at end of file diff --git a/1.13/plugins/environment/index.html b/1.13/plugins/environment/index.html new file mode 100644 index 000000000..450e873c1 --- /dev/null +++ b/1.13/plugins/environment/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/plugins/environment/reference/index.html b/1.13/plugins/environment/reference/index.html new file mode 100644 index 000000000..e160c13ed --- /dev/null +++ b/1.13/plugins/environment/reference/index.html @@ -0,0 +1,1444 @@ + Environment plugins - Hatch

Environment plugins


See the documentation for environment configuration.

Known third-party

Installation

Any required environment types that are not built-in must be manually installed alongside Hatch or listed in the tool.hatch.env.requires array for automatic management:

[tool.hatch.env]
+requires = [
+  "...",
+]
+
[env]
+requires = [
+  "...",
+]
+

Life cycle

Whenever an environment is used, the following logic is performed:

Source code in src/hatch/cli/application.py
def prepare_environment(self, environment: EnvironmentInterface):
+    if not environment.exists():
+        self.env_metadata.reset(environment)
+
+        with environment.app_status_creation():
+            environment.create()
+
+        if not environment.skip_install:
+            if environment.pre_install_commands:
+                with environment.app_status_pre_installation():
+                    self.run_shell_commands(
+                        ExecutionContext(
+                            environment,
+                            shell_commands=environment.pre_install_commands,
+                            source='pre-install',
+                            show_code_on_error=True,
+                        )
+                    )
+
+            with environment.app_status_project_installation():
+                if environment.dev_mode:
+                    environment.install_project_dev_mode()
+                else:
+                    environment.install_project()
+
+            if environment.post_install_commands:
+                with environment.app_status_post_installation():
+                    self.run_shell_commands(
+                        ExecutionContext(
+                            environment,
+                            shell_commands=environment.post_install_commands,
+                            source='post-install',
+                            show_code_on_error=True,
+                        )
+                    )
+
+    with environment.app_status_dependency_state_check():
+        new_dep_hash = environment.dependency_hash()
+
+    current_dep_hash = self.env_metadata.dependency_hash(environment)
+    if new_dep_hash != current_dep_hash:
+        with environment.app_status_dependency_installation_check():
+            dependencies_in_sync = environment.dependencies_in_sync()
+
+        if not dependencies_in_sync:
+            with environment.app_status_dependency_synchronization():
+                environment.sync_dependencies()
+                new_dep_hash = environment.dependency_hash()
+
+        self.env_metadata.update_dependency_hash(environment, new_dep_hash)
+

Build environments

All environment types should offer support for a special sub-environment in which projects can be built. This environment is used in the following scenarios:

EnvironmentInterface

Example usage:

    from hatch.env.plugin.interface import EnvironmentInterface
+
+
+    class SpecialEnvironment(EnvironmentInterface):
+        PLUGIN_NAME = 'special'
+        ...
+
    from hatchling.plugin import hookimpl
+
+    from .plugin import SpecialEnvironment
+
+
+    @hookimpl
+    def hatch_register_environment():
+        return SpecialEnvironment
+
Source code in src/hatch/env/plugin/interface.py
class EnvironmentInterface(ABC):
+    """
+    Example usage:
+
+    ```python tab="plugin.py"
+        from hatch.env.plugin.interface import EnvironmentInterface
+
+
+        class SpecialEnvironment(EnvironmentInterface):
+            PLUGIN_NAME = 'special'
+            ...
+    ```
+
+    ```python tab="hooks.py"
+        from hatchling.plugin import hookimpl
+
+        from .plugin import SpecialEnvironment
+
+
+        @hookimpl
+        def hatch_register_environment():
+            return SpecialEnvironment
+    ```
+    """
+
+    PLUGIN_NAME = ''
+    """The name used for selection."""
+
+    def __init__(
+        self,
+        root,
+        metadata,
+        name,
+        config,
+        matrix_variables,
+        data_directory,
+        isolated_data_directory,
+        platform,
+        verbosity,
+        app=None,
+    ):
+        self.__root = root
+        self.__metadata = metadata
+        self.__name = name
+        self.__config = config
+        self.__matrix_variables = matrix_variables
+        self.__data_directory = data_directory
+        self.__isolated_data_directory = isolated_data_directory
+        self.__platform = platform
+        self.__verbosity = verbosity
+        self.__app = app
+        self.__context = None
+
+        self._system_python = None
+        self._env_vars = None
+        self._env_include = None
+        self._env_exclude = None
+        self._environment_dependencies_complex = None
+        self._environment_dependencies = None
+        self._dependencies_complex = None
+        self._dependencies = None
+        self._platforms = None
+        self._skip_install = None
+        self._dev_mode = None
+        self._features = None
+        self._description = None
+        self._scripts = None
+        self._pre_install_commands = None
+        self._post_install_commands = None
+
+    @property
+    def matrix_variables(self):
+        return self.__matrix_variables
+
+    @property
+    def app(self):
+        """
+        An instance of [Application](../utilities.md#hatchling.bridge.app.Application).
+        """
+        if self.__app is None:
+            from hatchling.bridge.app import Application
+
+            self.__app = Application().get_safe_application()
+
+        return self.__app
+
+    @property
+    def context(self):
+        if self.__context is None:
+            self.__context = self.get_context()
+
+        return self.__context
+
+    @property
+    def verbosity(self):
+        return self.__verbosity
+
+    @property
+    def root(self):
+        """
+        The root of the project tree as a path-like object.
+        """
+        return self.__root
+
+    @property
+    def metadata(self):
+        return self.__metadata
+
+    @property
+    def name(self) -> str:
+        """
+        The name of the environment.
+        """
+        return self.__name
+
+    @property
+    def platform(self):
+        """
+        An instance of [Platform](../utilities.md#hatch.utils.platform.Platform).
+        """
+        return self.__platform
+
+    @property
+    def data_directory(self):
+        """
+        The [directory](../../config/hatch.md#environments) this plugin should use for storage as a path-like object.
+        If the user has not configured one then this will be the same as the
+        [isolated data directory](reference.md#hatch.env.plugin.interface.EnvironmentInterface.isolated_data_directory).
+        """
+        return self.__data_directory
+
+    @property
+    def isolated_data_directory(self):
+        """
+        The default [directory](../../config/hatch.md#environments) reserved exclusively for this plugin as a path-like
+        object.
+        """
+        return self.__isolated_data_directory
+
+    @property
+    def config(self) -> dict:
+        """
+        ```toml config-example
+        [tool.hatch.envs.<ENV_NAME>]
+        ```
+        """
+        return self.__config
+
+    @property
+    def system_python(self):
+        if self._system_python is None:
+            system_python = os.environ.get(AppEnvVars.PYTHON)
+            if system_python == 'self':
+                system_python = sys.executable
+
+            system_python = (
+                system_python
+                or self.platform.modules.shutil.which('python')
+                or self.platform.modules.shutil.which('python3')
+                or sys.executable
+            )
+            if not isabs(system_python):
+                system_python = self.platform.modules.shutil.which(system_python)
+
+            self._system_python = system_python
+
+        return self._system_python
+
+    @property
+    def env_vars(self) -> dict:
+        """
+        ```toml config-example
+        [tool.hatch.envs.<ENV_NAME>.env-vars]
+        ```
+        """
+        if self._env_vars is None:
+            env_vars = self.config.get('env-vars', {})
+            if not isinstance(env_vars, dict):
+                message = f'Field `tool.hatch.envs.{self.name}.env-vars` must be a mapping'
+                raise TypeError(message)
+
+            for key, value in env_vars.items():
+                if not isinstance(value, str):
+                    message = (
+                        f'Environment variable `{key}` of field `tool.hatch.envs.{self.name}.env-vars` must be a string'
+                    )
+                    raise TypeError(message)
+
+            new_env_vars = {}
+            with self.metadata.context.apply_context(self.context):
+                for key, value in env_vars.items():
+                    new_env_vars[key] = self.metadata.context.format(value)
+
+            new_env_vars[AppEnvVars.ENV_ACTIVE] = self.name
+            self._env_vars = new_env_vars
+
+        return self._env_vars
+
+    @property
+    def env_include(self) -> list[str]:
+        """
+        ```toml config-example
+        [tool.hatch.envs.<ENV_NAME>]
+        env-include = [...]
+        ```
+        """
+        if self._env_include is None:
+            env_include = self.config.get('env-include', [])
+            if not isinstance(env_include, list):
+                message = f'Field `tool.hatch.envs.{self.name}.env-include` must be an array'
+                raise TypeError(message)
+
+            for i, pattern in enumerate(env_include, 1):
+                if not isinstance(pattern, str):
+                    message = f'Pattern #{i} of field `tool.hatch.envs.{self.name}.env-include` must be a string'
+                    raise TypeError(message)
+
+            if env_include:
+                self._env_include = ['HATCH_BUILD_*', *env_include]
+            else:
+                self._env_include = env_include
+
+        return self._env_include
+
+    @property
+    def env_exclude(self) -> list[str]:
+        """
+        ```toml config-example
+        [tool.hatch.envs.<ENV_NAME>]
+        env-exclude = [...]
+        ```
+        """
+        if self._env_exclude is None:
+            env_exclude = self.config.get('env-exclude', [])
+            if not isinstance(env_exclude, list):
+                message = f'Field `tool.hatch.envs.{self.name}.env-exclude` must be an array'
+                raise TypeError(message)
+
+            for i, pattern in enumerate(env_exclude, 1):
+                if not isinstance(pattern, str):
+                    message = f'Pattern #{i} of field `tool.hatch.envs.{self.name}.env-exclude` must be a string'
+                    raise TypeError(message)
+
+            self._env_exclude = env_exclude
+
+        return self._env_exclude
+
+    @property
+    def environment_dependencies_complex(self):
+        if self._environment_dependencies_complex is None:
+            from packaging.requirements import InvalidRequirement, Requirement
+
+            dependencies_complex = []
+            with self.apply_context():
+                for option in ('dependencies', 'extra-dependencies'):
+                    dependencies = self.config.get(option, [])
+                    if not isinstance(dependencies, list):
+                        message = f'Field `tool.hatch.envs.{self.name}.{option}` must be an array'
+                        raise TypeError(message)
+
+                    for i, entry in enumerate(dependencies, 1):
+                        if not isinstance(entry, str):
+                            message = (
+                                f'Dependency #{i} of field `tool.hatch.envs.{self.name}.{option}` must be a string'
+                            )
+                            raise TypeError(message)
+
+                        try:
+                            dependencies_complex.append(Requirement(self.metadata.context.format(entry)))
+                        except InvalidRequirement as e:
+                            message = f'Dependency #{i} of field `tool.hatch.envs.{self.name}.{option}` is invalid: {e}'
+                            raise ValueError(message) from None
+
+            self._environment_dependencies_complex = dependencies_complex
+
+        return self._environment_dependencies_complex
+
+    @property
+    def environment_dependencies(self) -> list[str]:
+        """
+        The list of all [environment dependencies](../../config/environment/overview.md#dependencies).
+        """
+        if self._environment_dependencies is None:
+            self._environment_dependencies = [str(dependency) for dependency in self.environment_dependencies_complex]
+
+        return self._environment_dependencies
+
+    @property
+    def dependencies_complex(self):
+        if self._dependencies_complex is None:
+            all_dependencies_complex = list(self.environment_dependencies_complex)
+
+            # Ensure these are checked last to speed up initial environment creation since
+            # they will already be installed along with the project
+            if (not self.skip_install and self.dev_mode) or self.features:
+                from hatch.utils.dep import get_project_dependencies_complex
+
+                dependencies_complex, optional_dependencies_complex = get_project_dependencies_complex(self)
+
+                if not self.skip_install and self.dev_mode:
+                    all_dependencies_complex.extend(dependencies_complex.values())
+
+                for feature in self.features:
+                    if feature not in optional_dependencies_complex:
+                        message = (
+                            f'Feature `{feature}` of field `tool.hatch.envs.{self.name}.features` is not '
+                            f'defined in the dynamic field `project.optional-dependencies`'
+                        )
+                        raise ValueError(message)
+
+                    all_dependencies_complex.extend(optional_dependencies_complex[feature].values())
+
+            self._dependencies_complex = all_dependencies_complex
+
+        return self._dependencies_complex
+
+    @property
+    def dependencies(self) -> list[str]:
+        """
+        The list of all [project dependencies](../../config/metadata.md#dependencies) (if
+        [installed](../../config/environment/overview.md#skip-install) and in
+        [dev mode](../../config/environment/overview.md#dev-mode)), selected
+        [optional dependencies](../../config/environment/overview.md#features), and
+        [environment dependencies](../../config/environment/overview.md#dependencies).
+        """
+        if self._dependencies is None:
+            self._dependencies = [str(dependency) for dependency in self.dependencies_complex]
+
+        return self._dependencies
+
+    @property
+    def platforms(self) -> list[str]:
+        """
+        All names are stored as their lower-cased version.
+
+        ```toml config-example
+        [tool.hatch.envs.<ENV_NAME>]
+        platforms = [...]
+        ```
+        """
+        if self._platforms is None:
+            platforms = self.config.get('platforms', [])
+            if not isinstance(platforms, list):
+                message = f'Field `tool.hatch.envs.{self.name}.platforms` must be an array'
+                raise TypeError(message)
+
+            for i, command in enumerate(platforms, 1):
+                if not isinstance(command, str):
+                    message = f'Platform #{i} of field `tool.hatch.envs.{self.name}.platforms` must be a string'
+                    raise TypeError(message)
+
+            self._platforms = [platform.lower() for platform in platforms]
+
+        return self._platforms
+
+    @property
+    def skip_install(self) -> bool:
+        """
+        ```toml config-example
+        [tool.hatch.envs.<ENV_NAME>]
+        skip-install = ...
+        ```
+        """
+        if self._skip_install is None:
+            skip_install = self.config.get('skip-install', not self.metadata.has_project_file())
+            if not isinstance(skip_install, bool):
+                message = f'Field `tool.hatch.envs.{self.name}.skip-install` must be a boolean'
+                raise TypeError(message)
+
+            self._skip_install = skip_install
+
+        return self._skip_install
+
+    @property
+    def dev_mode(self) -> bool:
+        """
+        ```toml config-example
+        [tool.hatch.envs.<ENV_NAME>]
+        dev-mode = ...
+        ```
+        """
+        if self._dev_mode is None:
+            dev_mode = self.config.get('dev-mode', True)
+            if not isinstance(dev_mode, bool):
+                message = f'Field `tool.hatch.envs.{self.name}.dev-mode` must be a boolean'
+                raise TypeError(message)
+
+            self._dev_mode = dev_mode
+
+        return self._dev_mode
+
+    @property
+    def features(self):
+        if self._features is None:
+            from hatchling.metadata.utils import normalize_project_name
+
+            features = self.config.get('features', [])
+            if not isinstance(features, list):
+                message = f'Field `tool.hatch.envs.{self.name}.features` must be an array of strings'
+                raise TypeError(message)
+
+            all_features = set()
+            for i, feature in enumerate(features, 1):
+                if not isinstance(feature, str):
+                    message = f'Feature #{i} of field `tool.hatch.envs.{self.name}.features` must be a string'
+                    raise TypeError(message)
+
+                if not feature:
+                    message = f'Feature #{i} of field `tool.hatch.envs.{self.name}.features` cannot be an empty string'
+                    raise ValueError(message)
+
+                normalized_feature = (
+                    feature
+                    if self.metadata.hatch.metadata.allow_ambiguous_features
+                    else normalize_project_name(feature)
+                )
+                if (
+                    not self.metadata.hatch.metadata.hook_config
+                    and normalized_feature not in self.metadata.core.optional_dependencies
+                ):
+                    message = (
+                        f'Feature `{normalized_feature}` of field `tool.hatch.envs.{self.name}.features` is not '
+                        f'defined in field `project.optional-dependencies`'
+                    )
+                    raise ValueError(message)
+
+                all_features.add(normalized_feature)
+
+            self._features = sorted(all_features)
+
+        return self._features
+
+    @property
+    def description(self) -> str:
+        """
+        ```toml config-example
+        [tool.hatch.envs.<ENV_NAME>]
+        description = ...
+        ```
+        """
+        if self._description is None:
+            description = self.config.get('description', '')
+            if not isinstance(description, str):
+                message = f'Field `tool.hatch.envs.{self.name}.description` must be a string'
+                raise TypeError(message)
+
+            self._description = description
+
+        return self._description
+
+    @property
+    def scripts(self):
+        if self._scripts is None:
+            config = {}
+
+            # Extra scripts should come first to give less precedence
+            for field in ('extra-scripts', 'scripts'):
+                script_config = self.config.get(field, {})
+                if not isinstance(script_config, dict):
+                    message = f'Field `tool.hatch.envs.{self.name}.{field}` must be a table'
+                    raise TypeError(message)
+
+                for name, data in script_config.items():
+                    if ' ' in name:
+                        message = (
+                            f'Script name `{name}` in field `tool.hatch.envs.{self.name}.{field}` '
+                            f'must not contain spaces'
+                        )
+                        raise ValueError(message)
+
+                    commands = []
+
+                    if isinstance(data, str):
+                        commands.append(data)
+                    elif isinstance(data, list):
+                        for i, command in enumerate(data, 1):
+                            if not isinstance(command, str):
+                                message = (
+                                    f'Command #{i} in field `tool.hatch.envs.{self.name}.{field}.{name}` '
+                                    f'must be a string'
+                                )
+                                raise TypeError(message)
+
+                            commands.append(command)
+                    else:
+                        message = (
+                            f'Field `tool.hatch.envs.{self.name}.{field}.{name}` must be '
+                            f'a string or an array of strings'
+                        )
+                        raise TypeError(message)
+
+                    config[name] = commands
+
+            seen = {}
+            active = []
+            for script_name, commands in config.items():
+                commands[:] = expand_script_commands(self.name, script_name, commands, config, seen, active)
+
+            self._scripts = config
+
+        return self._scripts
+
+    @property
+    def pre_install_commands(self):
+        if self._pre_install_commands is None:
+            pre_install_commands = self.config.get('pre-install-commands', [])
+            if not isinstance(pre_install_commands, list):
+                message = f'Field `tool.hatch.envs.{self.name}.pre-install-commands` must be an array'
+                raise TypeError(message)
+
+            for i, command in enumerate(pre_install_commands, 1):
+                if not isinstance(command, str):
+                    message = (
+                        f'Command #{i} of field `tool.hatch.envs.{self.name}.pre-install-commands` must be a string'
+                    )
+                    raise TypeError(message)
+
+            self._pre_install_commands = list(pre_install_commands)
+
+        return self._pre_install_commands
+
+    @property
+    def post_install_commands(self):
+        if self._post_install_commands is None:
+            post_install_commands = self.config.get('post-install-commands', [])
+            if not isinstance(post_install_commands, list):
+                message = f'Field `tool.hatch.envs.{self.name}.post-install-commands` must be an array'
+                raise TypeError(message)
+
+            for i, command in enumerate(post_install_commands, 1):
+                if not isinstance(command, str):
+                    message = (
+                        f'Command #{i} of field `tool.hatch.envs.{self.name}.post-install-commands` must be a string'
+                    )
+                    raise TypeError(message)
+
+            self._post_install_commands = list(post_install_commands)
+
+        return self._post_install_commands
+
+    def activate(self):
+        """
+        A convenience method called when using the environment as a context manager:
+
+        ```python
+        with environment:
+            ...
+        ```
+        """
+
+    def deactivate(self):
+        """
+        A convenience method called after using the environment as a context manager:
+
+        ```python
+        with environment:
+            ...
+        ```
+        """
+
+    @abstractmethod
+    def find(self):
+        """
+        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+        This should return information about how to locate the environment or represent its ID in
+        some way. Additionally, this is expected to return something even if the environment is
+        [incompatible](reference.md#hatch.env.plugin.interface.EnvironmentInterface.check_compatibility).
+        """
+
+    @abstractmethod
+    def create(self):
+        """
+        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+        This should perform the necessary steps to set up the environment.
+        """
+
+    @abstractmethod
+    def remove(self):
+        """
+        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+        This should perform the necessary steps to completely remove the environment from the system and will only
+        be triggered manually by users with the [`env remove`](../../cli/reference.md#hatch-env-remove) or
+        [`env prune`](../../cli/reference.md#hatch-env-prune) commands.
+
+        If the
+        [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)
+        has a caching mechanism, this should remove that as well.
+        """
+
+    @abstractmethod
+    def exists(self) -> bool:
+        """
+        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+        This should indicate whether or not the environment has already been created.
+        """
+
+    @abstractmethod
+    def install_project(self):
+        """
+        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+        This should install the project in the environment.
+        """
+
+    @abstractmethod
+    def install_project_dev_mode(self):
+        """
+        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+        This should install the project in the environment such that the environment
+        always reflects the current state of the project.
+        """
+
+    @abstractmethod
+    def dependencies_in_sync(self) -> bool:
+        """
+        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+        This should indicate whether or not the environment is compatible with the current
+        [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies).
+        """
+
+    @abstractmethod
+    def sync_dependencies(self):
+        """
+        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+        This should install the
+        [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies)
+        in the environment.
+        """
+
+    def dependency_hash(self):
+        """
+        This should return a hash of the environment's
+        [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies)
+        and any other data that is handled by the
+        [sync_dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.sync_dependencies)
+        and
+        [dependencies_in_sync](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies_in_sync)
+        methods.
+        """
+        from hatch.utils.dep import hash_dependencies
+
+        return hash_dependencies(self.dependencies_complex)
+
+    @contextmanager
+    def app_status_creation(self):
+        """
+        See the [life cycle of environments](reference.md#life-cycle).
+        """
+        with self.app.status(f'Creating environment: {self.name}'):
+            yield
+
+    @contextmanager
+    def app_status_pre_installation(self):
+        """
+        See the [life cycle of environments](reference.md#life-cycle).
+        """
+        with self.app.status('Running pre-installation commands'):
+            yield
+
+    @contextmanager
+    def app_status_post_installation(self):
+        """
+        See the [life cycle of environments](reference.md#life-cycle).
+        """
+        with self.app.status('Running post-installation commands'):
+            yield
+
+    @contextmanager
+    def app_status_project_installation(self):
+        """
+        See the [life cycle of environments](reference.md#life-cycle).
+        """
+        if self.dev_mode:
+            with self.app.status('Installing project in development mode'):
+                yield
+        else:
+            with self.app.status('Installing project'):
+                yield
+
+    @contextmanager
+    def app_status_dependency_state_check(self):
+        """
+        See the [life cycle of environments](reference.md#life-cycle).
+        """
+        if not self.skip_install and (
+            'dependencies' in self.metadata.dynamic or 'optional-dependencies' in self.metadata.dynamic
+        ):
+            with self.app.status('Polling dependency state'):
+                yield
+        else:
+            yield
+
+    @contextmanager
+    def app_status_dependency_installation_check(self):
+        """
+        See the [life cycle of environments](reference.md#life-cycle).
+        """
+        with self.app.status('Checking dependencies'):
+            yield
+
+    @contextmanager
+    def app_status_dependency_synchronization(self):
+        """
+        See the [life cycle of environments](reference.md#life-cycle).
+        """
+        with self.app.status('Syncing dependencies'):
+            yield
+
+    @contextmanager
+    def build_environment(
+        self,
+        dependencies: list[str],  # noqa: ARG002
+    ):
+        """
+        This should set up an isolated environment in which to [`build`](../../cli/reference.md#hatch-build) the project
+        given a set of dependencies and must be a context manager:
+
+        ```python
+        with environment.build_environment([...]):
+            ...
+        ```
+
+        The build environment should reflect any
+        [environment variables](reference.md#hatch.env.plugin.interface.EnvironmentInterface.get_env_vars)
+        the user defined either currently or at the time of
+        [creation](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).
+        """
+        with self.get_env_vars():
+            yield
+
+    def run_builder(
+        self,
+        build_environment,  # noqa: ARG002
+        **kwargs,
+    ):
+        """
+        This will be called when the
+        [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)
+        is active:
+
+        ```python
+        with environment.build_environment([...]) as build_env:
+            process = environment.run_builder(build_env, ...)
+        ```
+
+        This should return the standard library's
+        [subprocess.CompletedProcess](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess).
+        The command is constructed by passing all keyword arguments to
+        [construct_build_command](reference.md#hatch.env.plugin.interface.EnvironmentInterface.construct_build_command).
+
+        For an example, open the default implementation below:
+        """
+        return self.platform.run_command(self.construct_build_command(**kwargs))
+
+    def build_environment_exists(self):  # noqa: PLR6301
+        """
+        If the
+        [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)
+        has a caching mechanism, this should indicate whether or not it has already been created.
+        """
+        return False
+
+    def enter_shell(
+        self,
+        name: str,  # noqa: ARG002
+        path: str,
+        args: Iterable[str],
+    ):
+        """
+        Spawn a [shell](../../config/hatch.md#shell) within the environment.
+
+        This should either use
+        [command_context](reference.md#hatch.env.plugin.interface.EnvironmentInterface.command_context)
+        directly or provide the same guarantee.
+        """
+        with self.command_context():
+            self.platform.exit_with_command([path, *args])
+
+    def run_shell_command(self, command: str, **kwargs):
+        """
+        This should return the standard library's
+        [subprocess.CompletedProcess](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess)
+        and will always be called when the
+        [command_context](reference.md#hatch.env.plugin.interface.EnvironmentInterface.command_context)
+        is active, with the expectation of providing the same guarantee.
+        """
+        kwargs.setdefault('shell', True)
+        return self.platform.run_command(command, **kwargs)
+
+    @contextmanager
+    def command_context(self):
+        """
+        A context manager that when active should make executed shell commands reflect any
+        [environment variables](reference.md#hatch.env.plugin.interface.EnvironmentInterface.get_env_vars)
+        the user defined either currently or at the time of
+        [creation](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).
+
+        For an example, open the default implementation below:
+        """
+        with self.get_env_vars():
+            yield
+
+    def resolve_commands(self, commands: list[str]):
+        """
+        This expands each command into one or more commands based on any
+        [scripts](../../config/environment/overview.md#scripts) that the user defined.
+        """
+        for command in commands:
+            yield from self.expand_command(command)
+
+    def expand_command(self, command):
+        possible_script, args, _ignore_exit_code = parse_script_command(command)
+
+        # Indicate undefined
+        if not args:
+            args = None
+
+        with self.apply_context():
+            if possible_script in self.scripts:
+                if args is not None:
+                    args = self.metadata.context.format(args)
+
+                for cmd in self.scripts[possible_script]:
+                    yield self.metadata.context.format(cmd, args=args).strip()
+            else:
+                yield self.metadata.context.format(command, args=args).strip()
+
+    def construct_build_command(  # noqa: PLR6301
+        self,
+        *,
+        directory=None,
+        targets=(),
+        hooks_only=False,
+        no_hooks=False,
+        clean=False,
+        clean_hooks_after=False,
+        clean_only=False,
+    ):
+        """
+        This is the canonical way [`build`](../../cli/reference.md#hatch-build) command options are translated to
+        a subprocess command issued to [builders](../builder/reference.md).
+        """
+        command = ['python', '-u', '-m', 'hatchling', 'build']
+
+        if directory:
+            command.extend(('--directory', directory))
+
+        if targets:
+            for target in targets:
+                command.extend(('--target', target))
+
+        if hooks_only:
+            command.append('--hooks-only')
+
+        if no_hooks:
+            command.append('--no-hooks')
+
+        if clean:
+            command.append('--clean')
+
+        if clean_hooks_after:
+            command.append('--clean-hooks-after')
+
+        if clean_only:
+            command.append('--clean-only')
+
+        return command
+
+    def construct_pip_install_command(self, args: list[str]):
+        """
+        A convenience method for constructing a [`pip install`](https://pip.pypa.io/en/stable/cli/pip_install/)
+        command with the given verbosity. The default verbosity is set to one less than Hatch's verbosity.
+        """
+        command = ['python', '-u', '-m', 'pip', 'install', '--disable-pip-version-check', '--no-python-version-warning']
+
+        # Default to -1 verbosity
+        add_verbosity_flag(command, self.verbosity, adjustment=-1)
+
+        command.extend(args)
+        return command
+
+    def join_command_args(self, args: list[str]):
+        """
+        This is used by the [`run`](../../cli/reference.md#hatch-run) command to construct the root command string
+        from the received arguments.
+        """
+        return self.platform.join_command_args(args)
+
+    def apply_features(self, requirement: str):
+        """
+        A convenience method that applies any user defined [features](../../config/environment/overview.md#features)
+        to the given requirement.
+        """
+        if self.features:
+            features = ','.join(self.features)
+            return f'{requirement}[{features}]'
+
+        return requirement
+
+    def check_compatibility(self):
+        """
+        This raises an exception if the environment is not compatible with the user's setup. The default behavior
+        checks for [platform compatibility](../../config/environment/overview.md#supported-platforms)
+        and any method override should keep this check.
+
+        This check is never performed if the environment has been
+        [created](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).
+        """
+        if self.platforms and self.platform.name not in self.platforms:
+            message = 'unsupported platform'
+            raise OSError(message)
+
+    def get_env_vars(self) -> EnvVars:
+        """
+        Returns a mapping of environment variables that should be available to the environment. The object can
+        be used as a context manager to temporarily apply the environment variables to the current process.
+
+        !!! note
+            The environment variable `HATCH_ENV_ACTIVE` will always be set to the name of the environment.
+        """
+        return EnvVars(self.env_vars, self.env_include, self.env_exclude)
+
+    def get_env_var_option(self, option: str) -> str:
+        """
+        Returns the value of the upper-cased environment variable `HATCH_ENV_TYPE_<PLUGIN_NAME>_<option>`.
+        """
+        return get_env_var_option(plugin_name=self.PLUGIN_NAME, option=option)
+
+    def get_context(self):
+        """
+        Returns a subclass of
+        [EnvironmentContextFormatter](../utilities.md#hatch.env.context.EnvironmentContextFormatter).
+        """
+        from hatch.env.context import EnvironmentContextFormatter
+
+        return EnvironmentContextFormatter(self)
+
+    @staticmethod
+    def get_option_types() -> dict:
+        """
+        Returns a mapping of supported options to their respective types so that they can be used by
+        [overrides](../../config/environment/advanced.md#option-overrides).
+        """
+        return {}
+
+    @contextmanager
+    def apply_context(self):
+        with self.get_env_vars(), self.metadata.context.apply_context(self.context):
+            yield
+
+    def __enter__(self):
+        self.activate()
+        return self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        self.deactivate()
+

PLUGIN_NAME = '' class-attribute instance-attribute

The name used for selection.

app property

An instance of Application.

root property

The root of the project tree as a path-like object.

name: str property

The name of the environment.

data_directory property

The directory this plugin should use for storage as a path-like object. If the user has not configured one then this will be the same as the isolated data directory.

isolated_data_directory property

The default directory reserved exclusively for this plugin as a path-like object.

config: dict property

[tool.hatch.envs.<ENV_NAME>]
+
[envs.<ENV_NAME>]
+

platform property

An instance of Platform.

environment_dependencies: list[str] property

The list of all environment dependencies.

dependencies: list[str] property

env_vars: dict property

[tool.hatch.envs.<ENV_NAME>.env-vars]
+
[envs.<ENV_NAME>.env-vars]
+

env_include: list[str] property

[tool.hatch.envs.<ENV_NAME>]
+env-include = [...]
+
[envs.<ENV_NAME>]
+env-include = [...]
+

env_exclude: list[str] property

[tool.hatch.envs.<ENV_NAME>]
+env-exclude = [...]
+
[envs.<ENV_NAME>]
+env-exclude = [...]
+

platforms: list[str] property

All names are stored as their lower-cased version.

[tool.hatch.envs.<ENV_NAME>]
+platforms = [...]
+
[envs.<ENV_NAME>]
+platforms = [...]
+

skip_install: bool property

[tool.hatch.envs.<ENV_NAME>]
+skip-install = ...
+
[envs.<ENV_NAME>]
+skip-install = ...
+

dev_mode: bool property

[tool.hatch.envs.<ENV_NAME>]
+dev-mode = ...
+
[envs.<ENV_NAME>]
+dev-mode = ...
+

description: str property

[tool.hatch.envs.<ENV_NAME>]
+description = ...
+
[envs.<ENV_NAME>]
+description = ...
+

find() abstractmethod

REQUIRED

This should return information about how to locate the environment or represent its ID in some way. Additionally, this is expected to return something even if the environment is incompatible.

Source code in src/hatch/env/plugin/interface.py
@abstractmethod
+def find(self):
+    """
+    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+    This should return information about how to locate the environment or represent its ID in
+    some way. Additionally, this is expected to return something even if the environment is
+    [incompatible](reference.md#hatch.env.plugin.interface.EnvironmentInterface.check_compatibility).
+    """
+

create() abstractmethod

REQUIRED

This should perform the necessary steps to set up the environment.

Source code in src/hatch/env/plugin/interface.py
@abstractmethod
+def create(self):
+    """
+    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+    This should perform the necessary steps to set up the environment.
+    """
+

remove() abstractmethod

REQUIRED

This should perform the necessary steps to completely remove the environment from the system and will only be triggered manually by users with the env remove or env prune commands.

If the build environment has a caching mechanism, this should remove that as well.

Source code in src/hatch/env/plugin/interface.py
@abstractmethod
+def remove(self):
+    """
+    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+    This should perform the necessary steps to completely remove the environment from the system and will only
+    be triggered manually by users with the [`env remove`](../../cli/reference.md#hatch-env-remove) or
+    [`env prune`](../../cli/reference.md#hatch-env-prune) commands.
+
+    If the
+    [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)
+    has a caching mechanism, this should remove that as well.
+    """
+

exists() -> bool abstractmethod

REQUIRED

This should indicate whether or not the environment has already been created.

Source code in src/hatch/env/plugin/interface.py
@abstractmethod
+def exists(self) -> bool:
+    """
+    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+    This should indicate whether or not the environment has already been created.
+    """
+

install_project() abstractmethod

REQUIRED

This should install the project in the environment.

Source code in src/hatch/env/plugin/interface.py
@abstractmethod
+def install_project(self):
+    """
+    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+    This should install the project in the environment.
+    """
+

install_project_dev_mode() abstractmethod

REQUIRED

This should install the project in the environment such that the environment always reflects the current state of the project.

Source code in src/hatch/env/plugin/interface.py
@abstractmethod
+def install_project_dev_mode(self):
+    """
+    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+    This should install the project in the environment such that the environment
+    always reflects the current state of the project.
+    """
+

dependencies_in_sync() -> bool abstractmethod

REQUIRED

This should indicate whether or not the environment is compatible with the current dependencies.

Source code in src/hatch/env/plugin/interface.py
@abstractmethod
+def dependencies_in_sync(self) -> bool:
+    """
+    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+    This should indicate whether or not the environment is compatible with the current
+    [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies).
+    """
+

sync_dependencies() abstractmethod

REQUIRED

This should install the dependencies in the environment.

Source code in src/hatch/env/plugin/interface.py
@abstractmethod
+def sync_dependencies(self):
+    """
+    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+    This should install the
+    [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies)
+    in the environment.
+    """
+

dependency_hash()

This should return a hash of the environment's dependencies and any other data that is handled by the sync_dependencies and dependencies_in_sync methods.

Source code in src/hatch/env/plugin/interface.py
def dependency_hash(self):
+    """
+    This should return a hash of the environment's
+    [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies)
+    and any other data that is handled by the
+    [sync_dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.sync_dependencies)
+    and
+    [dependencies_in_sync](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies_in_sync)
+    methods.
+    """
+    from hatch.utils.dep import hash_dependencies
+
+    return hash_dependencies(self.dependencies_complex)
+

build_environment(dependencies: list[str])

This should set up an isolated environment in which to build the project given a set of dependencies and must be a context manager:

with environment.build_environment([...]):
+    ...
+

The build environment should reflect any environment variables the user defined either currently or at the time of creation.

Source code in src/hatch/env/plugin/interface.py
@contextmanager
+def build_environment(
+    self,
+    dependencies: list[str],  # noqa: ARG002
+):
+    """
+    This should set up an isolated environment in which to [`build`](../../cli/reference.md#hatch-build) the project
+    given a set of dependencies and must be a context manager:
+
+    ```python
+    with environment.build_environment([...]):
+        ...
+    ```
+
+    The build environment should reflect any
+    [environment variables](reference.md#hatch.env.plugin.interface.EnvironmentInterface.get_env_vars)
+    the user defined either currently or at the time of
+    [creation](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).
+    """
+    with self.get_env_vars():
+        yield
+

build_environment_exists()

If the build environment has a caching mechanism, this should indicate whether or not it has already been created.

Source code in src/hatch/env/plugin/interface.py
def build_environment_exists(self):  # noqa: PLR6301
+    """
+    If the
+    [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)
+    has a caching mechanism, this should indicate whether or not it has already been created.
+    """
+    return False
+

activate()

A convenience method called when using the environment as a context manager:

with environment:
+    ...
+
Source code in src/hatch/env/plugin/interface.py
def activate(self):
+    """
+    A convenience method called when using the environment as a context manager:
+
+    ```python
+    with environment:
+        ...
+    ```
+    """
+

deactivate()

A convenience method called after using the environment as a context manager:

with environment:
+    ...
+
Source code in src/hatch/env/plugin/interface.py
def deactivate(self):
+    """
+    A convenience method called after using the environment as a context manager:
+
+    ```python
+    with environment:
+        ...
+    ```
+    """
+

app_status_creation()

See the life cycle of environments.

Source code in src/hatch/env/plugin/interface.py
@contextmanager
+def app_status_creation(self):
+    """
+    See the [life cycle of environments](reference.md#life-cycle).
+    """
+    with self.app.status(f'Creating environment: {self.name}'):
+        yield
+

app_status_pre_installation()

See the life cycle of environments.

Source code in src/hatch/env/plugin/interface.py
@contextmanager
+def app_status_pre_installation(self):
+    """
+    See the [life cycle of environments](reference.md#life-cycle).
+    """
+    with self.app.status('Running pre-installation commands'):
+        yield
+

app_status_post_installation()

See the life cycle of environments.

Source code in src/hatch/env/plugin/interface.py
@contextmanager
+def app_status_post_installation(self):
+    """
+    See the [life cycle of environments](reference.md#life-cycle).
+    """
+    with self.app.status('Running post-installation commands'):
+        yield
+

app_status_project_installation()

See the life cycle of environments.

Source code in src/hatch/env/plugin/interface.py
@contextmanager
+def app_status_project_installation(self):
+    """
+    See the [life cycle of environments](reference.md#life-cycle).
+    """
+    if self.dev_mode:
+        with self.app.status('Installing project in development mode'):
+            yield
+    else:
+        with self.app.status('Installing project'):
+            yield
+

app_status_dependency_state_check()

See the life cycle of environments.

Source code in src/hatch/env/plugin/interface.py
@contextmanager
+def app_status_dependency_state_check(self):
+    """
+    See the [life cycle of environments](reference.md#life-cycle).
+    """
+    if not self.skip_install and (
+        'dependencies' in self.metadata.dynamic or 'optional-dependencies' in self.metadata.dynamic
+    ):
+        with self.app.status('Polling dependency state'):
+            yield
+    else:
+        yield
+

app_status_dependency_installation_check()

See the life cycle of environments.

Source code in src/hatch/env/plugin/interface.py
@contextmanager
+def app_status_dependency_installation_check(self):
+    """
+    See the [life cycle of environments](reference.md#life-cycle).
+    """
+    with self.app.status('Checking dependencies'):
+        yield
+

app_status_dependency_synchronization()

See the life cycle of environments.

Source code in src/hatch/env/plugin/interface.py
@contextmanager
+def app_status_dependency_synchronization(self):
+    """
+    See the [life cycle of environments](reference.md#life-cycle).
+    """
+    with self.app.status('Syncing dependencies'):
+        yield
+

run_builder(build_environment, **kwargs)

This will be called when the build environment is active:

with environment.build_environment([...]) as build_env:
+    process = environment.run_builder(build_env, ...)
+

This should return the standard library's subprocess.CompletedProcess. The command is constructed by passing all keyword arguments to construct_build_command.

For an example, open the default implementation below:

Source code in src/hatch/env/plugin/interface.py
def run_builder(
+    self,
+    build_environment,  # noqa: ARG002
+    **kwargs,
+):
+    """
+    This will be called when the
+    [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)
+    is active:
+
+    ```python
+    with environment.build_environment([...]) as build_env:
+        process = environment.run_builder(build_env, ...)
+    ```
+
+    This should return the standard library's
+    [subprocess.CompletedProcess](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess).
+    The command is constructed by passing all keyword arguments to
+    [construct_build_command](reference.md#hatch.env.plugin.interface.EnvironmentInterface.construct_build_command).
+
+    For an example, open the default implementation below:
+    """
+    return self.platform.run_command(self.construct_build_command(**kwargs))
+

construct_build_command(*, directory=None, targets=(), hooks_only=False, no_hooks=False, clean=False, clean_hooks_after=False, clean_only=False)

This is the canonical way build command options are translated to a subprocess command issued to builders.

Source code in src/hatch/env/plugin/interface.py
def construct_build_command(  # noqa: PLR6301
+    self,
+    *,
+    directory=None,
+    targets=(),
+    hooks_only=False,
+    no_hooks=False,
+    clean=False,
+    clean_hooks_after=False,
+    clean_only=False,
+):
+    """
+    This is the canonical way [`build`](../../cli/reference.md#hatch-build) command options are translated to
+    a subprocess command issued to [builders](../builder/reference.md).
+    """
+    command = ['python', '-u', '-m', 'hatchling', 'build']
+
+    if directory:
+        command.extend(('--directory', directory))
+
+    if targets:
+        for target in targets:
+            command.extend(('--target', target))
+
+    if hooks_only:
+        command.append('--hooks-only')
+
+    if no_hooks:
+        command.append('--no-hooks')
+
+    if clean:
+        command.append('--clean')
+
+    if clean_hooks_after:
+        command.append('--clean-hooks-after')
+
+    if clean_only:
+        command.append('--clean-only')
+
+    return command
+

command_context()

A context manager that when active should make executed shell commands reflect any environment variables the user defined either currently or at the time of creation.

For an example, open the default implementation below:

Source code in src/hatch/env/plugin/interface.py
@contextmanager
+def command_context(self):
+    """
+    A context manager that when active should make executed shell commands reflect any
+    [environment variables](reference.md#hatch.env.plugin.interface.EnvironmentInterface.get_env_vars)
+    the user defined either currently or at the time of
+    [creation](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).
+
+    For an example, open the default implementation below:
+    """
+    with self.get_env_vars():
+        yield
+

enter_shell(name: str, path: str, args: Iterable[str])

Spawn a shell within the environment.

This should either use command_context directly or provide the same guarantee.

Source code in src/hatch/env/plugin/interface.py
def enter_shell(
+    self,
+    name: str,  # noqa: ARG002
+    path: str,
+    args: Iterable[str],
+):
+    """
+    Spawn a [shell](../../config/hatch.md#shell) within the environment.
+
+    This should either use
+    [command_context](reference.md#hatch.env.plugin.interface.EnvironmentInterface.command_context)
+    directly or provide the same guarantee.
+    """
+    with self.command_context():
+        self.platform.exit_with_command([path, *args])
+

run_shell_command(command: str, **kwargs)

This should return the standard library's subprocess.CompletedProcess and will always be called when the command_context is active, with the expectation of providing the same guarantee.

Source code in src/hatch/env/plugin/interface.py
def run_shell_command(self, command: str, **kwargs):
+    """
+    This should return the standard library's
+    [subprocess.CompletedProcess](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess)
+    and will always be called when the
+    [command_context](reference.md#hatch.env.plugin.interface.EnvironmentInterface.command_context)
+    is active, with the expectation of providing the same guarantee.
+    """
+    kwargs.setdefault('shell', True)
+    return self.platform.run_command(command, **kwargs)
+

resolve_commands(commands: list[str])

This expands each command into one or more commands based on any scripts that the user defined.

Source code in src/hatch/env/plugin/interface.py
def resolve_commands(self, commands: list[str]):
+    """
+    This expands each command into one or more commands based on any
+    [scripts](../../config/environment/overview.md#scripts) that the user defined.
+    """
+    for command in commands:
+        yield from self.expand_command(command)
+

get_env_vars() -> EnvVars

Returns a mapping of environment variables that should be available to the environment. The object can be used as a context manager to temporarily apply the environment variables to the current process.

Note

The environment variable HATCH_ENV_ACTIVE will always be set to the name of the environment.

Source code in src/hatch/env/plugin/interface.py
def get_env_vars(self) -> EnvVars:
+    """
+    Returns a mapping of environment variables that should be available to the environment. The object can
+    be used as a context manager to temporarily apply the environment variables to the current process.
+
+    !!! note
+        The environment variable `HATCH_ENV_ACTIVE` will always be set to the name of the environment.
+    """
+    return EnvVars(self.env_vars, self.env_include, self.env_exclude)
+

apply_features(requirement: str)

A convenience method that applies any user defined features to the given requirement.

Source code in src/hatch/env/plugin/interface.py
def apply_features(self, requirement: str):
+    """
+    A convenience method that applies any user defined [features](../../config/environment/overview.md#features)
+    to the given requirement.
+    """
+    if self.features:
+        features = ','.join(self.features)
+        return f'{requirement}[{features}]'
+
+    return requirement
+

construct_pip_install_command(args: list[str])

A convenience method for constructing a pip install command with the given verbosity. The default verbosity is set to one less than Hatch's verbosity.

Source code in src/hatch/env/plugin/interface.py
def construct_pip_install_command(self, args: list[str]):
+    """
+    A convenience method for constructing a [`pip install`](https://pip.pypa.io/en/stable/cli/pip_install/)
+    command with the given verbosity. The default verbosity is set to one less than Hatch's verbosity.
+    """
+    command = ['python', '-u', '-m', 'pip', 'install', '--disable-pip-version-check', '--no-python-version-warning']
+
+    # Default to -1 verbosity
+    add_verbosity_flag(command, self.verbosity, adjustment=-1)
+
+    command.extend(args)
+    return command
+

join_command_args(args: list[str])

This is used by the run command to construct the root command string from the received arguments.

Source code in src/hatch/env/plugin/interface.py
def join_command_args(self, args: list[str]):
+    """
+    This is used by the [`run`](../../cli/reference.md#hatch-run) command to construct the root command string
+    from the received arguments.
+    """
+    return self.platform.join_command_args(args)
+

check_compatibility()

This raises an exception if the environment is not compatible with the user's setup. The default behavior checks for platform compatibility and any method override should keep this check.

This check is never performed if the environment has been created.

Source code in src/hatch/env/plugin/interface.py
def check_compatibility(self):
+    """
+    This raises an exception if the environment is not compatible with the user's setup. The default behavior
+    checks for [platform compatibility](../../config/environment/overview.md#supported-platforms)
+    and any method override should keep this check.
+
+    This check is never performed if the environment has been
+    [created](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).
+    """
+    if self.platforms and self.platform.name not in self.platforms:
+        message = 'unsupported platform'
+        raise OSError(message)
+

get_option_types() -> dict staticmethod

Returns a mapping of supported options to their respective types so that they can be used by overrides.

Source code in src/hatch/env/plugin/interface.py
@staticmethod
+def get_option_types() -> dict:
+    """
+    Returns a mapping of supported options to their respective types so that they can be used by
+    [overrides](../../config/environment/advanced.md#option-overrides).
+    """
+    return {}
+

get_env_var_option(option: str) -> str

Returns the value of the upper-cased environment variable HATCH_ENV_TYPE_<PLUGIN_NAME>_<option>.

Source code in src/hatch/env/plugin/interface.py
def get_env_var_option(self, option: str) -> str:
+    """
+    Returns the value of the upper-cased environment variable `HATCH_ENV_TYPE_<PLUGIN_NAME>_<option>`.
+    """
+    return get_env_var_option(plugin_name=self.PLUGIN_NAME, option=option)
+

get_context()

Returns a subclass of EnvironmentContextFormatter.

Source code in src/hatch/env/plugin/interface.py
def get_context(self):
+    """
+    Returns a subclass of
+    [EnvironmentContextFormatter](../utilities.md#hatch.env.context.EnvironmentContextFormatter).
+    """
+    from hatch.env.context import EnvironmentContextFormatter
+
+    return EnvironmentContextFormatter(self)
+
\ No newline at end of file diff --git a/1.13/plugins/environment/virtual/index.html b/1.13/plugins/environment/virtual/index.html new file mode 100644 index 000000000..783327042 --- /dev/null +++ b/1.13/plugins/environment/virtual/index.html @@ -0,0 +1,16 @@ + Virtual environment - Hatch

Virtual environment


This uses virtual environments backed by virtualenv or UV.

Configuration

The environment plugin name is virtual.

[tool.hatch.envs.<ENV_NAME>]
+type = "virtual"
+
[envs.<ENV_NAME>]
+type = "virtual"
+

Options

Option Default Description
python The version of Python to find on your system and subsequently use to create the environment, defaulting to the HATCH_PYTHON environment variable, followed by the normal resolution logic. Setting the HATCH_PYTHON environment variable to self will force the use of the Python executable Hatch is running on. For more information, see the documentation.
python-sources ['external', 'internal'] This may be set to an array of strings that are either the literal internal or external. External considers only Python executables that are already on PATH. Internal considers only internally managed Python distributions.
path An explicit path to the virtual environment. The path may be absolute or relative to the project root. Any environments that inherit this option will also use this path. The environment variable HATCH_ENV_TYPE_VIRTUAL_PATH may be used, which will take precedence.
system-packages false Whether or not to give the virtual environment access to the system site-packages directory
installer pip When set to uv, UV will be used in place of virtualenv & pip for virtual environment creation and dependency management, respectively. If you intend to provide UV yourself, you may set the HATCH_ENV_TYPE_VIRTUAL_UV_PATH environment variable which should be the absolute path to a UV binary. This environment variable implicitly sets the installer option to uv (if unset).

Location

The location of environments is determined in the following heuristic order:

  1. The path option
  2. A directory named after the environment within the configured virtual environment directory if the directory resides somewhere within the project root or if it is set to a .virtualenvs directory within the user's home directory
  3. Otherwise, environments are stored within the configured virtual environment directory in a deeply nested structure in order to support multiple projects

Additionally, when the path option is not used, the name of the directory for the default environment will be the normalized project name to provide a more meaningful default shell prompt.

Python resolution

Virtual environments necessarily require a parent installation of Python. The following rules determine how the parent is resolved.

The Python choice is determined by the python option followed by the HATCH_PYTHON environment variable. If the choice is via the environment variable, then resolution stops and that path is used unconditionally.

The resolvers will be based on the python-sources option and all resolved interpreters will ensure compatibility with the project's defined Python support.

If a Python version has been chosen then each resolver will try to find an interpreter that satisfies that version.

If no version has been chosen, then each resolver will try to find a version that matches the version of Python that Hatch is currently running on. If not found then each resolver will try to find the highest compatible version.

Note

Some external Python paths are considered unstable and are ignored during resolution. For example, if Hatch is installed via Homebrew then sys.executable will be ignored because the interpreter could change or be removed at any time.

Note

When resolution finds a match using an internally managed distribution and an update is available, the latest distribution will automatically be downloaded before environment creation.

Internal distributions

The following options are recognized for internal Python resolution.

Tip

You can set custom sources for distributions by setting the HATCH_PYTHON_SOURCE_<NAME> environment variable where <NAME> is the uppercased version of the distribution name with periods replaced by underscores e.g. HATCH_PYTHON_SOURCE_PYPY3_10.

CPython

NAME
3.7
3.8
3.9
3.10
3.11
3.12
3.13

The source of distributions is the python-build-standalone project.

Some distributions have variants that may be configured. Options may be combined.

Option Platforms Allowed values
HATCH_PYTHON_VARIANT_CPU
  • Linux
  • v1
  • v2
  • v3 (default)
  • v4
HATCH_PYTHON_VARIANT_GIL
  • Linux
  • Windows
  • macOS
  • freethreaded

PyPy

NAME
pypy2.7
pypy3.9
pypy3.10

The source of distributions is the PyPy project.

Troubleshooting

macOS SIP

If you need to set linker environment variables like those starting with DYLD_ or LD_, any executable secured by System Integrity Protection that is invoked when running commands will not see those environment variable modifications as macOS strips those.

Hatch interprets such commands as shell commands but deliberately ignores such paths to protected shells. This workaround suffices for the majority of use cases but there are 2 situations in which it may not:

  1. There are no unprotected sh, bash, zsh, nor fish executables found along PATH.
  2. The desired executable is a project's script, and the location of environments contains spaces or is longer than 1241 characters. In this case pip and other installers will create such an entry point with a shebang pointing to /bin/sh (which is protected) to avoid shebang limitations. Rather than changing the location, you could invoke the script as e.g. python -m pytest (if the project supports that method of invocation by shipping a __main__.py).

  1. The shebang length limit is usually 127 but 3 characters surround the executable path: #!<EXE_PATH>\n 

\ No newline at end of file diff --git a/1.13/plugins/metadata-hook/custom/index.html b/1.13/plugins/metadata-hook/custom/index.html new file mode 100644 index 000000000..cdf184ec2 --- /dev/null +++ b/1.13/plugins/metadata-hook/custom/index.html @@ -0,0 +1,19 @@ + Custom metadata hook - Hatch

Custom metadata hook


This is a custom class in a given Python file that inherits from the MetadataHookInterface.

Configuration

The metadata hook plugin name is custom.

[tool.hatch.metadata.hooks.custom]
+
[metadata.hooks.custom]
+

Options

Option Default Description
path hatch_build.py The path of the Python file

Example

from hatchling.metadata.plugin.interface import MetadataHookInterface
+
+
+class CustomMetadataHook(MetadataHookInterface):
+    ...
+

If multiple subclasses are found, you must define a function named get_metadata_hook that returns the desired build hook.

Note

Any defined PLUGIN_NAME is ignored and will always be custom.

\ No newline at end of file diff --git a/1.13/plugins/metadata-hook/index.html b/1.13/plugins/metadata-hook/index.html new file mode 100644 index 000000000..450e873c1 --- /dev/null +++ b/1.13/plugins/metadata-hook/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/plugins/metadata-hook/reference/index.html b/1.13/plugins/metadata-hook/reference/index.html new file mode 100644 index 000000000..ee674b7d0 --- /dev/null +++ b/1.13/plugins/metadata-hook/reference/index.html @@ -0,0 +1,99 @@ + Metadata hook plugins - Hatch

Metadata hook plugins


Metadata hooks allow for the modification of project metadata after it has been loaded.

Known third-party

MetadataHookInterface

Example usage:

from hatchling.metadata.plugin.interface import MetadataHookInterface
+
+
+class SpecialMetadataHook(MetadataHookInterface):
+    PLUGIN_NAME = 'special'
+    ...
+
from hatchling.plugin import hookimpl
+
+from .plugin import SpecialMetadataHook
+
+
+@hookimpl
+def hatch_register_metadata_hook():
+    return SpecialMetadataHook
+
Source code in backend/src/hatchling/metadata/plugin/interface.py
class MetadataHookInterface(ABC):  # no cov
+    """
+    Example usage:
+
+    ```python tab="plugin.py"
+    from hatchling.metadata.plugin.interface import MetadataHookInterface
+
+
+    class SpecialMetadataHook(MetadataHookInterface):
+        PLUGIN_NAME = 'special'
+        ...
+    ```
+
+    ```python tab="hooks.py"
+    from hatchling.plugin import hookimpl
+
+    from .plugin import SpecialMetadataHook
+
+
+    @hookimpl
+    def hatch_register_metadata_hook():
+        return SpecialMetadataHook
+    ```
+    """
+
+    PLUGIN_NAME = ''
+    """The name used for selection."""
+
+    def __init__(self, root: str, config: dict) -> None:
+        self.__root = root
+        self.__config = config
+
+    @property
+    def root(self) -> str:
+        """
+        The root of the project tree.
+        """
+        return self.__root
+
+    @property
+    def config(self) -> dict:
+        """
+        The hook configuration.
+
+        ```toml config-example
+        [tool.hatch.metadata.hooks.<PLUGIN_NAME>]
+        ```
+        """
+        return self.__config
+
+    @abstractmethod
+    def update(self, metadata: dict) -> None:
+        """
+        This updates the metadata mapping of the `project` table in-place.
+        """
+
+    def get_known_classifiers(self) -> list[str]:  # noqa: PLR6301
+        """
+        This returns extra classifiers that should be considered valid in addition to the ones known to PyPI.
+        """
+        return []
+

PLUGIN_NAME = '' class-attribute instance-attribute

The name used for selection.

root: str property

The root of the project tree.

config: dict property

The hook configuration.

[tool.hatch.metadata.hooks.<PLUGIN_NAME>]
+
[metadata.hooks.<PLUGIN_NAME>]
+

update(metadata: dict) -> None abstractmethod

This updates the metadata mapping of the project table in-place.

Source code in backend/src/hatchling/metadata/plugin/interface.py
@abstractmethod
+def update(self, metadata: dict) -> None:
+    """
+    This updates the metadata mapping of the `project` table in-place.
+    """
+

get_known_classifiers() -> list[str]

This returns extra classifiers that should be considered valid in addition to the ones known to PyPI.

Source code in backend/src/hatchling/metadata/plugin/interface.py
def get_known_classifiers(self) -> list[str]:  # noqa: PLR6301
+    """
+    This returns extra classifiers that should be considered valid in addition to the ones known to PyPI.
+    """
+    return []
+
\ No newline at end of file diff --git a/1.13/plugins/publisher/index.html b/1.13/plugins/publisher/index.html new file mode 100644 index 000000000..450e873c1 --- /dev/null +++ b/1.13/plugins/publisher/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/plugins/publisher/package-index/index.html b/1.13/plugins/publisher/package-index/index.html new file mode 100644 index 000000000..53addba22 --- /dev/null +++ b/1.13/plugins/publisher/package-index/index.html @@ -0,0 +1,24 @@ + Index publisher - Hatch

Index publisher


See the documentation for publishing.

Options

Flag Config name Description
-r/--repo repo The repository with which to publish artifacts
-u/--user user The user with which to authenticate
-a/--auth auth The credentials to use for authentication
--ca-cert ca-cert The path to a CA bundle
--client-cert client-cert The path to a client certificate, optionally containing the private key
--client-key client-key The path to the client certificate's private key
repos A table of named repositories to their respective options

Configuration

The publisher plugin name is index.

[publish.index]
+

Repositories

All top-level options can be overridden per repository using the repos table with a required url attribute for each repository. The following shows the default configuration:

[publish.index.repos.main]
+url = "https://upload.pypi.org/legacy/"
+
+[publish.index.repos.test]
+url = "https://test.pypi.org/legacy/"
+

The repo and repos options have no effect.

Confirmation prompt

You can require a confirmation prompt or use of the -y/--yes flag by setting publishers' disable option to true in either Hatch's config file or project-specific configuration (which takes precedence):

[publish.index]
+disable = true
+
[tool.hatch.publish.index]
+disable = true
+
[publish.index]
+disable = true
+
\ No newline at end of file diff --git a/1.13/plugins/publisher/reference/index.html b/1.13/plugins/publisher/reference/index.html new file mode 100644 index 000000000..40f642eea --- /dev/null +++ b/1.13/plugins/publisher/reference/index.html @@ -0,0 +1,147 @@ + Publisher plugins - Hatch

Publisher plugins


Known third-party

PublisherInterface

Example usage:

    from hatch.publish.plugin.interface import PublisherInterface
+
+
+    class SpecialPublisher(PublisherInterface):
+        PLUGIN_NAME = 'special'
+        ...
+
    from hatchling.plugin import hookimpl
+
+    from .plugin import SpecialPublisher
+
+
+    @hookimpl
+    def hatch_register_publisher():
+        return SpecialPublisher
+
Source code in src/hatch/publish/plugin/interface.py
class PublisherInterface(ABC):
+    """
+    Example usage:
+
+    ```python tab="plugin.py"
+        from hatch.publish.plugin.interface import PublisherInterface
+
+
+        class SpecialPublisher(PublisherInterface):
+            PLUGIN_NAME = 'special'
+            ...
+    ```
+
+    ```python tab="hooks.py"
+        from hatchling.plugin import hookimpl
+
+        from .plugin import SpecialPublisher
+
+
+        @hookimpl
+        def hatch_register_publisher():
+            return SpecialPublisher
+    ```
+    """
+
+    PLUGIN_NAME = ''
+    """The name used for selection."""
+
+    def __init__(self, app, root, cache_dir, project_config, plugin_config):
+        self.__app = app
+        self.__root = root
+        self.__cache_dir = cache_dir
+        self.__project_config = project_config
+        self.__plugin_config = plugin_config
+
+        self.__disable = None
+
+    @property
+    def app(self):
+        """
+        An instance of [Application](../utilities.md#hatchling.bridge.app.Application).
+        """
+        return self.__app
+
+    @property
+    def root(self):
+        """
+        The root of the project tree as a path-like object.
+        """
+        return self.__root
+
+    @property
+    def cache_dir(self):
+        """
+        The directory reserved exclusively for this plugin as a path-like object.
+        """
+        return self.__cache_dir
+
+    @property
+    def project_config(self) -> dict:
+        """
+        ```toml config-example
+        [tool.hatch.publish.<PLUGIN_NAME>]
+        ```
+        """
+        return self.__project_config
+
+    @property
+    def plugin_config(self) -> dict:
+        """
+        This is defined in Hatch's [config file](../../config/hatch.md).
+
+        ```toml tab="config.toml"
+        [publish.<PLUGIN_NAME>]
+        ```
+        """
+        return self.__plugin_config
+
+    @property
+    def disable(self):
+        """
+        Whether this plugin is disabled, thus requiring confirmation when publishing. Local
+        [project configuration](reference.md#hatch.publish.plugin.interface.PublisherInterface.project_config)
+        takes precedence over global
+        [plugin configuration](reference.md#hatch.publish.plugin.interface.PublisherInterface.plugin_config).
+        """
+        if self.__disable is None:
+            if 'disable' in self.project_config:
+                disable = self.project_config['disable']
+                if not isinstance(disable, bool):
+                    message = f'Field `tool.hatch.publish.{self.PLUGIN_NAME}.disable` must be a boolean'
+                    raise TypeError(message)
+            else:
+                disable = self.plugin_config.get('disable', False)
+                if not isinstance(disable, bool):
+                    message = f'Global plugin configuration `publish.{self.PLUGIN_NAME}.disable` must be a boolean'
+                    raise TypeError(message)
+
+            self.__disable = disable
+
+        return self.__disable
+
+    @abstractmethod
+    def publish(self, artifacts: list[str], options: dict):
+        """
+        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+        This is called directly by the [`publish`](../../cli/reference.md#hatch-publish) command
+        with the arguments and options it receives.
+        """
+

PLUGIN_NAME = '' class-attribute instance-attribute

The name used for selection.

app property

An instance of Application.

root property

The root of the project tree as a path-like object.

cache_dir property

The directory reserved exclusively for this plugin as a path-like object.

project_config: dict property

[tool.hatch.publish.<PLUGIN_NAME>]
+
[publish.<PLUGIN_NAME>]
+

plugin_config: dict property

This is defined in Hatch's config file.

[publish.<PLUGIN_NAME>]
+

disable property

Whether this plugin is disabled, thus requiring confirmation when publishing. Local project configuration takes precedence over global plugin configuration.

publish(artifacts: list[str], options: dict) abstractmethod

REQUIRED

This is called directly by the publish command with the arguments and options it receives.

Source code in src/hatch/publish/plugin/interface.py
@abstractmethod
+def publish(self, artifacts: list[str], options: dict):
+    """
+    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:
+
+    This is called directly by the [`publish`](../../cli/reference.md#hatch-publish) command
+    with the arguments and options it receives.
+    """
+
\ No newline at end of file diff --git a/1.13/plugins/utilities/index.html b/1.13/plugins/utilities/index.html new file mode 100644 index 000000000..19c679c1f --- /dev/null +++ b/1.13/plugins/utilities/index.html @@ -0,0 +1,20 @@ + Plugin utilities - Hatch

Plugin utilities


hatchling.builders.utils.get_reproducible_timestamp() -> int

Returns an int derived from the SOURCE_DATE_EPOCH environment variable; see https://reproducible-builds.org/specs/source-date-epoch/.

The default value will always be: 1580601600

Source code in backend/src/hatchling/builders/utils.py
def get_reproducible_timestamp() -> int:
+    """
+    Returns an `int` derived from the `SOURCE_DATE_EPOCH` environment variable; see
+    https://reproducible-builds.org/specs/source-date-epoch/.
+
+    The default value will always be: `1580601600`
+    """
+    return int(os.environ.get('SOURCE_DATE_EPOCH', '1580601600'))
+

BuilderConfig

directory: str property

ignore_vcs: bool property

reproducible: bool property

Whether or not the target should be built in a reproducible manner, defaulting to true.

dev_mode_dirs: list[str] property

Directories which must be added to Python's search path in dev mode.

versions: list[str] property

dependencies: list[str] property

default_include() -> list

default_exclude() -> list

default_packages() -> list

default_only_include() -> list

Application

The way output is displayed can be configured by users.

Important

Never import this directly; Hatch judiciously decides if a type of plugin requires the capabilities herein and will grant access via an attribute.

verbosity: int property

The verbosity level of the application, with 0 as the default.

abort(message: str = '', code: int = 1, **kwargs: Any) -> None

Terminate the program with the given return code.

display_debug(message: str = '', level: int = 1, **kwargs: Any) -> None

Meant to be used for messages that are not useful for most user experiences. The level option must be between 1 and 3 (inclusive).

display_error(message: str = '', **kwargs: Any) -> None

Meant to be used for messages indicating some unrecoverable error.

display_info(message: str = '', **kwargs: Any) -> None

Meant to be used for messages conveying basic information.

display_success(message: str = '', **kwargs: Any) -> None

Meant to be used for messages indicating some positive outcome.

display_waiting(message: str = '', **kwargs: Any) -> None

Meant to be used for messages shown before potentially time consuming operations.

display_warning(message: str = '', **kwargs: Any) -> None

Meant to be used for messages conveying important information.

Platform

default_shell: str property

Returns the default shell of the system.

On Windows systems first try the SHELL environment variable, if present, followed by the COMSPEC environment variable, defaulting to cmd. On all other platforms only the SHELL environment variable will be used, defaulting to bash.

modules: LazilyLoadedModules property

Accessor for lazily loading modules that either take multiple milliseconds to import (like shutil and subprocess) or are not used on all platforms (like shlex).

home: Path property

The user's home directory as a path-like object.

name: str property

One of the following:

  • linux
  • windows
  • macos

display_name: str property

One of the following:

  • Linux
  • Windows
  • macOS

windows: bool property

Indicates whether Hatch is running on Windows.

macos: bool property

Indicates whether Hatch is running on macOS.

linux: bool property

Indicates whether Hatch is running on neither Windows nor macOS.

format_for_subprocess(command: str | list[str], *, shell: bool) -> str | list[str]

Format the given command in a cross-platform manner for immediate consumption by subprocess utilities.

run_command(command: str | list[str], *, shell: bool = False, **kwargs: Any) -> CompletedProcess

Equivalent to the standard library's subprocess.run, with the command first being properly formatted.

check_command(command: str | list[str], *, shell: bool = False, **kwargs: Any) -> CompletedProcess

Equivalent to run_command, but non-zero exit codes will gracefully end program execution.

check_command_output(command: str | list[str], *, shell: bool = False, **kwargs: Any) -> str

Equivalent to the output from the process returned by capture_process, but non-zero exit codes will gracefully end program execution.

capture_process(command: str | list[str], *, shell: bool = False, **kwargs: Any) -> Popen

Equivalent to the standard library's subprocess.Popen, with all output captured by stdout and the command first being properly formatted.

exit_with_command(command: list[str]) -> None

Run the given command and exit with its exit code. On non-Windows systems, this uses the standard library's os.execvp.

EnvironmentContextFormatter

formatters()

This returns a mapping of supported field names to their respective formatting functions. Each function accepts 2 arguments:

  • the value that was passed to the format call, defaulting to None
  • the modifier data, defaulting to an empty string
\ No newline at end of file diff --git a/1.13/plugins/version-scheme/index.html b/1.13/plugins/version-scheme/index.html new file mode 100644 index 000000000..450e873c1 --- /dev/null +++ b/1.13/plugins/version-scheme/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/plugins/version-scheme/reference/index.html b/1.13/plugins/version-scheme/reference/index.html new file mode 100644 index 000000000..661d45146 --- /dev/null +++ b/1.13/plugins/version-scheme/reference/index.html @@ -0,0 +1,88 @@ + Version scheme plugins - Hatch

Version scheme plugins


Known third-party

VersionSchemeInterface

Example usage:

from hatchling.version.scheme.plugin.interface import VersionSchemeInterface
+
+
+class SpecialVersionScheme(VersionSchemeInterface):
+    PLUGIN_NAME = 'special'
+    ...
+
from hatchling.plugin import hookimpl
+
+from .plugin import SpecialVersionScheme
+
+
+@hookimpl
+def hatch_register_version_scheme():
+    return SpecialVersionScheme
+
Source code in backend/src/hatchling/version/scheme/plugin/interface.py
class VersionSchemeInterface(ABC):  # no cov
+    """
+    Example usage:
+
+    ```python tab="plugin.py"
+    from hatchling.version.scheme.plugin.interface import VersionSchemeInterface
+
+
+    class SpecialVersionScheme(VersionSchemeInterface):
+        PLUGIN_NAME = 'special'
+        ...
+    ```
+
+    ```python tab="hooks.py"
+    from hatchling.plugin import hookimpl
+
+    from .plugin import SpecialVersionScheme
+
+
+    @hookimpl
+    def hatch_register_version_scheme():
+        return SpecialVersionScheme
+    ```
+    """
+
+    PLUGIN_NAME = ''
+    """The name used for selection."""
+
+    def __init__(self, root: str, config: dict) -> None:
+        self.__root = root
+        self.__config = config
+
+    @property
+    def root(self) -> str:
+        """
+        The root of the project tree as a string.
+        """
+        return self.__root
+
+    @property
+    def config(self) -> dict:
+        """
+        ```toml config-example
+        [tool.hatch.version]
+        ```
+        """
+        return self.__config
+
+    @abstractmethod
+    def update(self, desired_version: str, original_version: str, version_data: dict) -> str:
+        """
+        This should return a normalized form of the desired version and verify that it
+        is higher than the original version.
+        """
+

PLUGIN_NAME = '' class-attribute instance-attribute

The name used for selection.

root: str property

The root of the project tree as a string.

config: dict property

[tool.hatch.version]
+
[version]
+

update(desired_version: str, original_version: str, version_data: dict) -> str abstractmethod

This should return a normalized form of the desired version and verify that it is higher than the original version.

Source code in backend/src/hatchling/version/scheme/plugin/interface.py
@abstractmethod
+def update(self, desired_version: str, original_version: str, version_data: dict) -> str:
+    """
+    This should return a normalized form of the desired version and verify that it
+    is higher than the original version.
+    """
+
\ No newline at end of file diff --git a/1.13/plugins/version-scheme/standard/index.html b/1.13/plugins/version-scheme/standard/index.html new file mode 100644 index 000000000..43785c58e --- /dev/null +++ b/1.13/plugins/version-scheme/standard/index.html @@ -0,0 +1,16 @@ + Standard version scheme - Hatch

Standard version scheme


See the documentation for versioning.

Configuration

The version scheme plugin name is standard.

[tool.hatch.version]
+scheme = "standard"
+
[version]
+scheme = "standard"
+

Options

Option Description
validate-bump When setting a specific version, this determines whether to check that the new version is higher than the original. The default is true.
\ No newline at end of file diff --git a/1.13/plugins/version-source/code/index.html b/1.13/plugins/version-source/code/index.html new file mode 100644 index 000000000..fdf8600ef --- /dev/null +++ b/1.13/plugins/version-source/code/index.html @@ -0,0 +1,30 @@ + Code version source - Hatch

Code version source


Updates

Setting the version is not supported.

Configuration

The version source plugin name is code.

[tool.hatch.version]
+source = "code"
+
[version]
+source = "code"
+

Options

Option Description
path (required) A relative path to a Python file or extension module that will be loaded
expression A Python expression that when evaluated in the context of the loaded file returns the version. The default expression is simply __version__.
search-paths A list of relative paths to directories that will be prepended to Python's search path

Missing imports

If the chosen path imports another module in your project, then you'll need to use absolute imports coupled with the search-paths option. For example, say you need to load the following file:

    from ._version import get_version
+
+    __version__ = get_version()
+

You should change it to:

    from pkg._version import get_version
+
+    __version__ = get_version()
+

and the configuration would become:

[tool.hatch.version]
+source = "code"
+path = "src/pkg/__init__.py"
+search-paths = ["src"]
+
[version]
+source = "code"
+path = "src/pkg/__init__.py"
+search-paths = ["src"]
+
\ No newline at end of file diff --git a/1.13/plugins/version-source/env/index.html b/1.13/plugins/version-source/env/index.html new file mode 100644 index 000000000..e43277094 --- /dev/null +++ b/1.13/plugins/version-source/env/index.html @@ -0,0 +1,16 @@ + Environment version source - Hatch

Environment version source


Retrieves the version from an environment variable. This can be useful in build pipelines where the version is set by an external trigger.

Updates

Setting the version is not supported.

Configuration

The version source plugin name is env.

[tool.hatch.version]
+source = "env"
+
[version]
+source = "env"
+

Options

Option Description
variable (required) The name of the environment variable
\ No newline at end of file diff --git a/1.13/plugins/version-source/index.html b/1.13/plugins/version-source/index.html new file mode 100644 index 000000000..450e873c1 --- /dev/null +++ b/1.13/plugins/version-source/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/plugins/version-source/reference/index.html b/1.13/plugins/version-source/reference/index.html new file mode 100644 index 000000000..bfad809fe --- /dev/null +++ b/1.13/plugins/version-source/reference/index.html @@ -0,0 +1,107 @@ + Version source plugins - Hatch

Version source plugins


Known third-party

  • hatch-vcs - uses your preferred version control system (like Git)
  • hatch-nodejs-version - uses the version field of NodeJS package.json files
  • hatch-regex-commit - automatically creates a Git commit and tag after version bumping
  • versioningit - determines version from Git or Mercurial tags, with customizable version formatting

VersionSourceInterface

Example usage:

from hatchling.version.source.plugin.interface import VersionSourceInterface
+
+
+class SpecialVersionSource(VersionSourceInterface):
+    PLUGIN_NAME = 'special'
+    ...
+
from hatchling.plugin import hookimpl
+
+from .plugin import SpecialVersionSource
+
+
+@hookimpl
+def hatch_register_version_source():
+    return SpecialVersionSource
+
Source code in backend/src/hatchling/version/source/plugin/interface.py
class VersionSourceInterface(ABC):  # no cov
+    """
+    Example usage:
+
+    ```python tab="plugin.py"
+    from hatchling.version.source.plugin.interface import VersionSourceInterface
+
+
+    class SpecialVersionSource(VersionSourceInterface):
+        PLUGIN_NAME = 'special'
+        ...
+    ```
+
+    ```python tab="hooks.py"
+    from hatchling.plugin import hookimpl
+
+    from .plugin import SpecialVersionSource
+
+
+    @hookimpl
+    def hatch_register_version_source():
+        return SpecialVersionSource
+    ```
+    """
+
+    PLUGIN_NAME = ''
+    """The name used for selection."""
+
+    def __init__(self, root: str, config: dict) -> None:
+        self.__root = root
+        self.__config = config
+
+    @property
+    def root(self) -> str:
+        """
+        The root of the project tree as a string.
+        """
+        return self.__root
+
+    @property
+    def config(self) -> dict:
+        """
+        ```toml config-example
+        [tool.hatch.version]
+        ```
+        """
+        return self.__config
+
+    @abstractmethod
+    def get_version_data(self) -> dict:
+        """
+        This should return a mapping with a `version` key representing the current version of the project and will be
+        displayed when invoking the [`version`](../../cli/reference.md#hatch-version) command without any arguments.
+
+        The mapping can contain anything else and will be passed to
+        [set_version](reference.md#hatchling.version.source.plugin.interface.VersionSourceInterface.set_version)
+        when updating the version.
+        """
+
+    def set_version(self, version: str, version_data: dict) -> None:
+        """
+        This should update the version to the first argument with the data provided during retrieval.
+        """
+        raise NotImplementedError
+

PLUGIN_NAME = '' class-attribute instance-attribute

The name used for selection.

root: str property

The root of the project tree as a string.

config: dict property

[tool.hatch.version]
+
[version]
+

get_version_data() -> dict abstractmethod

This should return a mapping with a version key representing the current version of the project and will be displayed when invoking the version command without any arguments.

The mapping can contain anything else and will be passed to set_version when updating the version.

Source code in backend/src/hatchling/version/source/plugin/interface.py
@abstractmethod
+def get_version_data(self) -> dict:
+    """
+    This should return a mapping with a `version` key representing the current version of the project and will be
+    displayed when invoking the [`version`](../../cli/reference.md#hatch-version) command without any arguments.
+
+    The mapping can contain anything else and will be passed to
+    [set_version](reference.md#hatchling.version.source.plugin.interface.VersionSourceInterface.set_version)
+    when updating the version.
+    """
+

set_version(version: str, version_data: dict) -> None

This should update the version to the first argument with the data provided during retrieval.

Source code in backend/src/hatchling/version/source/plugin/interface.py
def set_version(self, version: str, version_data: dict) -> None:
+    """
+    This should update the version to the first argument with the data provided during retrieval.
+    """
+    raise NotImplementedError
+
\ No newline at end of file diff --git a/1.13/plugins/version-source/regex/index.html b/1.13/plugins/version-source/regex/index.html new file mode 100644 index 000000000..e182b2962 --- /dev/null +++ b/1.13/plugins/version-source/regex/index.html @@ -0,0 +1,16 @@ + Regex version source - Hatch

Regex version source


See the documentation for versioning.

Updates

Setting the version is supported.

Configuration

The version source plugin name is regex.

[tool.hatch.version]
+source = "regex"
+
[version]
+source = "regex"
+

Options

Option Description
path (required) A relative path to a file containing the project's version
pattern A regular expression that has a named group called version that represents the version. The default pattern looks for a variable named __version__ or VERSION that is set to a string containing the version, optionally prefixed with the lowercase letter v.
\ No newline at end of file diff --git a/1.13/publish/index.html b/1.13/publish/index.html new file mode 100644 index 000000000..cbc4b04ac --- /dev/null +++ b/1.13/publish/index.html @@ -0,0 +1,19 @@ + Publishing - Hatch

Publishing


After your project is built, you can distribute it using the publish command.

The -p/--publisher option controls which publisher to use, with the default being index.

Artifact selection

By default, the dist directory located at the root of your project will be used:

$ hatch publish
+dist/hatch_demo-1rc0-py3-none-any.whl ... success
+dist/hatch_demo-1rc0.tar.gz ... success
+
+[hatch-demo]
+https://pypi.org/project/hatch-demo/1rc0/
+

You can instead pass specific paths as arguments:

hatch publish /path/to/artifacts foo-1.tar.gz
+

Only files ending with .whl or .tar.gz will be published.

Further resources

Please refer to the publisher plugin reference for configuration options.

There's a How-To on authentication and on options to select the target repository.

The publish command is implemented as a built-in plugin, if you're planning your own plugin, read about the publisher plugin API.

\ No newline at end of file diff --git a/1.13/search/search_index.json b/1.13/search/search_index.json new file mode 100644 index 000000000..fd75ec3a8 --- /dev/null +++ b/1.13/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"Hatch","text":"CI/CD Docs Package Meta

Hatch is a modern, extensible Python project manager. See the Why Hatch? page for more information.

  • Build system

    Reproducible builds by default with a rich ecosystem of plugins

    Configure builds

  • Environments

    Robust environment management with support for custom scripts and UV

    Getting started

  • Python management

    Choose between easy manual installations or automatic as part of environments

    Try it

  • Testing

    Test execution with known best practices

    Run

  • Static analysis

    Static analysis backed by Ruff with up-to-date, sane defaults

    Learn

  • Script runner

    Execute Python scripts with specific dependencies and Python versions

    Execute

  • Publishing

    Easily upload to PyPI or other indices

    See how

  • Versioning

    Streamlined workflow for bumping versions

    Managing versions

  • Project generation

    Create new projects from templates with known best practices

    Project setup

  • Responsive CLI

    Hatch is up to 3x faster than equivalent tools

    CLI reference

"},{"location":"#license","title":"License","text":"

Hatch is distributed under the terms of the MIT license.

"},{"location":"#navigation","title":"Navigation","text":"

Documentation for specific MAJOR.MINOR versions can be chosen by using the dropdown on the top of every page. The dev version reflects changes that have not yet been released.

Also, desktop readers can use special keyboard shortcuts:

Keys Action
  • , (comma)
  • p
Navigate to the \"previous\" page
  • . (period)
  • n
Navigate to the \"next\" page
  • /
  • s
Display the search modal"},{"location":"build/","title":"Builds","text":""},{"location":"build/#configuration","title":"Configuration","text":"

Builds are configured using the tool.hatch.build table. Every target is defined by a section within tool.hatch.build.targets, for example:

pyproject.toml hatch.toml
[tool.hatch.build.targets.sdist]\nexclude = [\n  \"/.github\",\n  \"/docs\",\n]\n\n[tool.hatch.build.targets.wheel]\npackages = [\"src/foo\"]\n
[build.targets.sdist]\nexclude = [\n  \"/.github\",\n  \"/docs\",\n]\n\n[build.targets.wheel]\npackages = [\"src/foo\"]\n
"},{"location":"build/#building","title":"Building","text":"

Invoking the build command without any arguments will build the sdist and wheel targets:

$ hatch build\n[sdist]\ndist/hatch_demo-1rc0.tar.gz\n\n[wheel]\ndist/hatch_demo-1rc0-py3-none-any.whl\n

To only build specific targets, use the -t/--target option:

$ hatch build -t wheel\n[wheel]\ndist/hatch_demo-1rc0-py3-none-any.whl\n

If the target supports multiple versions, you can specify the exact versions to build by appending a colon followed by the desired versions separated by commas:

$ hatch -v build -t wheel:standard\n[wheel]\nBuilding `wheel` version `standard`\ndist/hatch_demo-1rc0-py3-none-any.whl\n
"},{"location":"build/#packaging-ecosystem","title":"Packaging ecosystem","text":"

Hatch complies with modern Python packaging specs and therefore your projects can be used by other tools with Hatch serving as just the build backend.

So you could use tox as an alternative to Hatch's environment management, or cibuildwheel to distribute packages for every platform, and they both will transparently use Hatch without any extra modification.

"},{"location":"environment/","title":"Environments","text":"

Environments are designed to allow for isolated workspaces for testing, building documentation, or anything else projects need.

Unless an environment is chosen explicitly, Hatch will use the default environment.

Tip

For a more comprehensive walk-through, see the Basic usage tutorial.

"},{"location":"environment/#creation","title":"Creation","text":"

You can create environments by using the env create command. Let's enter the directory of the project we created in the setup phase:

$ hatch env create\nCreating environment: default\nInstalling project in development mode\nSyncing dependencies\n

Tip

You never need to manually create environments as spawning a shell or running commands within one will automatically trigger creation.

"},{"location":"environment/#entering-environments","title":"Entering environments","text":"

You can spawn a shell within an environment by using the shell command.

$ hatch shell\n(hatch-demo) $\n

Now confirm the project has been installed:

(hatch-demo) $ pip show hatch-demo\nName: hatch-demo\nVersion: 0.0.1\n...\n

Finally, see where your environment's Python is located:

(hatch-demo) $ python -c \"import sys;print(sys.executable)\"\n...\n

You can type exit to leave the environment.

"},{"location":"environment/#command-execution","title":"Command execution","text":"

The run command allows you to execute commands in an environment as if you had already entered it. For example, running the following command will output the same path as before:

hatch run python -c \"import sys;print(sys.executable)\"\n

Tip

Be sure to check out how to define scripts for your project.

"},{"location":"environment/#dependencies","title":"Dependencies","text":"

Hatch ensures that environments are always compatible with the currently defined project dependencies (if installed and in dev mode) and environment dependencies.

To add cowsay as a dependency, open pyproject.toml and add it to the dependencies array:

pyproject.toml
[project]\n...\ndependencies = [\n  \"cowsay\"\n]\n

This dependency will be installed the next time you spawn a shell or run a command. For example:

$ hatch run cowsay -t \"Hello, world!\"\nSyncing dependencies\n  _____________\n| Hello, world! |\n  =============\n             \\\n              \\\n                ^__^\n                (oo)\\_______\n                (__)\\       )\\/\\\n                    ||----w |\n                    ||     ||\n

Note

The Syncing dependencies status will display temporarily when Hatch updates environments in response to any dependency changes that you make.

"},{"location":"environment/#selection","title":"Selection","text":"

You can select which environment to enter or run commands in by using the -e/--env root option or by setting the HATCH_ENV environment variable.

The run command allows for more explicit selection by prepending <ENV_NAME>: to commands. For example, if you had the following configuration:

pyproject.toml hatch.toml
[tool.hatch.envs.docs]\ndependencies = [\n  \"mkdocs\"\n]\n[tool.hatch.envs.docs.scripts]\nbuild = \"mkdocs build --clean --strict\"\nserve = \"mkdocs serve --dev-addr localhost:8000\"\n
[envs.docs]\ndependencies = [\n  \"mkdocs\"\n]\n[envs.docs.scripts]\nbuild = \"mkdocs build --clean --strict\"\nserve = \"mkdocs serve --dev-addr localhost:8000\"\n

you could then serve your documentation by running:

hatch run docs:serve\n

Tip

If you've already entered an environment, commands will target it by default.

"},{"location":"environment/#matrix","title":"Matrix","text":"

Every environment can define its own set of matrices:

pyproject.toml hatch.toml
[tool.hatch.envs.test]\ndependencies = [\n  \"pytest\"\n]\n\n[[tool.hatch.envs.test.matrix]]\npython = [\"3.10\", \"3.11\"]\nversion = [\"42\", \"3.14\"]\n\n[[tool.hatch.envs.test.matrix]]\npython = [\"3.11\", \"3.12\"]\nversion = [\"9000\"]\nfeature = [\"foo\", \"bar\"]\n
[envs.test]\ndependencies = [\n  \"pytest\"\n]\n\n[[envs.test.matrix]]\npython = [\"3.10\", \"3.11\"]\nversion = [\"42\", \"3.14\"]\n\n[[envs.test.matrix]]\npython = [\"3.11\", \"3.12\"]\nversion = [\"9000\"]\nfeature = [\"foo\", \"bar\"]\n

Using the env show command would then display:

$ hatch env show --ascii\n     Standalone\n+---------+---------+\n| Name    | Type    |\n+=========+=========+\n| default | virtual |\n+---------+---------+\n                        Matrices\n+------+---------+----------------------+--------------+\n| Name | Type    | Envs                 | Dependencies |\n+======+=========+======================+==============+\n| test | virtual | test.py3.10-42       | pytest       |\n|      |         | test.py3.10-3.14     |              |\n|      |         | test.py3.11-42       |              |\n|      |         | test.py3.11-3.14     |              |\n|      |         | test.py3.11-9000-foo |              |\n|      |         | test.py3.11-9000-bar |              |\n|      |         | test.py3.12-9000-foo |              |\n|      |         | test.py3.12-9000-bar |              |\n+------+---------+----------------------+--------------+\n
"},{"location":"environment/#removal","title":"Removal","text":"

You can remove a single environment or environment matrix by using the env remove command or all of a project's environments by using the env prune command.

"},{"location":"install/","title":"Installation","text":""},{"location":"install/#github-actions","title":"GitHub Actions","text":"
- name: Install Hatch\n  uses: pypa/hatch@install\n

Refer to the official action for more information.

"},{"location":"install/#installers","title":"Installers","text":"macOSWindows GUI installerCommand line installer
  1. In your browser, download the .pkg file: hatch-universal.pkg
  2. Run your downloaded file and follow the on-screen instructions.
  3. Restart your terminal.
  4. To verify that the shell can find and run the hatch command in your PATH, use the following command.

    $ hatch --version\n1.13.0\n
  1. Download the file using the curl command. The -o option specifies the file name that the downloaded package is written to. In this example, the file is written to hatch-universal.pkg in the current directory.

    curl -Lo hatch-universal.pkg https://github.com/pypa/hatch/releases/latest/download/hatch-universal.pkg\n
  2. Run the standard macOS installer program, specifying the downloaded .pkg file as the source. Use the -pkg parameter to specify the name of the package to install, and the -target / parameter for the drive in which to install the package. The files are installed to /usr/local/hatch, and an entry is created at /etc/paths.d/hatch that instructs shells to add the /usr/local/hatch directory to. You must include sudo on the command to grant write permissions to those folders.

    sudo installer -pkg ./hatch-universal.pkg -target /\n
  3. Restart your terminal.

  4. To verify that the shell can find and run the hatch command in your PATH, use the following command.

    $ hatch --version\n1.13.0\n
GUI installerCommand line installer
  1. In your browser, download one the .msi files:
    • hatch-x64.msi
  2. Run your downloaded file and follow the on-screen instructions.
  3. Restart your terminal.
  4. To verify that the shell can find and run the hatch command in your PATH, use the following command.

    $ hatch --version\n1.13.0\n
  1. Download and run the installer using the standard Windows msiexec program, specifying one of the .msi files as the source. Use the /passive and /i parameters to request an unattended, normal installation.

    x64x86
    msiexec /passive /i https://github.com/pypa/hatch/releases/latest/download/hatch-x64.msi\n
    msiexec /passive /i https://github.com/pypa/hatch/releases/latest/download/hatch-x86.msi\n
  2. Restart your terminal.

  3. To verify that the shell can find and run the hatch command in your PATH, use the following command.

    $ hatch --version\n1.13.0\n
"},{"location":"install/#standalone-binaries","title":"Standalone binaries","text":"

After downloading the archive corresponding to your platform and architecture, extract the binary to a directory that is on your PATH and rename to hatch.

LinuxmacOSWindows
  • hatch-aarch64-unknown-linux-gnu.tar.gz
  • hatch-x86_64-unknown-linux-gnu.tar.gz
  • hatch-x86_64-unknown-linux-musl.tar.gz
  • hatch-powerpc64le-unknown-linux-gnu.tar.gz
  • hatch-aarch64-apple-darwin.tar.gz
  • hatch-x86_64-apple-darwin.tar.gz
  • hatch-x86_64-pc-windows-msvc.zip
  • hatch-i686-pc-windows-msvc.zip
"},{"location":"install/#pip","title":"pip","text":"

Hatch is available on PyPI and can be installed with pip.

pip install hatch\n

Warning

This method modifies the Python environment in which you choose to install. Consider instead using pipx to avoid dependency conflicts.

"},{"location":"install/#pipx","title":"pipx","text":"

pipx allows for the global installation of Python applications in isolated environments.

pipx install hatch\n
"},{"location":"install/#homebrew","title":"Homebrew","text":"

See the formula for more details.

brew install hatch\n
"},{"location":"install/#conda","title":"Conda","text":"

See the feedstock for more details.

conda install -c conda-forge hatch\n

or with mamba:

mamba install hatch\n

Warning

This method modifies the Conda environment in which you choose to install. Consider instead using pipx or condax to avoid dependency conflicts.

"},{"location":"install/#macports","title":"MacPorts","text":"

See the port for more details.

sudo port install hatch\n
"},{"location":"install/#fedora","title":"Fedora","text":"

The minimum supported version is 37, currently in development as Rawhide.

sudo dnf install hatch\n
"},{"location":"install/#void-linux","title":"Void Linux","text":"
xbps-install hatch\n
"},{"location":"install/#build-system-availability","title":"Build system availability","text":"

Hatchling is Hatch's build backend which you will never need to install manually. See its changelog for version information.

"},{"location":"intro/","title":"Introduction","text":""},{"location":"intro/#setup","title":"Setup","text":"

Projects can be set up for use by Hatch using the new command.

"},{"location":"intro/#new-project","title":"New project","text":"

Let's say you want to create a project named Hatch Demo. You would run:

hatch new \"Hatch Demo\"\n

This would create the following structure in your current working directory:

hatch-demo\n\u251c\u2500\u2500 src\n\u2502   \u2514\u2500\u2500 hatch_demo\n\u2502       \u251c\u2500\u2500 __about__.py\n\u2502       \u2514\u2500\u2500 __init__.py\n\u251c\u2500\u2500 tests\n\u2502   \u2514\u2500\u2500 __init__.py\n\u251c\u2500\u2500 LICENSE.txt\n\u251c\u2500\u2500 README.md\n\u2514\u2500\u2500 pyproject.toml\n

Tip

There are many ways to customize project generation.

"},{"location":"intro/#existing-project","title":"Existing project","text":"

To initialize an existing project, enter the directory containing the project and run the following:

hatch new --init\n

If your project has a setup.py file the command will automatically migrate setuptools configuration for you. Otherwise, this will interactively guide you through the setup process.

"},{"location":"intro/#project-metadata","title":"Project metadata","text":"

Next you'll want to define more of your project's metadata located in the pyproject.toml file. You can specify things like its license, the supported versions of Python, and URLs referring to various parts of your project, like documentation.

"},{"location":"intro/#dependencies","title":"Dependencies","text":"

The last step of the setup process is to define any dependencies that you'd like your project to begin with.

"},{"location":"intro/#configuration","title":"Configuration","text":"

All project-specific configuration recognized by Hatch can be defined in either the pyproject.toml file, or a file named hatch.toml where options are not contained within the tool.hatch table:

pyproject.toml hatch.toml
[tool.hatch]\noption = \"...\"\n\n[tool.hatch.table1]\noption = \"...\"\n\n[tool.hatch.table2]\noption = \"...\"\n
option = \"...\"\n\n[table1]\noption = \"...\"\n\n[table2]\noption = \"...\"\n

Top level keys in the latter file take precedence when defined in both.

Tip

If you want to make your file more compact, you can use dotted keys, turning the above example into:

pyproject.toml hatch.toml
[tool.hatch]\noption = \"...\"\ntable1.option = \"...\"\ntable2.option = \"...\"\n
option = \"...\"\ntable1.option = \"...\"\ntable2.option = \"...\"\n
"},{"location":"next-steps/","title":"Next steps","text":""},{"location":"next-steps/#learn-more","title":"Learn more","text":"

At this point you should have a basic understanding of how to use Hatch.

Now you may want to check out advanced configuration for environments or builds, set up your preferred shell, or read more about Hatch's CLI.

After that, check out the Hatch Showcase project to see examples of what is possible.

Finally, if you see a need, feel free to write a plugin for extended functionality.

"},{"location":"next-steps/#community","title":"Community","text":"

For any projects using Hatch, you may add its official badge somewhere prominent like the README.

MarkdownreStructuredText
[![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch)\n
.. image:: https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg\n   :alt: Hatch project\n   :target: https://github.com/pypa/hatch\n
"},{"location":"publish/","title":"Publishing","text":"

After your project is built, you can distribute it using the publish command.

The -p/--publisher option controls which publisher to use, with the default being index.

"},{"location":"publish/#artifact-selection","title":"Artifact selection","text":"

By default, the dist directory located at the root of your project will be used:

$ hatch publish\ndist/hatch_demo-1rc0-py3-none-any.whl ... success\ndist/hatch_demo-1rc0.tar.gz ... success\n\n[hatch-demo]\nhttps://pypi.org/project/hatch-demo/1rc0/\n

You can instead pass specific paths as arguments:

hatch publish /path/to/artifacts foo-1.tar.gz\n

Only files ending with .whl or .tar.gz will be published.

"},{"location":"publish/#further-resources","title":"Further resources","text":"

Please refer to the publisher plugin reference for configuration options.

There's a How-To on authentication and on options to select the target repository.

The publish command is implemented as a built-in plugin, if you're planning your own plugin, read about the publisher plugin API.

"},{"location":"version/","title":"Versioning","text":""},{"location":"version/#configuration","title":"Configuration","text":"

When the version is not statically set, configuration is defined in the tool.hatch.version table. The source option determines the source to use for retrieving and updating the version. The regex source is used by default.

The regex source requires an option path that represents a relative path to a file containing the project's version:

pyproject.toml hatch.toml
[tool.hatch.version]\npath = \"src/hatch_demo/__about__.py\"\n
[version]\npath = \"src/hatch_demo/__about__.py\"\n

The default pattern looks for a variable named __version__ or VERSION that is set to a string containing the version, optionally prefixed with the lowercase letter v.

If this doesn't reflect how you store the version, you can define a different regular expression using the pattern option:

pyproject.toml hatch.toml
[tool.hatch.version]\npath = \"pkg/__init__.py\"\npattern = \"BUILD = 'b(?P<version>[^']+)'\"\n
[version]\npath = \"pkg/__init__.py\"\npattern = \"BUILD = 'b(?P<version>[^']+)'\"\n

The pattern must have a named group called version that represents the version.

"},{"location":"version/#display","title":"Display","text":"

Invoking the version command without any arguments will display the current version of the project:

$ hatch version\n0.0.1\n
"},{"location":"version/#updating","title":"Updating","text":"

You can update the version like so:

$ hatch version \"0.1.0\"\nOld: 0.0.1\nNew: 0.1.0\n

The scheme option determines the scheme to use for parsing both the existing and new versions. The standard scheme is used by default, which is based on PEP 440.

Rather than setting the version explicitly, you can select the name of a segment used to increment the version:

$ hatch version minor\nOld: 0.1.0\nNew: 0.2.0\n

You can chain multiple segment updates with a comma. For example, if you wanted to release a preview of your project's first major version, you could do:

$ hatch version major,rc\nOld: 0.2.0\nNew: 1.0.0rc0\n

When you want to release the final version, you would do:

$ hatch version release\nOld: 1.0.0rc0\nNew: 1.0.0\n
"},{"location":"version/#supported-segments","title":"Supported segments","text":"

Here are the supported segments and how they would influence an existing version of 1.0.0:

Segments New version release 1.0.0 major 2.0.0 minor 1.1.0 micropatchfix 1.0.1 aalpha 1.0.0a0 bbeta 1.0.0b0 crcprepreview 1.0.0rc0 rrevpost 1.0.0.post0 dev 1.0.0.dev0"},{"location":"why/","title":"Why Hatch?","text":"

The high level value proposition of Hatch is that if one adopts all functionality then many other tools become unnecessary since there is support for everything one might require. Further, if one chooses to use only specific features then there are still benefits compared to alternatives.

"},{"location":"why/#build-backend","title":"Build backend","text":"

Hatchling, the build backend sister project, has many benefits compared to setuptools. Here we only compare setuptools as that is the one most people are familiar with.

  • Better defaults: The default behavior for setuptools is often not desirable for the average user.
    • For source distributions, setuptools has a custom enumeration of files that get included and excluded by default. Hatchling takes the defaults from your version control system such as Git's .gitignore file.
    • For wheels, setuptools attempts to find every directory that looks like a Python package. This is often undesirable as you might ship files to the end-user unintentionally such as test or tooling directories. Hatchling defaults to very specific inclusion based on the project name and errors if no heuristic is satisfied.
  • Ease of configurability: Hatchling was designed based on a history of significant challenges when configuring setuptools.
    • Hatchling uses the same glob pattern syntax as Git itself for every option which is what most users are familiar with. On the other hand, setuptools uses shell-style glob patterns for source distributions while wheels use a mix of shell-style globs and Python package syntax.
    • Configuring what gets included in source distributions requires a separate MANIFEST.in file. The custom syntax and directives must be learned and it is difficult knowing which options in the main files like setup.py influence the behavior and under what conditions. For Hatchling, everything gets configured in a single file under dedicated sections for specific targets like [tool.hatch.build.targets.wheel].
    • By default, non-Python files are excluded from wheels. Including such files requires usually verbose rules for every nested package directory. Hatchling makes no such distinction between file types and acts more like a general build system one might already be familiar with.
  • Editable installations: The default behavior of Hatchling allows for proper static analysis by external tools such as IDEs. With setuptools, you must provide additional configuration which means that by default, for example, you would not get autocompletion in Visual Studio Code. This is marked as a legacy feature and may in fact be removed in future versions of setuptools.
  • Reproducibility: Hatchling builds reproducible wheels and source distributions by default. setuptools does not support this for source distributions and there is no guarantee that wheels are reproducible.
  • Extensibility: Although it is possible to extend setuptools, the API is quite low level. Hatchling has the concept of plugins that are separated into discrete types and only expose what is necessary, leading to an easier developer experience.

Why not?:

If building extension modules is required then it is recommended that you continue using setuptools, or even other backends that specialize in interfacing with compilers.

"},{"location":"why/#environment-management","title":"Environment management","text":"

Here we compare to both tox and nox. At a high level, there are a few common advantages:

  • Python management: Hatch is able to automatically download Python distributions on the fly when specific versions that environments request cannot be found. The alternatives will raise an error, with the option to ignore unknown distributions.
  • Philosophy: In the alternatives, environments are for the most part treated as executable units where a dependency set is associated with an action. If you are familiar with container ecosystems, this would be like defining a CMD at the end of a Dockerfile but without the ability to change the action at runtime. This involves significant wasted disk space usually because one often requires slight modifications to the actions and therefore will define entirely different environments inherited from a base config just to perform different logic. Additionally, this can be confusing to users not just configuration-wise but also for execution of the different environments.

    In Hatch, environments are treated as isolated areas where you can execute arbitrary commands at runtime. For example, you can define a single test environment with named scripts that runs unit vs non-unit tests, each command being potentially very long but named however you wish so you get to control the interface. Since environments are treated as places where work is performed, you can also spawn a shell into any which will execute a subprocess that automatically drops into your shell of choice. Your shell will be configured appropriately like python on PATH being updated and the prompt being changed to reflect the chosen environment.

  • Configuration:

    • nox config is defined in Python which often leads to increased verbosity and makes it challenging to onboard folks compared to a standardized format with known behaviors.
  • Extensibility:
    • tox allows for extending most aspects of its functionality however the API is so low-level and attached to internals that creating plugins may be challenging. For example, here is a tox plugin that was migrated to an equivalent Hatch environment collector plugin.
    • nox is configured with Python so for the local project you can do whatever you want, however there is no concept of third-party plugins per se. To achieve that, you must usually use a package that wraps nox and use that package's imports instead (example).

Why not?:

If you are using nox and you wish to migrate, and for some reason you notify sessions, then migration wouldn't be a straight translation but rather you might have to redesign that conditional step.

"},{"location":"why/#python-management","title":"Python management","text":"

Here we compare Python management to that of pyenv.

  • Cross-platform: Hatch allows for the same experience no matter the system whereas pyenv does not support Windows so you must use an entirely different project that tries to emulate the functionality.
  • No build dependencies: Hatch guarantees that every available distribution is prebuilt whereas the alternative requires one to maintain a precise build environment which differs by platform and potentially Python version. Another benefit to this is extremely fast installations since the distributions are simply downloaded and unpacked.
  • Optimized by default: The CPython distributions are built with profile guided optimization and link-time optimization, resulting in a 10-30% performance improvement depending on the workload. These distributions have seen wide adoption throughout the industry and are even used by the build system Bazel.
  • Simplicity: Hatch treats Python installations as just another directory that one would add to PATH. It can do this for you or you can manage PATH yourself, even allowing for custom install locations. On the other hand, pyenv operates by adding shims which then act as wrappers around the actual underlying binaries. This has many unfortunate side effects:
    • It is incumbent upon the user to manage which specific Python comes first via the CLI, switch when necessary, and/or have a mental model of which versions are exposed globally and locally per-project. This can become confusing quite quickly. When working with Hatch, your global Python installations are only important insofar as they are on PATH somewhere since environments do not use them directly but rather create virtual environments from them, always using a version that is compatible with your project.
    • Configuration is required for each shell to properly set up pyenv on start, leading to inconsistencies when running processes that do not spawn a shell.
    • Debugging issues with Python search paths can be extremely difficult, especially for users of software. If you or users have ever ran into an issue where code was being executed that you did not anticipate, the issue is almost always pyenv influencing the python on PATH.

Why not?:

Currently, Hatch does not allow for the installation of specific patch release versions but rather only uses minor release granularity that tracks the latest patch release. If specific patch releases are important to you then it is best to use an alternative installation mechanism.

"},{"location":"blog/","title":"Blog","text":""},{"location":"blog/2024/05/02/hatch-v1100/","title":"Hatch v1.10.0","text":"

Hatch v1.10.0 brings a test command, support for UV, and a Python script runner.

"},{"location":"blog/2024/05/02/hatch-v1100/#test-command","title":"Test command","text":"

The new test command allows you to easily run tests for your project on multiple versions of Python. The default behavior follows best practices, using pytest with select plugins for test execution and coverage.py for code coverage measurement.

The command is designed to be both simple to use while also satisfying the needs of most projects. For example, the following shows Hatch running tests for Jinja in all environments in the default matrix:

Here is us testing Rich, with a bit of configuration:

See the tutorial for a detailed walk-through and the config reference for options.

"},{"location":"blog/2024/05/02/hatch-v1100/#uv","title":"UV","text":"

The package installer UV, brought to you by the same folks behind Ruff, is now supported. In any environment, you can set the installer option to uv to use UV in place of virtualenv & pip for virtual environment creation and dependency management, respectively. This often results in a significant performance benefit.

For example, if you wanted to enable this functionality for the default environment, you could set the following:

pyproject.toml hatch.toml
[tool.hatch.envs.default]\ninstaller = \"uv\"\n
[envs.default]\ninstaller = \"uv\"\n

Semi-internal environments like those used for testing and static analysis have this enabled by default.

See the how-to guide for more information about switching the installer.

"},{"location":"blog/2024/05/02/hatch-v1100/#python-script-runner","title":"Python script runner","text":"

The run command now supports executing Python scripts with inline metadata as standardized by PEP 723.

As an example, consider the following script:

script.py
# /// script\n# requires-python = \">=3.11\"\n# dependencies = [\n#   \"httpx\",\n#   \"rich\",\n# ]\n# ///\n\nimport httpx\nfrom rich.pretty import pprint\n\nresp = httpx.get(\"https://peps.python.org/api/peps.json\")\ndata = resp.json()\npprint([(k, v[\"title\"]) for k, v in data.items()][:10])\n

If you run the script for the first time as follows:

hatch run script.py\n

Hatch will create a dedicated environment for that script using a version of Python greater than or equal to 3.11 with dependencies httpx and rich.

See the how-to guide for more information.

"},{"location":"blog/2024/05/02/hatch-v1100/#static-analysis","title":"Static analysis","text":"

The environment used for static analysis is now completely configurable such that you can fully alter the underlying behavior of the fmt command (see the how-to).

Additionally, Ruff has been updated to version 1.4.0 and the rules selected by default have been updated accordingly. Check out their blog post about how the new hand-written parser has made it twice as fast!

"},{"location":"blog/2024/05/02/hatch-v1100/#community-highlights","title":"Community highlights","text":""},{"location":"blog/2024/05/02/hatch-v1100/#visual-studio-code","title":"Visual Studio Code","text":"

Visual Studio Code announced support for Hatch environments in their latest release. This means that you can now easily discover and select Hatch environments for your projects directly from the editor.

See the how-to guide for detailed instructions.

"},{"location":"blog/2024/05/02/hatch-v1100/#cmake-build-plugin","title":"CMake build plugin","text":"

A new release of the extension module builder scikit-build-core has introduced a build plugin for Hatchling. This means that you can use Hatchling as your build backend while also shipping extension modules built with CMake.

To get started, add the dependency to your build requirements:

pyproject.toml
[build-system]\nrequires = [\"hatchling>=1.24.2\", \"scikit-build-core~=0.9.3\"]\nbuild-backend = \"hatchling.build\"\n

Then explicitly enable the experimental option (acknowledging that the plugin will move to a dedicated package in the future):

pyproject.toml hatch.toml
[tool.hatch.build.targets.wheel.hooks.scikit-build]\nexperimental = true\n
[build.targets.wheel.hooks.scikit-build]\nexperimental = true\n

At this point, you can create your CMakeLists.txt file as usual and start building your extension modules with CMake! Check out the dedicated example project for a complete demonstration.

"},{"location":"blog/2024/05/02/hatch-v1100/#meta","title":"Meta","text":""},{"location":"blog/2024/05/02/hatch-v1100/#docs","title":"Docs","text":"

The efforts toward documentation improvements have increased substantially and the priorities have shifted. From now on expect to see far more tutorials and how-to guides rather than just reference material.

"},{"location":"blog/2024/05/02/hatch-v1100/#future","title":"Future","text":"

Upcoming features include:

  • workspaces functionality similar to Cargo
  • commands to manage dependencies
  • Windows release artifacts signed by the PSF (just like macOS)
  • performance improvements for both the CLI and the Hatchling build system
"},{"location":"blog/2024/05/02/hatch-v1100/#support","title":"Support","text":"

If you or your organization finds value in what Hatch provides, consider a sponsorship to assist with maintenance and more rapid development!

"},{"location":"blog/2022/10/08/hatch-v160/","title":"Hatch v1.6.0","text":"

Hatch v1.6.0 brings improvements to build environments, better handling of dynamic metadata, and support for tools like Visual Studio Code.

"},{"location":"blog/2022/10/08/hatch-v160/#build-environments","title":"Build environments","text":"

Originally, the environment interface method for providing builder sub-environments was intended to be used in conjunction with some cleanup logic in order to provide a fresh setup every time. However, this is unnecessary in practice because build dependencies rarely change.

Without caching, repeat build environment use is slow which affects the following scenarios:

  • the build command
  • commands that read project metadata, like dep hash, if any fields are set dynamically

Now a new environment interface method build_environment_exists is used by Hatch to determine whether or not it has already been created, for implementations that have a caching mechanism.

The virtual environment type now uses this method to cache build environments.

"},{"location":"blog/2022/10/08/hatch-v160/#project-metadata","title":"Project metadata","text":"

Dynamically defined metadata is now supported everywhere, thanks to the new caching of virtual build environments.

A project metadata command is introduced that displays the fully resolved metadata. The output format is JSON unless a field is specified as an argument.

For example, if you checkout a project that is built by Hatch, like FastAPI, and run:

hatch project metadata readme\n

only the readme text will be displayed. If the content is in Markdown, then Rich will render it directly in your terminal:

"},{"location":"blog/2022/10/08/hatch-v160/#virtual-environment-location","title":"Virtual environment location","text":"

The virtual environment type now uses a flat layout for storage in the configured virtual environment directory if the directory resides somewhere within the project root or if it is set to a .virtualenvs directory within the user's home directory.

For example, if you define the following Hatch configuration:

config.toml
[dirs.env]\nvirtual = \".hatch\"\n

and the following matrix:

pyproject.toml hatch.toml
[[tool.hatch.envs.test.matrix]]\npython = [\"3.7\", \"3.8\", \"3.9\", \"3.10\", \"3.11\"]\n
[[envs.test.matrix]]\npython = [\"3.7\", \"3.8\", \"3.9\", \"3.10\", \"3.11\"]\n

then locating environments with the following command:

hatch env find test\n

will show that the general directory structure is:

.hatch\n\u251c\u2500\u2500 test.py3.7\n\u251c\u2500\u2500 test.py3.8\n\u251c\u2500\u2500 test.py3.9\n\u251c\u2500\u2500 test.py3.10\n\u2514\u2500\u2500 test.py3.11\n

This flat structure is required for detection of virtual environments by tools like Visual Studio Code and PyCharm.

Additionally, the virtual environment type now supports a path option to specify an explicit path that all inherited environments will share, such as the common .venv.

"},{"location":"blog/2022/10/08/hatch-v160/#migration-script-improvements","title":"Migration script improvements","text":"

The script used to migrate existing projects from setuptools has been improved to handle more edge cases that were encountered in the wild and now no longer modifies the formatting of existing pyproject.toml configuration.

"},{"location":"blog/2022/10/08/hatch-v160/#hatchling","title":"Hatchling","text":"

Hatch now depends on Hatchling v1.11.0, which was also just released.

"},{"location":"blog/2022/10/08/hatch-v160/#environment-version-source","title":"Environment version source","text":"

A new env version source is available that allows for the project version to be defined by an environment variable.

"},{"location":"blog/2022/10/08/hatch-v160/#relaxed-version-bumping","title":"Relaxed version bumping","text":"

The standard version scheme now supports a validate-bump option that when set to false will forego the check when updating the version that the desired version is higher than the current version.

This use case comes from Project Jupyter:

A common pattern we use in Jupyter is to bump to a .dev0 minor version bump after making a release. If we have a bug fix that needs to go out in the interim, we'd rather not be forced to create a branch every time.

"},{"location":"blog/2023/12/11/hatch-v180/","title":"Hatch v1.8.0","text":"

Hatch v1.8.0 brings Python distribution management, static analysis and formatting backed by Ruff, and binaries for every platform.

"},{"location":"blog/2023/12/11/hatch-v180/#installation-made-easy","title":"Installation made easy","text":"

One thing that has been a perpetual problem for Hatch and other Python applications is that Python itself is a dependency. You, and more importantly your users, need to in some way get Python before your software can even be used. The recommended way to go about that is platform-dependent and even differs based on your target audience. I viewed this as a central UX problem for Hatch and so severe that I took a bit of a hiatus to solve it.

Luckily, I have to my satisfaction solved this problem in the form of PyApp. It is a runtime installer for Python projects written in Rust. Apps are distributed as standalone executables as users have come to expect and bootstrapping occurs upon the first invocation. Here is an example of what you would see the first time you run a binary from this release:

Now that we have binaries, creating installers for different platforms becomes trivial. Starting with this release not only are binaries available for every platform but also we have installers for Windows and macOS. The installer for macOS is signed using a certificate from the same account used to sign the official distributions from https://www.python.org, so users will not get any security pop-ups. Shout out to @ewdurbin for their extreme generosity in setting up multiple certificates in their free time!

These installers and binaries are now the recommended way to install and update Hatch. These binaries have built-in management so you can update to the latest version by running hatch self update.

Windows signing

In future we will sign the installers for Windows but I did not have time to look into how that works. macOS signing took way longer than I anticipated

"},{"location":"blog/2023/12/11/hatch-v180/#python-management","title":"Python management","text":"

For a long time I and other users have desired that Hatch gain the ability to manage Python distributions. In my mind this was always blocked on a better installation experience because there was sort of a chicken-or-egg problem where you want a Python manager but you first need Python. No longer is that the case!

The new python command group allows for easy installation of various distributions to arbitrary locations which are then added to your PATH by default. Hatch supports CPython and PyPy distributions:

"},{"location":"blog/2023/12/11/hatch-v180/#virtual-environment-python-resolution","title":"Virtual environment Python resolution","text":"

The virtual environment type is now far more intelligent when resolving the parent distribution to use and guarantees that, when no specific version is requested, the resolved distribution will always be compatible with the project.

Additionally, when a requested version cannot be found on PATH it will automatically be downloaded and managed internally.

"},{"location":"blog/2023/12/11/hatch-v180/#static-analysis","title":"Static analysis","text":"

There is a new fmt command, backed entirely by Ruff, that checks and fixes your code for formatting and linting issues.

Starting with this release, Hatch maintains default settings that are guaranteed to be up-to-date and represent best practices for programming in modern Python. The idea is to provide defaults that are so broadly applicable that the majority of users will maintain little if any of their own overrides.

The default behavior is internal management of settings to provide an OOTB experience that works. It is recommended however that you persist the default config file in version control so that other tools like IDEs can utilize your full configuration.

Since Ruff is now provided as a built-in feature, new project templates no longer have such configuration and are much less verbose.

"},{"location":"blog/2023/12/11/hatch-v180/#build-improvements","title":"Build improvements","text":"

Building projects that do not use Hatchling as a backend is now supported and such builds are managed with the standard build tool.

The bridge between Hatch and the Hatchling CLI has been removed. Previously, the builder would send serialized messages to Hatch that would contain the desired content and style for each line of output. This was done in an effort to allow builder and build hook plugins to output pretty messages without actually requiring a dependency like Rich. A problem that arises with this is that builders that invoke subprocesses will not display ANSI codes as one might expect and will lose out on the interactive experience of such invocations, like the built-in binary builder plugin calling cargo build. So now everything is simpler at the expense of no colored output without manual logic, or adding a dependency if you're a third-party plugin.

"},{"location":"blog/2023/12/11/hatch-v180/#faster-environment-usage","title":"Faster environment usage","text":"

Spawning a shell or running commands within environments always first checks that your project's dependencies are satisfied and if not synchronizes the environment with what is defined. Previously, this had the potential to be quite slow for projects that have many dependencies.

Now the set of dependency definitions is hashed and no check is performed if the hash is the same as before, significantly speeding up environment usage in most cases.

"},{"location":"blog/2023/12/11/hatch-v180/#hatchling","title":"Hatchling","text":"

Hatch now depends on Hatchling v1.19.0, which was also just released.

"},{"location":"blog/2023/12/11/hatch-v180/#better-defaults","title":"Better defaults","text":"

Hatchling is all about providing the best possible defaults, even at the expense of backward compatibility. In this release, there are two breaking changes that provide a much better user experience and were in fact requested by users.

  • Both the force-include option and the force_include_editable wheel build data setting now raise errors if source paths do not exist.
  • The wheel build target now raises an error when no file inclusion options have been defined and none of its heuristics to determine what to ship are satisfied.
"},{"location":"blog/2023/12/11/hatch-v180/#binary-build-target","title":"Binary build target","text":"

A new binary build target is now stable that allows for the building of standalone binaries for projects. This is what Hatch itself uses for its binaries.

"},{"location":"blog/2023/12/11/hatch-v180/#meta","title":"Meta","text":""},{"location":"blog/2023/12/11/hatch-v180/#why-hatch","title":"Why Hatch?","text":"

A new page has been introduced that discusses the value proposition of Hatch and Hatchling in comparison to alternatives. Currently, it only addresses a few features but in future this page will become more comprehensive.

"},{"location":"blog/2023/12/11/hatch-v180/#future","title":"Future","text":"

Upcoming features include a test command, commands to manage dependencies, and workspaces functionality similar to Cargo that will make managing monorepos far easier.

Next year there will be two large efforts that you should expect to see:

  1. A significant amount of my free time (and some at work) will be devoted to introducing lock file functionality in Hatch and trying to get whatever that happens to be standardized.

    I met with @brettcannon about his thoughts post-PEP 665 and about mousebender. I also met with the prefix.dev team about rip and was fortunate enough to be shown a demo before its official announcement.

    At the moment, the two options I see are to either go all in and contribute to mousebender or rely on the Prefix folks and use rip. The latter has the benefit of potentially supporting Conda as a side effect with the downside of being quite new with the spec firmly out of our control. The former has the benefit of being able to easily gain institutional support from the Python packaging team and each of our employers with the downside being a significant amount of work needing to be done.

  2. When @henryiii is able to get some free time away from teaching I plan to work with him once again and push very hard for the Python build ecosystem to adopt the extensionlib approach.

    I am of the opinion that the Python community has not fully completed the expressed outcome of PEP 517 in that build backends are still (for the most part) reliant on setuptools for building non-Python code bases.

    Basically, there are components that interact with compilers to produce extension modules and components that pack files into an archive which we call a build backend. These are two distinct pieces of functionality and my view is that there should be an API that allows backends to consume extension module builders to find out where things got created and where they should be shipped inside archives.

    In this hypothetical future any build backend would be able to trigger the building of extension modules based on user configuration.

"},{"location":"blog/2023/12/11/hatch-v180/#support","title":"Support","text":"

If you or your organization finds value in what Hatch provides, consider a sponsorship to assist with maintenance and more rapid development!

"},{"location":"blog/2023/12/18/hatch-v190/","title":"Hatch v1.9.0","text":"

Hatch v1.9.0 brings improvements to static analysis and important bug fixes.

"},{"location":"blog/2023/12/18/hatch-v190/#static-analysis","title":"Static analysis","text":"

The default version of Ruff has been increased to v0.1.8. This release brings formatting capabilities to docstrings and Hatch enables this by default with line length set to 80. This length was chosen as the default because it plays nicely with the rendering of the most popular themes for Python documentation, such as Material for MkDocs and Furo.

Additionally, it is now possible for projects to pin to specific versions of Ruff for upgrading at a later time:

pyproject.toml hatch.toml
[tool.hatch.envs.hatch-static-analysis]\ndependencies = [\"ruff==X.Y.Z\"]\n
[envs.hatch-static-analysis]\ndependencies = [\"ruff==X.Y.Z\"]\n
"},{"location":"blog/2023/12/18/hatch-v190/#notable-fixes","title":"Notable fixes","text":"
  • Python resolution for environments that do not install the project is no longer bound by the project's Python requirement.
  • Fixed an edge case for out-of-the-box static analysis when there was existing configuration.
  • Compatibility checks for environments no longer occur if the environment is already created. This significantly increases the responsiveness of environment usage.
"},{"location":"cli/about/","title":"CLI usage","text":""},{"location":"cli/about/#verbosity","title":"Verbosity","text":"

The amount of displayed output is controlled solely by the -v/--verbose (environment variable HATCH_VERBOSE) and -q/--quiet (environment variable HATCH_QUIET) root options.

The levels are documented here.

"},{"location":"cli/about/#project-awareness","title":"Project awareness","text":"

No matter the mode, Hatch will always change to the project's root directory for entering or running commands in environments.

"},{"location":"cli/about/#tab-completion","title":"Tab completion","text":"

Completion is achieved by saving a script and then executing it as a part of your shell's startup sequence.

Afterward, you'll need to start a new shell in order for the changes to take effect.

BashZ shellfish

Save the script somewhere:

_HATCH_COMPLETE=bash_source hatch > ~/.hatch-complete.bash\n

Source the file in ~/.bashrc (or ~/.bash_profile if on macOS):

. ~/.hatch-complete.bash\n

Save the script somewhere:

_HATCH_COMPLETE=zsh_source hatch > ~/.hatch-complete.zsh\n

Source the file in ~/.zshrc:

. ~/.hatch-complete.zsh\n

Save the script in ~/.config/fish/completions:

_HATCH_COMPLETE=fish_source hatch > ~/.config/fish/completions/hatch.fish\n
"},{"location":"cli/reference/","title":"hatch","text":"

Usage:

hatch [OPTIONS] COMMAND [ARGS]...\n

Options:

Name Type Description Default --env, -e text The name of the environment to use [env var: HATCH_ENV] default --project, -p text The name of the project to work on [env var: HATCH_PROJECT] None --verbose, -v integer range (0 and above) Increase verbosity (can be used additively) [env var: HATCH_VERBOSE] 0 --quiet, -q integer range (0 and above) Decrease verbosity (can be used additively) [env var: HATCH_QUIET] 0 --color / --no-color boolean Whether or not to display colored output (default is auto-detection) [env vars: FORCE_COLOR/NO_COLOR] None --interactive / --no-interactive boolean Whether or not to allow features like prompts and progress bars (default is auto-detection) [env var: HATCH_INTERACTIVE] None --data-dir text The path to a custom directory used to persist data [env var: HATCH_DATA_DIR] None --cache-dir text The path to a custom directory used to cache data [env var: HATCH_CACHE_DIR] None --config text The path to a custom config file to use [env var: HATCH_CONFIG] None --version boolean Show the version and exit. False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-build","title":"hatch build","text":"

Build a project.

Usage:

hatch build [OPTIONS] [LOCATION]\n

Options:

Name Type Description Default --target, -t text The target to build, overriding project defaults. This may be selected multiple times e.g. -t sdist -t wheel None --hooks-only boolean Whether or not to only execute build hooks [env var: HATCH_BUILD_HOOKS_ONLY] False --no-hooks boolean Whether or not to disable build hooks [env var: HATCH_BUILD_NO_HOOKS] False --ext boolean Whether or not to only execute build hooks for distributing binary Python packages, such as compiling extensions. Equivalent to --hooks-only -t wheel False --clean, -c boolean Whether or not existing artifacts should first be removed [env var: HATCH_BUILD_CLEAN] False --clean-hooks-after boolean Whether or not build hook artifacts should be removed after each build [env var: HATCH_BUILD_CLEAN_HOOKS_AFTER] False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-clean","title":"hatch clean","text":"

Remove build artifacts.

Usage:

hatch clean [OPTIONS] [LOCATION]\n

Options:

Name Type Description Default --target, -t text The target with which to remove artifacts, overriding project defaults. This may be selected multiple times e.g. -t sdist -t wheel None --hooks-only boolean Whether or not to only remove artifacts from build hooks [env var: HATCH_BUILD_HOOKS_ONLY] False --no-hooks boolean Whether or not to ignore artifacts from build hooks [env var: HATCH_BUILD_NO_HOOKS] False --ext boolean Whether or not to only remove artifacts from build hooks for distributing binary Python packages, such as compiled extensions. Equivalent to --hooks-only -t wheel False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-config","title":"hatch config","text":"

Manage the config file

Usage:

hatch config [OPTIONS] COMMAND [ARGS]...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-config-explore","title":"hatch config explore","text":"

Open the config location in your file manager.

Usage:

hatch config explore [OPTIONS]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-config-find","title":"hatch config find","text":"

Show the location of the config file.

Usage:

hatch config find [OPTIONS]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-config-restore","title":"hatch config restore","text":"

Restore the config file to default settings.

Usage:

hatch config restore [OPTIONS]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-config-set","title":"hatch config set","text":"

Assign values to config file entries. If the value is omitted, you will be prompted, with the input hidden if it is sensitive.

Usage:

hatch config set [OPTIONS] KEY [VALUE]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-config-show","title":"hatch config show","text":"

Show the contents of the config file.

Usage:

hatch config show [OPTIONS]\n

Options:

Name Type Description Default --all, -a boolean Do not scrub secret fields False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-config-update","title":"hatch config update","text":"

Update the config file with any new fields.

Usage:

hatch config update [OPTIONS]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-dep","title":"hatch dep","text":"

Manage environment dependencies

Usage:

hatch dep [OPTIONS] COMMAND [ARGS]...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-dep-hash","title":"hatch dep hash","text":"

Output a hash of the currently defined dependencies.

Usage:

hatch dep hash [OPTIONS]\n

Options:

Name Type Description Default --project-only, -p boolean Whether or not to exclude environment dependencies False --env-only, -e boolean Whether or not to exclude project dependencies False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-dep-show","title":"hatch dep show","text":"

Display dependencies in various formats

Usage:

hatch dep show [OPTIONS] COMMAND [ARGS]...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-dep-show-requirements","title":"hatch dep show requirements","text":"

Enumerate dependencies as a list of requirements.

Usage:

hatch dep show requirements [OPTIONS]\n

Options:

Name Type Description Default --project-only, -p boolean Whether or not to exclude environment dependencies False --env-only, -e boolean Whether or not to exclude project dependencies False --feature, -f text Whether or not to only show the dependencies of the specified features None --all boolean Whether or not to include the dependencies of all features False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-dep-show-table","title":"hatch dep show table","text":"

Enumerate dependencies in a tabular format.

Usage:

hatch dep show table [OPTIONS]\n

Options:

Name Type Description Default --project-only, -p boolean Whether or not to exclude environment dependencies False --env-only, -e boolean Whether or not to exclude project dependencies False --lines, -l boolean Whether or not to show lines between table rows False --ascii boolean Whether or not to only use ASCII characters False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-env","title":"hatch env","text":"

Manage project environments

Usage:

hatch env [OPTIONS] COMMAND [ARGS]...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-env-create","title":"hatch env create","text":"

Create environments.

Usage:

hatch env create [OPTIONS] [ENV_NAME]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-env-find","title":"hatch env find","text":"

Locate environments.

Usage:

hatch env find [OPTIONS] [ENV_NAME]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-env-prune","title":"hatch env prune","text":"

Remove all environments.

Usage:

hatch env prune [OPTIONS]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-env-remove","title":"hatch env remove","text":"

Remove environments.

Usage:

hatch env remove [OPTIONS] [ENV_NAME]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-env-run","title":"hatch env run","text":"

Run commands within project environments.

The -e/--env option overrides the equivalent root option and the HATCH_ENV environment variable.

The -i/--include and -x/--exclude options may be used to include or exclude certain variables, optionally followed by specific comma-separated values, and may be selected multiple times. For example, if you have the following configuration:

pyproject.toml hatch.toml
[[tool.hatch.envs.test.matrix]]\npython = [\"3.9\", \"3.10\"]\nversion = [\"42\", \"3.14\", \"9000\"]\n
[[envs.test.matrix]]\npython = [\"3.9\", \"3.10\"]\nversion = [\"42\", \"3.14\", \"9000\"]\n

then running:

hatch env run -i py=3.10 -x version=9000 test:pytest\n

would execute pytest in the environments test.py3.10-42 and test.py3.10-3.14. Note that py may be used as an alias for python.

Note

The inclusion option is treated as an intersection while the exclusion option is treated as a union i.e. an environment must match all of the included variables to be selected while matching any of the excluded variables will prevent selection.

Usage:

hatch env run [OPTIONS] ARGS...\n

Options:

Name Type Description Default --env, -e text The environments to target None --include, -i text The matrix variables to include None --exclude, -x text The matrix variables to exclude None --filter, -f text The JSON data used to select environments None --force-continue boolean Run every command and if there were any errors exit with the first code False --ignore-compat boolean Ignore incompatibility when selecting specific environments False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-env-show","title":"hatch env show","text":"

Show the available environments.

Usage:

hatch env show [OPTIONS] [ENVS]...\n

Options:

Name Type Description Default --ascii boolean Whether or not to only use ASCII characters False --json boolean Whether or not to output in JSON format False --internal, -i boolean Show internal environments False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-fmt","title":"hatch fmt","text":"

Format and lint source code.

Usage:

hatch fmt [OPTIONS] [ARGS]...\n

Options:

Name Type Description Default --check boolean Only check for errors rather than fixing them False --linter, -l boolean Only run the linter False --formatter, -f boolean Only run the formatter False --sync boolean Sync the default config file with the current version of Hatch False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-new","title":"hatch new","text":"

Create or initialize a project.

Usage:

hatch new [OPTIONS] [NAME] [LOCATION]\n

Options:

Name Type Description Default --interactive, -i boolean Interactively choose details about the project False --cli boolean Give the project a command line interface False --init boolean Initialize an existing project False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-project","title":"hatch project","text":"

View project information

Usage:

hatch project [OPTIONS] COMMAND [ARGS]...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-project-metadata","title":"hatch project metadata","text":"

Display project metadata.

If you want to view the raw readme file without rendering, you can use a JSON parser like jq:

hatch project metadata | jq -r .readme\n

Usage:

hatch project metadata [OPTIONS] [FIELD]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-publish","title":"hatch publish","text":"

Publish build artifacts.

Usage:

hatch publish [OPTIONS] [ARTIFACTS]...\n

Options:

Name Type Description Default --repo, -r text The repository with which to publish artifacts [env var: HATCH_INDEX_REPO] None --user, -u text The user with which to authenticate [env var: HATCH_INDEX_USER] None --auth, -a text The credentials to use for authentication [env var: HATCH_INDEX_AUTH] None --ca-cert text The path to a CA bundle [env var: HATCH_INDEX_CA_CERT] None --client-cert text The path to a client certificate, optionally containing the private key [env var: HATCH_INDEX_CLIENT_CERT] None --client-key text The path to the client certificate's private key [env var: HATCH_INDEX_CLIENT_KEY] None --no-prompt, -n boolean Disable prompts, such as for missing required fields False --initialize-auth boolean Save first-time authentication information even if nothing was published False --publisher, -p text The publisher plugin to use (default is index) [env var: HATCH_PUBLISHER] index --option, -o text Options to pass to the publisher plugin. This may be selected multiple times e.g. -o foo=bar -o baz=23 [env var: HATCH_PUBLISHER_OPTIONS] None --yes, -y boolean Confirm without prompting when the plugin is disabled False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-python","title":"hatch python","text":"

Manage Python installations

Usage:

hatch python [OPTIONS] COMMAND [ARGS]...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-python-find","title":"hatch python find","text":"

Locate Python binaries.

Usage:

hatch python find [OPTIONS] NAME\n

Options:

Name Type Description Default -p, --parent boolean Show the parent directory of the Python binary False --dir, -d text The directory in which distributions reside None --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-python-install","title":"hatch python install","text":"

Install Python distributions.

You may select all to install all compatible distributions:

hatch python install all\n

You can set custom sources for distributions by setting the HATCH_PYTHON_SOURCE_<NAME> environment variable where <NAME> is the uppercased version of the distribution name with periods replaced by underscores e.g. HATCH_PYTHON_SOURCE_PYPY3_10.

Usage:

hatch python install [OPTIONS] NAMES...\n

Options:

Name Type Description Default --private boolean Do not add distributions to the user PATH False --update, -u boolean Update existing installations False --dir, -d text The directory in which to install distributions, overriding configuration None --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-python-remove","title":"hatch python remove","text":"

Remove Python distributions.

You may select all to remove all installed distributions:

hatch python remove all\n

Usage:

hatch python remove [OPTIONS] NAMES...\n

Options:

Name Type Description Default --dir, -d text The directory in which distributions reside None --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-python-show","title":"hatch python show","text":"

Show the available Python distributions.

Usage:

hatch python show [OPTIONS]\n

Options:

Name Type Description Default --ascii boolean Whether or not to only use ASCII characters False --dir, -d text The directory in which distributions reside None --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-python-update","title":"hatch python update","text":"

Update Python distributions.

You may select all to update all installed distributions:

hatch python update all\n

Usage:

hatch python update [OPTIONS] NAMES...\n

Options:

Name Type Description Default --dir, -d text The directory in which distributions reside None --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-run","title":"hatch run","text":"

Run commands within project environments. This is a convenience wrapper around the env run command.

If the first argument contains a colon, then the preceding component will be interpreted as the name of the environment to target, overriding the -e/--env root option and the HATCH_ENV environment variable.

If the environment provides matrices, then you may also provide leading arguments starting with a + or - to select or exclude certain variables, optionally followed by specific comma-separated values. For example, if you have the following configuration:

pyproject.toml hatch.toml
[[tool.hatch.envs.test.matrix]]\npython = [\"3.9\", \"3.10\"]\nversion = [\"42\", \"3.14\", \"9000\"]\n
[[envs.test.matrix]]\npython = [\"3.9\", \"3.10\"]\nversion = [\"42\", \"3.14\", \"9000\"]\n

then running:

hatch run +py=3.10 -version=9000 test:pytest\n

would execute pytest in the environments test.py3.10-42 and test.py3.10-3.14. Note that py may be used as an alias for python.

Note

Inclusions are treated as an intersection while exclusions are treated as a union i.e. an environment must match all of the included variables to be selected while matching any of the excluded variables will prevent selection.

Usage:

hatch run [OPTIONS] [ENV:]ARGS...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-self","title":"hatch self","text":"

Manage Hatch

Usage:

hatch self [OPTIONS] COMMAND [ARGS]...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-self-report","title":"hatch self report","text":"

Generate a pre-populated GitHub issue.

Usage:

hatch self report [OPTIONS]\n

Options:

Name Type Description Default --no-open, -n boolean Show the URL instead of opening it False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-self-restore","title":"hatch self restore","text":"

Restore the installation

Usage:

hatch self restore [OPTIONS] [ARGS]...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-self-update","title":"hatch self update","text":"

Install the latest version

Usage:

hatch self update [OPTIONS] [ARGS]...\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-shell","title":"hatch shell","text":"

Enter a shell within a project's environment.

Usage:

hatch shell [OPTIONS] [ENV_NAME]\n

Options:

Name Type Description Default --name text N/A None --path text N/A None --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-status","title":"hatch status","text":"

Show information about the current environment.

Usage:

hatch status [OPTIONS]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-test","title":"hatch test","text":"

Run tests using the hatch-test environment matrix.

If no filtering options are selected, then tests will be run in the first compatible environment found in the matrix with priority given to those matching the current interpreter.

The -i/--include and -x/--exclude options may be used to include or exclude certain variables, optionally followed by specific comma-separated values, and may be selected multiple times. For example, if you have the following configuration:

pyproject.toml hatch.toml
[[tool.hatch.envs.hatch-test.matrix]]\npython = [\"3.9\", \"3.10\"]\nversion = [\"42\", \"3.14\", \"9000\"]\n
[[envs.hatch-test.matrix]]\npython = [\"3.9\", \"3.10\"]\nversion = [\"42\", \"3.14\", \"9000\"]\n

then running:

hatch test -i py=3.10 -x version=9000\n

would run tests in the environments hatch-test.py3.10-42 and hatch-test.py3.10-3.14.

The -py/--python option is a shortcut for specifying the inclusion -i py=....

Note

The inclusion option is treated as an intersection while the exclusion option is treated as a union i.e. an environment must match all of the included variables to be selected while matching any of the excluded variables will prevent selection.

Usage:

hatch test [OPTIONS] [ARGS]...\n

Options:

Name Type Description Default --randomize, -r boolean Randomize the order of test execution False --parallel, -p boolean Parallelize test execution False --retries integer Number of times to retry failed tests None --retry-delay float Seconds to wait between retries None --cover, -c boolean Measure code coverage False --cover-quiet boolean Disable coverage reporting after tests, implicitly enabling --cover False --all, -a boolean Test all environments in the matrix False --python, -py text The Python versions to test, equivalent to: -i py=... None --include, -i text The matrix variables to include None --exclude, -x text The matrix variables to exclude None --show, -s boolean Show information about environments in the matrix False --help boolean Show this message and exit. False"},{"location":"cli/reference/#hatch-version","title":"hatch version","text":"

View or set a project's version.

Usage:

hatch version [OPTIONS] [DESIRED_VERSION]\n

Options:

Name Type Description Default --help boolean Show this message and exit. False"},{"location":"community/contributing/","title":"Contributing","text":"

The usual process to make a contribution is to:

  1. Check for existing related issues
  2. Fork the repository and create a new branch
  3. Make your changes
  4. Make sure formatting, linting and tests passes.
  5. Add tests if possible to cover the lines you added.
  6. Commit, and send a Pull Request.
"},{"location":"community/contributing/#clone-the-repository","title":"Clone the repository","text":"

Clone the hatch repository, cd into it, and create a new branch for your contribution:

cd hatch\ngit checkout -b add-my-contribution\n
"},{"location":"community/contributing/#run-the-tests","title":"Run the tests","text":"

Run the test suite while developing:

hatch run dev\n

Run the test suite with coverage report:

hatch run cov\n

Run the extended test suite with coverage:

hatch run full\n
"},{"location":"community/contributing/#lint","title":"Lint","text":"

Run automated formatting:

hatch run lint:fmt\n

Run full linting and type checking:

hatch run lint:all\n
"},{"location":"community/contributing/#docs","title":"Docs","text":"

Start the documentation in development:

hatch run docs:serve\n

Build and validate the documentation website:

hatch run docs:build-check\n
"},{"location":"community/highlights/","title":"Community highlights","text":""},{"location":"community/highlights/#integration","title":"Integration","text":"
  • Project Jupyter - https://blog.jupyter.org/packaging-for-jupyter-in-2022-c7be64c38926
  • Visual Studio Code - https://code.visualstudio.com/updates/v1_88#_hatch-environment-discovery
"},{"location":"community/highlights/#adoption","title":"Adoption","text":"
  • Black - https://ichard26.github.io/blog/2022/10/black-22.10.0/#goodbye-python-36-and-hello-hatchling
  • \"Switching to Hatch\" - https://andrich.me/2023/08/switching-to-hatch/
"},{"location":"community/users/","title":"Users","text":"

The following is not intended to be a complete enumeration. Be sure to view the development version of this page for an up-to-date listing.

"},{"location":"community/users/#projects","title":"Projects","text":"

aiogram | Apache Airflow | argon2-cffi | attrs | Black | coffea | Colorama | Django Anymail | Django Debug Toolbar | Django NYT | Django OTP | Django OTP Agents | Django OTP Twilio | Django OTP YubiKey | Django Places | Django Wiki | FastAPI | filelock | Fluentd | github3.py | Gradio | HTTPX | iCalendar for Humans | LinkChecker | Litestar | Material for MkDocs | MicroPython | MkDocs | openSUSE | Nox | Packit | pipx | platformdirs | Pydantic | Pygments | PyHamcrest | PyMdown Extensions | Python JSON Schema | Rye | SALib | Spack | Starlette | structlog | tox | Twisted | urllib3 | Uvicorn | virtualenv | Voil\u00e0 | XGBoost | Ypy | yt-dlp

"},{"location":"community/users/#industry","title":"Industry","text":"
  • Anaconda [1|2|3|4|5|6|7]
  • Airbnb [1]
  • Astronomer [1|2|3]
  • Bitwarden [1]
  • Bloomberg [1|2]
  • Blue Robotics [1]
  • Cars.com [1]
  • Cisco [1|2]
  • Databricks [1|2|3]
  • Datadog [1|2|3|4]
  • deepset [1|2]
  • Elastic [1|2|3]
  • Google [1|2|3|4|5|6]
  • IBM [1]
  • JPMorgan Chase [1]
  • Intel Corporation [1|2|3]
  • McKinsey [1|2]
  • Meta [1|2|3]
  • Microsoft [1|2|3|4|5|6]
  • OpenAI [1]
  • Oracle [1]
  • Palo Alto Networks [1]
  • Quansight [1]
  • Red Hat [1|2|3|4|5]
  • Salesforce [1]
  • Snowflake [1]
  • Splunk [1]
  • The Westervelt Company [1|2|3|4|5|6]
  • Virtru [1|2]
  • VMware [1|2|3]
  • Volvo Group [1]
"},{"location":"community/users/#organizations","title":"Organizations","text":"
  • Free Ebook Foundation [1]
  • Greater Paris University Hospitals (AP-HP) [1]
  • Massachusetts General Hospital [1]
  • Let's Encrypt [1]
  • Max Planck Society [1]
  • OpenTelemetry [1|2]
  • Smithsonian Institution [1]
  • The New York Public Library [1]
"},{"location":"community/users/#government","title":"Government","text":"
  • European Molecular Biology Laboratory
    • European Bioinformatics Institute [1]
  • Germany
    • Berlin Institute of Health [1]
    • Helmholtz Munich [1|2]
  • Norway
    • Statistics Norway [1]
  • United Kingdom
    • The Alan Turing Institute [1]
    • Department for Business and Trade [1]
    • The National Archives [1]
  • United States
    • NASA [1]
    • National Institute of Standards and Technology [1|2|3|4|5]
    • National Security Agency [1|2]
    • National Telecommunications and Information Administration [1|2|3|4]
"},{"location":"community/users/#academia","title":"Academia","text":"
  • Brown University
    • Carney Institute for Brain Science [1]
  • Carnegie Mellon University
    • Department of Chemical Engineering [1|2|3|4|5|6]
  • Chinese Academy of Sciences
    • Academy of Mathematics and Systems Science [1]
  • Georgia Institute of Technology
    • Georgia Tech Database Group [1]
  • Harvard University
    • Department of Molecular and Cellular Biology [1]
  • Heidelberg University
    • Center for Molecular Biology [1]
  • Leiden University
    • Leiden University Libraries [1|2]
  • Maastricht University
    • Institute of Data Science [1|2|3|4|5|6|7|8]
  • Massachusetts Institute of Technology
    • Computer Science and Artificial Intelligence Laboratory [1]
    • Digital Humanities [1]
  • Medical University of Innsbruck
    • Institute of Bioinformatics [1]
  • Polytechnique Montr\u00e9al
    • Department of Computer Engineering and Software Engineering [1]
  • Siberian Branch of the Russian Academy of Sciences
    • Institute of Cytology and Genetics [1|2|3|4]
  • Stanford University
    • Empirical Security Research Group [1]
  • University of British Columbia
    • Department of Earth, Ocean and Atmospheric Sciences [1|2|3]
  • University of California, Berkeley
    • Center for Computational Biology [1]
  • University of California, Santa Barbara
    • Department of Computer Science [1]
  • University of Freiburg
    • Freiburg Center for Data Analysis and Modeling [1]
  • University of Illinois Urbana-Champaign
    • Grainger College of Engineering [1]
  • University of Lausanne
    • Department of Computational Biology [1]
  • University of Ljubljana
    • Faculty of Mechanical Engineering [1]
  • University of Massachusetts Amherst
    • College of Information and Computer Sciences [1]
  • University of Oxford
    • Oxford Research Software Engineering [1]
  • University of Pennsylvania
    • Lifespan Informatics and Neuroimaging Center [1|2|3|4]
  • University of Regensburg
    • Spang Lab [1]
  • University of Sussex
    • Predictive Analytics Lab [1]
  • University of Toronto Scarborough
    • utsc-networking [1|2|3|4]
  • University of Washington
    • Interactive Data Lab [1]
    • Virtual Brain Lab [1]
  • University of Wisconsin-Madison
    • Data Science Institute [1]
  • Waseda University
    • Tackeuchi Laboratory [1|2|3|4|5]
  • Wellcome Sanger Institute [1]
"},{"location":"community/users/#research","title":"Research","text":"
  • Clariah [1]
  • CloudDrift [1]
  • Dask [1|2]
  • GAMA [1]
  • IPython [1|2|3]
  • MNE [1|2|3]
  • NIPY [1|2]
  • Project Jupyter
    • Jupyter [1|2|3|4]
    • JupyterLab [1|2|3|4|5]
    • Jupyter Server [1|2|3|4]
  • RAPIDS [1]
  • Scikit-HEP [1|2|3|4|5|6|7|8|9|10]
  • scverse [1|2|3]
  • Spyder [1]
  • "},{"location":"community/users/#security","title":"Security","text":"
    • Armory
    • in-toto
    • The Update Framework
    "},{"location":"community/users/#crypto","title":"Crypto","text":"
    • Ocean Protocol [1]
    "},{"location":"config/build/","title":"Build configuration","text":"

    Build targets are defined as sections within tool.hatch.build.targets:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.<TARGET_NAME>]\n
    [build.targets.<TARGET_NAME>]\n

    Tip

    Although not recommended, you may define global configuration in the tool.hatch.build table. Keys may then be overridden by target config.

    "},{"location":"config/build/#build-system","title":"Build system","text":"

    To be compatible with the broader Python packaging ecosystem, you must define the build system as follows:

    pyproject.toml
    [build-system]\nrequires = [\"hatchling\"]\nbuild-backend = \"hatchling.build\"\n

    The version of hatchling defined here will be used to build all targets.

    Hatchling is a standards-compliant1 build backend and is a dependency of Hatch itself.

    "},{"location":"config/build/#file-selection","title":"File selection","text":""},{"location":"config/build/#vcs","title":"VCS","text":"

    By default, Hatch will respect the first .gitignore or .hgignore file found in your project's root directory or parent directories. Set ignore-vcs to true to disable this behavior:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.sdist]\nignore-vcs = true\n
    [build.targets.sdist]\nignore-vcs = true\n

    Note

    For .hgignore files only glob syntax is supported.

    "},{"location":"config/build/#patterns","title":"Patterns","text":"

    You can set the include and exclude options to select exactly which files will be shipped in each build, with exclude taking precedence. Every entry represents a Git-style glob pattern.

    For example, the following configuration:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.sdist]\ninclude = [\n  \"pkg/*.py\",\n  \"/tests\",\n]\nexclude = [\n  \"*.json\",\n  \"pkg/_compat.py\",\n]\n
    [build.targets.sdist]\ninclude = [\n  \"pkg/*.py\",\n  \"/tests\",\n]\nexclude = [\n  \"*.json\",\n  \"pkg/_compat.py\",\n]\n

    will exclude every file with a .json extension, and will include everything under a tests directory located at the root and every file with a .py extension that is directly under a pkg directory located at the root except for _compat.py.

    "},{"location":"config/build/#artifacts","title":"Artifacts","text":"

    If you want to include files that are ignored by your VCS, such as those that might be created by build hooks, you can use the artifacts option. This option is semantically equivalent to include.

    Note that artifacts are not affected by the exclude option. Artifacts can be excluded by using more explicit paths or by using the ! negation operator. When using the ! operator, the negated pattern(s) must come after the more generic ones.

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.wheel]\nartifacts = [\n  \"*.so\",\n  \"*.dll\",\n  \"!/foo/*.so\",\n]\n
    [build.targets.wheel]\nartifacts = [\n  \"*.so\",\n  \"*.dll\",\n  \"!/foo/*.so\",\n]\n
    "},{"location":"config/build/#explicit-selection","title":"Explicit selection","text":""},{"location":"config/build/#generic","title":"Generic","text":"

    You can use the only-include option to prevent directory traversal starting at the project root and only select specific relative paths to directories or files. Using this option ignores any defined include patterns.

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.sdist]\nonly-include = [\"pkg\", \"tests/unit\"]\n
    [build.targets.sdist]\nonly-include = [\"pkg\", \"tests/unit\"]\n
    "},{"location":"config/build/#packages","title":"Packages","text":"

    The packages option is semantically equivalent to only-include (which takes precedence) except that the shipped path will be collapsed to only include the final component.

    So for example, if you want to ship a package foo that is stored in a directory src you would do:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.wheel]\npackages = [\"src/foo\"]\n
    [build.targets.wheel]\npackages = [\"src/foo\"]\n
    "},{"location":"config/build/#forced-inclusion","title":"Forced inclusion","text":"

    The force-include option allows you to select specific files or directories from anywhere on the file system that should be included and map them to the desired relative distribution path.

    For example, if there was a directory alongside the project root named artifacts containing a file named lib.so and a file named lib.h in your home directory, you could ship both files in a pkg directory with the following configuration:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.wheel.force-include]\n\"../artifacts\" = \"pkg\"\n\"~/lib.h\" = \"pkg/lib.h\"\n
    [build.targets.wheel.force-include]\n\"../artifacts\" = \"pkg\"\n\"~/lib.h\" = \"pkg/lib.h\"\n

    Note

    • Files must be mapped exactly to their desired paths, not to directories.
    • The contents of directory sources are recursively included.
    • To map directory contents directly to the root use / (a forward slash).
    • Sources that do not exist will raise an error.

    Warning

    Files included using this option will overwrite any file path that was already included by other file selection options.

    "},{"location":"config/build/#default-file-selection","title":"Default file selection","text":"

    If no file selection options are provided, then what gets included is determined by each build target.

    "},{"location":"config/build/#excluding-files-outside-packages","title":"Excluding files outside packages","text":"

    If you want to exclude non-artifact files that do not reside within a Python package, set only-packages to true:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.wheel]\nonly-packages = true\n
    [build.targets.wheel]\nonly-packages = true\n
    "},{"location":"config/build/#rewriting-paths","title":"Rewriting paths","text":"

    You can rewrite relative paths to directories with the sources option. For example, the following configuration:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.wheel.sources]\n\"src/foo\" = \"bar\"\n
    [build.targets.wheel.sources]\n\"src/foo\" = \"bar\"\n

    would distribute the file src/foo/file.ext as bar/file.ext.

    If you want to remove path prefixes entirely, rather than setting each to an empty string, you can define sources as an array:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.wheel]\nsources = [\"src\"]\n
    [build.targets.wheel]\nsources = [\"src\"]\n

    If you want to add a prefix to paths, you can use an empty string. For example, the following configuration:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.wheel.sources]\n\"\" = \"foo\"\n
    [build.targets.wheel.sources]\n\"\" = \"foo\"\n

    would distribute the file bar/file.ext as foo/bar/file.ext.

    The packages option itself relies on sources. Defining packages = [\"src/foo\"] for the wheel target is equivalent to the following:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.wheel]\nonly-include = [\"src/foo\"]\nsources = [\"src\"]\n
    [build.targets.wheel]\nonly-include = [\"src/foo\"]\nsources = [\"src\"]\n
    "},{"location":"config/build/#performance","title":"Performance","text":"

    All encountered directories are traversed by default. To skip non-artifact directories that are excluded, set skip-excluded-dirs to true:

    pyproject.toml hatch.toml
    [tool.hatch.build]\nskip-excluded-dirs = true\n
    [build]\nskip-excluded-dirs = true\n

    Warning

    This may result in not shipping desired files. For example, if you want to include the file a/b/c.txt but your VCS ignores a/b, the file c.txt will not be seen because its parent directory will not be entered. In such cases you can use the force-include option.

    "},{"location":"config/build/#reproducible-builds","title":"Reproducible builds","text":"

    By default, build targets will build in a reproducible manner provided that they support that behavior. To disable this, set reproducible to false:

    pyproject.toml hatch.toml
    [tool.hatch.build]\nreproducible = false\n
    [build]\nreproducible = false\n

    When enabled, the SOURCE_DATE_EPOCH environment variable will be used for all build timestamps. If not set, then Hatch will use an unchanging default value.

    "},{"location":"config/build/#output-directory","title":"Output directory","text":"

    When the output directory is not provided to the build command, the dist directory will be used by default. You can change the default to a different directory using a relative or absolute path like so:

    pyproject.toml hatch.toml
    [tool.hatch.build]\ndirectory = \"<PATH>\"\n
    [build]\ndirectory = \"<PATH>\"\n
    "},{"location":"config/build/#dev-mode","title":"Dev mode","text":"

    By default for dev mode environment installations or editable installs, the wheel target will determine which directories should be added to Python's search path based on the selected files.

    If you want to override this detection or perhaps instruct other build targets as well, you can use the dev-mode-dirs option:

    pyproject.toml hatch.toml
    [tool.hatch.build]\ndev-mode-dirs = [\".\"]\n
    [build]\ndev-mode-dirs = [\".\"]\n

    If you don't want to add entire directories to Python's search path, you can enable a more targeted mechanism with the mutually exclusive dev-mode-exact option:

    pyproject.toml hatch.toml
    [tool.hatch.build]\ndev-mode-exact = true\n
    [build]\ndev-mode-exact = true\n

    Warning

    The dev-mode-exact mechanism is not supported by static analysis tools & IDEs, therefore functionality such as autocompletion is unlikely to work.

    "},{"location":"config/build/#build-targets","title":"Build targets","text":"

    A build target can be provided by any builder plugin. There are three built-in build targets: wheel, sdist, and custom.

    "},{"location":"config/build/#dependencies","title":"Dependencies","text":"

    You can specify additional dependencies that will be installed in each build environment, such as for third party builders:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.your-target-name]\ndependencies = [\n  \"your-builder-plugin\"\n]\n
    [build.targets.your-target-name]\ndependencies = [\n  \"your-builder-plugin\"\n]\n

    You can also declare dependence on the project's runtime dependencies with the require-runtime-dependencies option:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.your-target-name]\nrequire-runtime-dependencies = true\n
    [build.targets.your-target-name]\nrequire-runtime-dependencies = true\n

    Additionally, you may declare dependence on specific runtime features of the project with the require-runtime-features option:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.your-target-name]\nrequire-runtime-features = [\n  \"feature1\",\n  \"feature2\",\n]\n
    [build.targets.your-target-name]\nrequire-runtime-features = [\n  \"feature1\",\n  \"feature2\",\n]\n
    "},{"location":"config/build/#versions","title":"Versions","text":"

    If a build target supports multiple build strategies or if there are major changes over time, you can specify exactly which versions you want to build using the versions option:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.<TARGET_NAME>]\nversions = [\n  \"v1\",\n  \"beta-feature\",\n]\n
    [build.targets.<TARGET_NAME>]\nversions = [\n  \"v1\",\n  \"beta-feature\",\n]\n

    See the wheel target for a real world example.

    "},{"location":"config/build/#build-hooks","title":"Build hooks","text":"

    A build hook defines code that will be executed at various stages of the build process and can be provided by any build hook plugin. There is one built-in build hook: custom.

    Build hooks can be applied either globally:

    pyproject.toml hatch.toml
    [tool.hatch.build.hooks.<HOOK_NAME>]\n
    [build.hooks.<HOOK_NAME>]\n

    or to specific build targets:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.<TARGET_NAME>.hooks.<HOOK_NAME>]\n
    [build.targets.<TARGET_NAME>.hooks.<HOOK_NAME>]\n
    "},{"location":"config/build/#dependencies_1","title":"Dependencies","text":"

    You can specify additional dependencies that will be installed in each build environment, such as for third party build hooks:

    pyproject.toml hatch.toml
    [tool.hatch.build.hooks.your-hook-name]\ndependencies = [\n  \"your-build-hook-plugin\"\n]\n
    [build.hooks.your-hook-name]\ndependencies = [\n  \"your-build-hook-plugin\"\n]\n

    You can also declare dependence on the project's runtime dependencies with the require-runtime-dependencies option:

    pyproject.toml hatch.toml
    [tool.hatch.build.hooks.your-hook-name]\nrequire-runtime-dependencies = true\n
    [build.hooks.your-hook-name]\nrequire-runtime-dependencies = true\n

    Additionally, you may declare dependence on specific runtime features of the project with the require-runtime-features option:

    pyproject.toml hatch.toml
    [tool.hatch.build.hooks.your-hook-name]\nrequire-runtime-features = [\n  \"feature1\",\n  \"feature2\",\n]\n
    [build.hooks.your-hook-name]\nrequire-runtime-features = [\n  \"feature1\",\n  \"feature2\",\n]\n
    "},{"location":"config/build/#order-of-execution","title":"Order of execution","text":"

    For each build target, build hooks execute in the order in which they are defined, starting with global hooks.

    As an example, for the following configuration:

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.foo.hooks.hook2]\n\n[tool.hatch.build.hooks.hook3]\n[tool.hatch.build.hooks.hook1]\n
    [build.targets.foo.hooks.hook2]\n\n[build.hooks.hook3]\n[build.hooks.hook1]\n

    When target foo is built, build hook hook3 will be executed first, followed by hook1, and then finally hook2.

    "},{"location":"config/build/#conditional-execution","title":"Conditional execution","text":"

    If you want to disable a build hook by default and control its use by environment variables, you can do so by setting the enable-by-default option to false:

    pyproject.toml hatch.toml
    [tool.hatch.build.hooks.<HOOK_NAME>]\nenable-by-default = false\n
    [build.hooks.<HOOK_NAME>]\nenable-by-default = false\n
    "},{"location":"config/build/#environment-variables","title":"Environment variables","text":"Variable Default Description HATCH_BUILD_CLEAN false Whether or not existing artifacts should first be removed HATCH_BUILD_CLEAN_HOOKS_AFTER false Whether or not build hook artifacts should be removed after each build HATCH_BUILD_HOOKS_ONLY false Whether or not to only execute build hooks HATCH_BUILD_NO_HOOKS false Whether or not to disable all build hooks; this takes precedence over other options HATCH_BUILD_HOOKS_ENABLE false Whether or not to enable all build hooks HATCH_BUILD_HOOK_ENABLE_<HOOK_NAME> false Whether or not to enable the build hook named <HOOK_NAME> HATCH_BUILD_LOCATION dist The location with which to build the targets; only used by the build command
    1. Support for PEP 517 and PEP 660 guarantees interoperability with other build tools.\u00a0\u21a9

    "},{"location":"config/context/","title":"Context formatting","text":"

    You can populate configuration with the values of certain supported fields using the syntax of Python's format strings. Each field interprets the modifier part after the colon differently, if at all.

    "},{"location":"config/context/#global-fields","title":"Global fields","text":"

    Any configuration that declares support for context formatting will always support these fields.

    "},{"location":"config/context/#paths","title":"Paths","text":"Field Description root The root project directory home The user's home directory

    All paths support the following modifiers:

    Modifier Description uri The normalized absolute URI path prefixed by file: real The path with all symbolic links resolved parent The parent of the preceding path

    Tip

    The parent modifier can be chained and may be combined with either the uri or real modifier, with the latter placed at the end. For example:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test]\ndependencies = [\n    \"example-project @ {root:parent:parent:uri}/example-project\",\n]\n
    [envs.test]\ndependencies = [\n    \"example-project @ {root:parent:parent:uri}/example-project\",\n]\n
    "},{"location":"config/context/#system-separators","title":"System separators","text":"Field Description / \\ on Windows, / otherwise ; ; on Windows, : otherwise"},{"location":"config/context/#environment-variables","title":"Environment variables","text":"

    The env field and its modifier allow you to select the value of an environment variable. If the environment variable is not set, you must specify a default value as an additional modifier e.g. {env:PATH:DEFAULT}.

    "},{"location":"config/context/#field-nesting","title":"Field nesting","text":"

    You can insert fields within others. For example, if you wanted a script that displays the value of the environment variable FOO, with a fallback to the environment variable BAR, with its own fallback to the user's home directory, you could do the following:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.scripts]\ndisplay = \"echo {env:FOO:{env:BAR:{home}}}\"\n
    [envs.test.scripts]\ndisplay = \"echo {env:FOO:{env:BAR:{home}}}\"\n
    "},{"location":"config/dependency/","title":"Dependency configuration","text":"

    Project dependencies are defined with PEP 508 strings using optional PEP 440 version specifiers.

    "},{"location":"config/dependency/#version-specifiers","title":"Version specifiers","text":"

    A version specifier consists of a series of version clauses, separated by commas. For example:

    pyproject.toml
    [project]\n...\ndependencies = [\n  \"cryptography\",\n  \"click>=7, <9, != 8.0.0\",\n  \"python-dateutil==2.8.*\",\n  \"numpy~=1.21.4\",\n]\n

    The comma is equivalent to a logical AND operator: a candidate version must match all given version clauses in order to match the specifier as a whole.

    "},{"location":"config/dependency/#operators","title":"Operators","text":"Operators Function ~= Compatible release == Version matching != Version exclusion <=, >= Inclusive ordered comparison <, > Exclusive ordered comparison === Arbitrary equality"},{"location":"config/dependency/#version-matching","title":"Version matching","text":"

    A version matching clause includes the version matching operator == and a version identifier.

    By default, the version matching operator is based on a strict equality comparison: the specified version must be exactly the same as the requested version.

    Clause Allowed versions ==1 1.0.0 ==1.2 1.2.0

    Prefix matching may be requested instead of strict comparison, by appending a trailing .* to the version identifier in the version matching clause. This means that additional trailing segments will be ignored when determining whether or not a version identifier matches the clause.

    Clause Allowed versions ==1.* >=1.0.0, <2.0.0 ==1.2.* >=1.2.0, <1.3.0"},{"location":"config/dependency/#compatible-release","title":"Compatible release","text":"

    A compatible release clause consists of the compatible release operator ~= and a version identifier. It matches any candidate version that is expected to be compatible with the specified version.

    For a given release identifier V.N, the compatible release clause is approximately equivalent to the following pair of comparison clauses:

    >= V.N, == V.*\n

    This operator cannot be used with a single segment version number such as ~=1.

    Clause Allowed versions ~=1.2 >=1.2.0, <2.0.0 ~=1.2.3 >=1.2.3, <1.3.0"},{"location":"config/dependency/#version-exclusion","title":"Version exclusion","text":"

    A version exclusion clause includes the version exclusion operator != and a version identifier.

    The allowed version identifiers and comparison semantics are the same as those of the Version matching operator, except that the sense of any match is inverted.

    "},{"location":"config/dependency/#ordered-comparison","title":"Ordered comparison","text":"

    Inclusive comparisons allow for the version identifier part of clauses whereas exclusive comparisons do not. For example, >=1.2 allows for version 1.2.0 while >1.2 does not.

    Unlike the inclusive ordered comparisons <= and >=, the exclusive ordered comparisons < and > specifically exclude pre-releases, post-releases, and local versions of the specified version.

    "},{"location":"config/dependency/#arbitrary-equality","title":"Arbitrary equality","text":"

    Though heavily discouraged, arbitrary equality comparisons allow for simple string matching without any version semantics, for example ===foobar.

    "},{"location":"config/dependency/#environment-markers","title":"Environment markers","text":"

    Environment markers allow for dependencies to only be installed when certain conditions are met.

    For example, if you need to install the latest version of cryptography that is available for a given Python major version you could define the following:

    cryptography==3.3.2; python_version < \"3\"\ncryptography>=35.0; python_version > \"3\"\n

    Alternatively, if you only need it on Python 3 when running on Windows you could do:

    cryptography; python_version ~= \"3.0\" and platform_system == \"Windows\"\n

    The available environment markers are as follows.

    Marker Python equivalent Examples os_name import osos.name
    • posix
    • java
    sys_platform import syssys.platform
    • linux
    • win32
    • darwin
    platform_machine import platformplatform.machine()
    • x86_64
    platform_python_implementation import platformplatform.python_implementation()
    • CPython
    • Jython
    platform_release import platformplatform.release()
    • 1.8.0_51
    • 3.14.1-x86_64-linode39
    platform_system import platformplatform.system()
    • Linux
    • Windows
    • Darwin
    platform_version import platformplatform.version()
    • 10.0.19041
    • #1 SMP Fri Apr 2 22:23:49 UTC 2021
    python_version import platform'.'.join(platform.python_version_tuple()[:2])
    • 2.7
    • 3.10
    python_full_version import platformplatform.python_version()
    • 2.7.18
    • 3.11.0b1
    implementation_name import syssys.implementation.name
    • cpython
    implementation_version See here
    • 2.7.18
    • 3.11.0b1
    "},{"location":"config/dependency/#features","title":"Features","text":"

    You can select groups of optional dependencies to install using the extras syntax. For example, if a dependency named foo defined the following:

    pyproject.toml
    [project.optional-dependencies]\ncrypto = [\n  \"PyJWT\",\n  \"cryptography\",\n]\nfastjson = [\n  \"orjson\",\n]\ncli = [\n  \"prompt-toolkit\",\n  \"colorama; platform_system == 'Windows'\",\n]\n

    You can select the cli and crypto features like so:

    foo[cli,crypto]==1.*\n

    Note that the features come immediately after the package name, before any version specifiers.

    "},{"location":"config/dependency/#self-referential","title":"Self-referential","text":"

    Feature groups can self-referentially extend others. For example, for a project called awesome-project, the dev feature group in the following pyproject.toml file would select everything in the crypto feature group, plus black:

    pyproject.toml
    [project]\nname = \"awesome-project\"\n\n[project.optional-dependencies]\ncrypto = [\n  \"PyJWT\",\n  \"cryptography\",\n]\ndev = [\n  \"awesome-project[crypto]\",\n  \"black\",\n]\n
    "},{"location":"config/dependency/#direct-references","title":"Direct references","text":"

    Instead of using normal version specifiers and fetching packages from an index like PyPI, you can define exact sources using direct references with an explicit URI.

    Direct references are usually not meant to be used for dependencies of a published project but rather are used for defining dependencies for an environment.

    All direct reference types are prefixed by the package name like:

    <NAME> @ <REFERENCE>\n
    "},{"location":"config/dependency/#version-control-systems","title":"Version control systems","text":"

    Various version control systems (VCS) are supported as long as the associated executable is available along your PATH.

    VCS direct references are defined using one of the following formats:

    <NAME> @ <SCHEME>://<PATH>\n<NAME> @ <SCHEME>://<PATH>@<REVISION>\n

    You may also append a #subdirectory=<PATH> component for specifying the relative path to the Python package when it is not located at the root e.g. #subdirectory=lib/foo.

    For more information, refer to this.

    "},{"location":"config/dependency/#supported-vcs","title":"Supported VCS","text":"GitMercurialSubversionBazaar Executable Schemes Revisions Example git
    • git+file
    • git+https
    • git+ssh
    • git+http
    • git+git
    • git
    • Commit hash
    • Tag name
    • Branch name
    proj @ git+https://github.com/org/proj.git@v1 Executable Schemes Revisions Example hg
    • hg+file
    • hg+https
    • hg+ssh
    • hg+http
    • hg+static-http
    • Revision hash
    • Revision number
    • Tag name
    • Branch name
    proj @ hg+file:///path/to/proj@v1 Executable Schemes Revisions Example svn
    • svn+https
    • svn+ssh
    • svn+http
    • svn+svn
    • svn
    • Revision number
    proj @ svn+file:///path/to/proj Executable Schemes Revisions Example bzr
    • bzr+https
    • bzr+ssh
    • bzr+sftp
    • bzr+lp
    • bzr+http
    • bzr+ftp
    • Revision number
    • Tag name
    proj @ bzr+lp:proj@v1"},{"location":"config/dependency/#local","title":"Local","text":"

    You can install local packages with the file scheme in the following format:

    <NAME> @ file://<HOST>/<PATH>\n

    The <HOST> is only used on Windows systems, where it can refer to a network share. If omitted it is assumed to be localhost and the third slash must still be present.

    The <PATH> can refer to a source archive, a wheel, or a directory containing a Python package.

    Type Unix Windows Source archive proj @ file:///path/to/pkg.tar.gz proj @ file:///c:/path/to/pkg.tar.gz Wheel proj @ file:///path/to/pkg.whl proj @ file:///c:/path/to/pkg.whl Directory proj @ file:///path/to/pkg proj @ file:///c:/path/to/pkg

    Tip

    You may also specify paths relative to your project's root directory on all platforms by using context formatting:

    <NAME> @ {root:uri}/pkg_inside_project\n<NAME> @ {root:parent:uri}/pkg_alongside_project\n
    "},{"location":"config/dependency/#remote","title":"Remote","text":"

    You can install source archives and wheels by simply referring to a URL:

    black @ https://github.com/psf/black/archive/refs/tags/21.10b0.zip\npytorch @ https://download.pytorch.org/whl/cu102/torch-1.10.0%2Bcu102-cp39-cp39-linux_x86_64.whl\n

    An expected hash value may be specified by appending a #<HASH_ALGORITHM>=<EXPECTED_HASH> component:

    requests @ https://github.com/psf/requests/archive/refs/tags/v2.26.0.zip#sha256=eb729a757f01c10546ebd179ae2aec852dd0d7f8ada2328ccf4558909d859985\n

    If the hash differs from the expected hash, the installation will fail.

    It is recommended that only hashes which are unconditionally provided by the latest version of the standard library's hashlib module be used for hashes. As of Python 3.10, that list consists of:

    • md5
    • sha1
    • sha224
    • sha256
    • sha384
    • sha512
    • blake2b
    • blake2s
    "},{"location":"config/dependency/#complex-syntax","title":"Complex syntax","text":"

    The following is an example that uses features and environment markers:

    pkg[feature1,feature2] @ <REFERENCE> ; python_version < \"3.7\"\n

    Note that the space before the semicolon is required.

    "},{"location":"config/hatch/","title":"Hatch configuration","text":"

    Configuration for Hatch itself is stored in a config.toml file located by default in one of the following platform-specific directories.

    Platform Path macOS ~/Library/Application Support/hatch Windows %USERPROFILE%\\AppData\\Local\\hatch Unix $XDG_CONFIG_HOME/hatch (the XDG_CONFIG_HOME environment variable default is ~/.config)

    You can select a custom path to the file using the --config root option or by setting the HATCH_CONFIG environment variable.

    The file can be managed by the config command group.

    "},{"location":"config/hatch/#mode","title":"Mode","text":"

    The mode key controls how Hatch selects the project to work on.

    "},{"location":"config/hatch/#local","title":"Local","text":"config.toml
    mode = \"local\"\n

    By default, Hatch will look for a pyproject.toml file in the current working directory and any parent directories. The directory storing the first found file will be considered the project root.

    "},{"location":"config/hatch/#project","title":"Project","text":"config.toml
    mode = \"project\"\nproject = \"proj1\"\n\n[projects]\nproj1 = \"/path/to/project1\"\nproj2 = {\"location\": \"/path/to/project2\"}\n\n[dirs]\nproject = [\"/path/to/monorepo1\", \"/path/to/monorepo2\"]\n

    In this mode, Hatch will only work on the selected project. The project is located using multiple heuristics:

    1. If the project is defined in the projects table then it must be a string, or an inline table with a location key, that is the full path to the project.
    2. If the project matches a subdirectory in any of the directories listed in dirs.project, then that will be used as the project root.

    An error will occur if the project cannot be found.

    You can use the config set command to change the project you are working on:

    $ hatch config set project proj2\nNew setting:\nproject = \"proj2\"\n

    The project can be selected on a per-command basis with the -p/--project (environment variable HATCH_PROJECT) root option.

    "},{"location":"config/hatch/#aware","title":"Aware","text":"config.toml
    mode = \"aware\"\n

    This is essentially the local mode with a fallback to the project mode.

    "},{"location":"config/hatch/#shell","title":"Shell","text":"

    You can control the shell used to enter environments with the shell key.

    If defined as a string, it must be the name of one of the supported shells and be available along your PATH.

    config.toml
    shell = \"fish\"\n

    If the executable name of your shell differs from the supported name, you can define the shell as a table with name and path keys.

    config.toml
    [shell]\nname = \"bash\"\npath = \"/bin/ash\"\n

    You can change the default arguments used to spawn most shells with the args key. The default for such supported shells is usually [\"-i\"].

    config.toml
    [shell]\nname = \"bash\"\nargs = [\"--login\"]\n
    "},{"location":"config/hatch/#supported","title":"Supported","text":"Shell Name Arguments macOS Windows Unix Almquist shell ash [\"-i\"] Bash bash [\"-i\"] Command Prompt cmd C shell csh [\"-i\"] fish fish [\"-i\"] Nushell nu [] PowerShell pwsh, powershell tcsh tcsh [\"-i\"] xonsh xonsh [\"-i\"] Z shell zsh [\"-i\"]"},{"location":"config/hatch/#default","title":"Default","text":"

    Hatch will attempt to use the current shell based on parent processes. If the shell cannot be determined, then on Windows systems Hatch will use the SHELL environment variable, if present, followed by the COMSPEC environment variable, defaulting to cmd. On all other platforms only the SHELL environment variable will be used, defaulting to bash.

    "},{"location":"config/hatch/#directories","title":"Directories","text":""},{"location":"config/hatch/#data","title":"Data","text":"config.toml
    [dirs]\ndata = \"...\"\n

    This is the directory that is used to persist data. By default it is set to one of the following platform-specific directories.

    Platform Path macOS ~/Library/Application Support/hatch Windows %USERPROFILE%\\AppData\\Local\\hatch Unix $XDG_DATA_HOME/hatch (the XDG_DATA_HOME environment variable default is ~/.local/share)

    You can select a custom path to the directory using the --data-dir root option or by setting the HATCH_DATA_DIR environment variable.

    "},{"location":"config/hatch/#cache","title":"Cache","text":"config.toml
    [dirs]\ncache = \"...\"\n

    This is the directory that is used to cache data. By default it is set to one of the following platform-specific directories.

    Platform Path macOS ~/Library/Caches/hatch Windows %USERPROFILE%\\AppData\\Local\\hatch\\Cache Unix $XDG_CACHE_HOME/hatch (the XDG_CACHE_HOME environment variable default is ~/.cache)

    You can select a custom path to the directory using the --cache-dir root option or by setting the HATCH_CACHE_DIR environment variable.

    "},{"location":"config/hatch/#environments","title":"Environments","text":"config.toml
    [dirs.env]\n<ENV_TYPE> = \"...\"\n

    This determines where to store environments, with every key being the type of environment and the value being the desired storage location.

    For example, if you wanted to store virtual environments in a .virtualenvs directory within your home directory, you could specify the following:

    config.toml
    [dirs.env]\nvirtual = \"~/.virtualenvs\"\n

    Any environment variables are also expanded.

    If the path is not absolute, then it will be relative to the project root. So if you wanted to use a directory named .hatch in each project directory, you could do:

    config.toml
    [dirs.env]\nvirtual = \".hatch\"\n

    Any type of environment that is not explicitly defined will default to <DATA_DIR>/env/<ENV_TYPE>.

    "},{"location":"config/hatch/#python-installations","title":"Python installations","text":"config.toml
    [dirs]\npython = \"...\"\n

    This determines where to install specific versions of Python.

    The following values have special meanings:

    Value Path isolated (default) <DATA_DIR>/pythons"},{"location":"config/hatch/#terminal","title":"Terminal","text":"

    You can configure how all output is displayed using the terminal.styles table. These settings are also applied to all plugins.

    config.toml
    [terminal.styles]\nerror = \"...\"\n...\n

    Cross-platform terminal capabilities are provided by Rich.

    "},{"location":"config/hatch/#output-levels","title":"Output levels","text":"

    The levels of output are as follows. Note that the verbosity indicates the minimum level at which the output is displayed.

    Level Default Verbosity Description debug bold 1 - 3 Messages that are not useful for most user experiences error bold red -2 Messages indicating some unrecoverable error info bold 0 Messages conveying basic information success bold cyan 0 Messages indicating some positive outcome waiting bold magenta 0 Messages shown before potentially time consuming operations warning bold yellow -1 Messages conveying important information

    See the documentation and color reference for guidance on valid values.

    "},{"location":"config/hatch/#spinner","title":"Spinner","text":"

    You can select the sequence used for waiting animations with the spinner option.

    config.toml
    [terminal.styles]\nspinner = \"...\"\n
    "},{"location":"config/metadata/","title":"Configuring project metadata","text":"

    Project metadata is stored in a pyproject.toml file located at the root of a project's tree and is based entirely on the standard.

    "},{"location":"config/metadata/#name","title":"Name (required)","text":"

    The name of the project.

    pyproject.toml
    [project]\nname = \"your-app\"\n
    "},{"location":"config/metadata/#version","title":"Version (required)","text":"pyproject.toml DynamicStatic

    See the dedicated versioning section.

    [project]\n...\ndynamic = [\"version\"]\n\n[tool.hatch.version]\npath = \"...\"\n
    [project]\n...\nversion = \"0.0.1\"\n
    "},{"location":"config/metadata/#description","title":"Description","text":"

    A brief summary of the project.

    pyproject.toml
    [project]\n...\ndescription = '...'\n
    "},{"location":"config/metadata/#readme","title":"Readme","text":"

    The full description of the project.

    pyproject.toml SimpleComplex

    The file extension must be .md, .rst, or .txt.

    [project]\n...\nreadme = \"README.md\"\n

    The content-type field must be set to text/markdown, text/x-rst, or text/plain.

    FileText

    A charset field may also be set to instruct which encoding to use for reading the file, defaulting to utf-8.

    [project]\n...\nreadme = {\"file\" = \"README.md\", \"content-type\" = \"text/markdown\"}\n

    The content-type field must be set to text/markdown or text/x-rst.

    [project]\n...\nreadme = {\"text\" = \"...\", \"content-type\" = \"text/markdown\"}\n

    Note

    If this is defined as a file, then it will always be included in source distributions for consistent builds.

    "},{"location":"config/metadata/#python-support","title":"Python support","text":"

    The Python version requirements of the project.

    pyproject.toml
    [project]\n...\nrequires-python = \">=3.8\"\n
    "},{"location":"config/metadata/#license","title":"License","text":"

    For more information, see PEP 639.

    pyproject.toml SPDX expressionFiles
    [project]\n...\nlicense = \"Apache-2.0 OR MIT\"\n
    PathsGlobs
    [project]\n...\nlicense-files = { paths = [\"LICENSE.txt\"] }\n
    [project]\n...\nlicense-files = { globs = [\"LICENSES/*\"] }\n
    "},{"location":"config/metadata/#ownership","title":"Ownership","text":"

    The people or organizations considered to be the authors or maintainers of the project. The exact meaning is open to interpretation; it may list the original or primary authors, current maintainers, or owners of the package. If the values are the same, prefer only the use of the authors field.

    pyproject.toml
    [project]\n...\nauthors = [\n  { name = \"...\", email = \"...\" },\n]\nmaintainers = [\n  { name = \"...\", email = \"...\" },\n]\n
    "},{"location":"config/metadata/#keywords","title":"Keywords","text":"

    The keywords used to assist in the discovery of the project.

    pyproject.toml
    [project]\n...\nkeywords = [\n  \"...\",\n]\n
    "},{"location":"config/metadata/#classifiers","title":"Classifiers","text":"

    The trove classifiers that apply to the project.

    pyproject.toml
    [project]\n...\nclassifiers = [\n  \"...\",\n]\n
    "},{"location":"config/metadata/#urls","title":"URLs","text":"

    A table of URLs where the key is the URL label and the value is the URL itself.

    pyproject.toml
    [project.urls]\nDocumentation = \"...\"\n\"Source code\" = \"...\"\n
    "},{"location":"config/metadata/#dependencies","title":"Dependencies","text":"

    See the dependency specification page for more information.

    Entries support context formatting and disallow direct references by default.

    "},{"location":"config/metadata/#required","title":"Required","text":"pyproject.toml
    [project]\n...\ndependencies = [\n  \"...\",\n]\n
    "},{"location":"config/metadata/#optional","title":"Optional","text":"pyproject.toml
    [project.optional-dependencies]\noption1 = [\n  \"...\",\n]\noption2 = [\n  \"...\",\n]\n
    "},{"location":"config/metadata/#entry-points","title":"Entry points","text":"

    Entry points are a mechanism for the project to advertise components it provides to be discovered and used by other code.

    "},{"location":"config/metadata/#cli","title":"CLI","text":"

    After installing projects that define CLI scripts, each key will be available along your PATH as a command that will call its associated object.

    pyproject.toml
    [project.scripts]\ncli-name = \"pkg.subpkg:func\"\n

    Using the above example, running cli-name would essentially execute the following Python script:

    import sys\n\nfrom pkg.subpkg import func\n\nsys.exit(func())\n
    "},{"location":"config/metadata/#gui","title":"GUI","text":"

    GUI scripts are exactly the same as CLI scripts except on Windows, where they are handled specially so that they can be started without a console.

    pyproject.toml
    [project.gui-scripts]\ngui-name = \"pkg.subpkg:func\"\n
    "},{"location":"config/metadata/#plugins","title":"Plugins","text":"pyproject.toml
    [project.entry-points.plugin-namespace]\nplugin-name1 = \"pkg.subpkg1\"\nplugin-name2 = \"pkg.subpkg2:func\"\n
    "},{"location":"config/metadata/#dynamic","title":"Dynamic","text":"

    If any metadata fields are set dynamically, like the version may be, then they must be listed here.

    pyproject.toml
    [project]\n...\ndynamic = [\n  \"...\",\n]\n
    "},{"location":"config/metadata/#metadata-options","title":"Metadata options","text":""},{"location":"config/metadata/#allowing-direct-references","title":"Allowing direct references","text":"

    By default, dependencies are not allowed to define direct references. To disable this check, set allow-direct-references to true:

    pyproject.toml hatch.toml
    [tool.hatch.metadata]\nallow-direct-references = true\n
    [metadata]\nallow-direct-references = true\n
    "},{"location":"config/metadata/#allowing-ambiguous-features","title":"Allowing ambiguous features","text":"

    By default, names of optional dependencies are normalized to prevent ambiguity. To disable this normalization, set allow-ambiguous-features to true:

    pyproject.toml hatch.toml
    [tool.hatch.metadata]\nallow-ambiguous-features = true\n
    [metadata]\nallow-ambiguous-features = true\n

    Deprecated

    This option temporarily exists to provide better interoperability with tools that do not yet support PEP 685 and will be removed in the first minor release after Jan 1, 2024.

    "},{"location":"config/project-templates/","title":"Project templates","text":"

    You can control how new projects are created by the new command using Hatch's config file.

    "},{"location":"config/project-templates/#author","title":"Author","text":"config.toml
    [template]\nname = \"...\"\nemail = \"...\"\n
    "},{"location":"config/project-templates/#licenses","title":"Licenses","text":"config.toml
    [template.licenses]\nheaders = true\ndefault = [\n  \"MIT\",\n]\n

    The list of licenses should be composed of SPDX identifiers. If multiple licenses are specified, then they will be placed in a LICENSES directory.

    "},{"location":"config/project-templates/#options","title":"Options","text":""},{"location":"config/project-templates/#tests","title":"Tests","text":"

    This adds a tests directory with environments for testing and linting.

    config.toml
    [template.plugins.default]\ntests = true\n
    "},{"location":"config/project-templates/#ci","title":"CI","text":"

    This adds a GitHub Actions workflow that runs tests on all platforms using modern versions of Python.

    config.toml
    [template.plugins.default]\nci = false\n
    "},{"location":"config/project-templates/#src-layout","title":"src layout","text":"

    See this blog post.

    config.toml
    [template.plugins.default]\nsrc-layout = true\n
    "},{"location":"config/project-templates/#feature-flags","title":"Feature flags","text":""},{"location":"config/project-templates/#command-line-interface","title":"Command line interface","text":"

    The --cli flag adds a CLI backed by Click that can also be invoked with python -m <PKG_NAME>.

    "},{"location":"config/environment/advanced/","title":"Advanced environment configuration","text":""},{"location":"config/environment/advanced/#context-formatting","title":"Context formatting","text":"

    All environments support the following extra context formatting fields:

    Field Description env_name The name of the environment env_type The type of environment matrix Its modifier selects the value of that matrix variable. If the environment is not part of a matrix or was not generated with the variable, you must specify a default value as an additional modifier e.g. {matrix:version:v1.0.0}. verbosity The integer verbosity value of Hatch. A flag modifier is supported that will render the value as a CLI flag e.g. -2 becomes -qq, 1 becomes -v, and 0 becomes an empty string. An additional flag integer modifier may be used to adjust the verbosity level. For example, if you wanted to make a command quiet by default, you could use {verbosity:flag:-1} within the command. args For executed commands only, any extra command line arguments with an optional default modifier if none were provided"},{"location":"config/environment/advanced/#matrix","title":"Matrix","text":"

    Environments can define a series of matrices with the matrix option:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test]\ndependencies = [\n  \"pytest\"\n]\n\n[[tool.hatch.envs.test.matrix]]\npython = [\"3.10\", \"3.11\"]\nversion = [\"42\", \"3.14\"]\n\n[[tool.hatch.envs.test.matrix]]\npython = [\"3.11\", \"3.12\"]\nversion = [\"9000\"]\nfeature = [\"foo\", \"bar\"]\n
    [envs.test]\ndependencies = [\n  \"pytest\"\n]\n\n[[envs.test.matrix]]\npython = [\"3.10\", \"3.11\"]\nversion = [\"42\", \"3.14\"]\n\n[[envs.test.matrix]]\npython = [\"3.11\", \"3.12\"]\nversion = [\"9000\"]\nfeature = [\"foo\", \"bar\"]\n

    Doing so will result in the product of each variable combination being its own environment.

    "},{"location":"config/environment/advanced/#naming","title":"Naming","text":"

    The name of the generated environments will be the variable values of each combination separated by hyphens, altogether prefixed by <ENV_NAME>.. For example, the following configuration:

    pyproject.toml hatch.toml
    [[tool.hatch.envs.test.matrix]]\nversion = [\"42\"]\nfeature = [\"foo\", \"bar\"]\n
    [[envs.test.matrix]]\nversion = [\"42\"]\nfeature = [\"foo\", \"bar\"]\n

    would indicate the following unique environments:

    test.42-foo\ntest.42-bar\n

    The exceptions to this format are described below.

    "},{"location":"config/environment/advanced/#python-variables","title":"Python variables","text":"

    If the variables py or python are specified, then they will rank first in the product result and will be prefixed by py if the value is not. For example, the following configuration:

    pyproject.toml hatch.toml
    [[tool.hatch.envs.test.matrix]]\nversion = [\"42\"]\npython = [\"3.9\", \"pypy3\"]\n
    [[envs.test.matrix]]\nversion = [\"42\"]\npython = [\"3.9\", \"pypy3\"]\n

    would generate the following environments:

    test.py3.9-42\ntest.pypy3-42\n

    Note

    The value of this variable sets the Python version.

    "},{"location":"config/environment/advanced/#name-formatting","title":"Name formatting","text":"

    You can set the matrix-name-format option to modify how each variable part is formatted which recognizes the placeholders {variable} and {value}. For example, the following configuration:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test]\nmatrix-name-format = \"{variable}_{value}\"\n\n[[tool.hatch.envs.test.matrix]]\nversion = [\"42\"]\nfeature = [\"foo\", \"bar\"]\n
    [envs.test]\nmatrix-name-format = \"{variable}_{value}\"\n\n[[envs.test.matrix]]\nversion = [\"42\"]\nfeature = [\"foo\", \"bar\"]\n

    would produce the following environments:

    test.version_42-feature_foo\ntest.version_42-feature_bar\n

    By default this option is set to {value}.

    "},{"location":"config/environment/advanced/#default-environment","title":"Default environment","text":"

    If the default environment defines matrices, then the generated names will not be prefixed by the environment name. This can be useful for projects that only need a single series of matrices without any standalone environments.

    "},{"location":"config/environment/advanced/#selection","title":"Selection","text":"

    Rather than selecting a single generated environment, you can select the root environment to target all of them. For example, if you have the following configuration:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test]\ndependencies = [\n  \"coverage[toml]\",\n  \"pytest\",\n  \"pytest-cov\",\n]\n\n[tool.hatch.envs.test.scripts]\ncov = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests'\n\n[[tool.hatch.envs.test.matrix]]\npython = [\"3.11\", \"3.12\"]\nversion = [\"42\", \"3.14\"]\n
    [envs.test]\ndependencies = [\n  \"coverage[toml]\",\n  \"pytest\",\n  \"pytest-cov\",\n]\n\n[envs.test.scripts]\ncov = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests'\n\n[[envs.test.matrix]]\npython = [\"3.11\", \"3.12\"]\nversion = [\"42\", \"3.14\"]\n

    you could then run your tests consecutively in all 4 environments with:

    hatch run test:cov\n
    "},{"location":"config/environment/advanced/#option-overrides","title":"Option overrides","text":"

    You can modify options based on the conditions of different sources like matrix variables with the overrides table, using dotted key syntax for each declaration:

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>.overrides]\n<SOURCE>.<CONDITION>.<OPTION> = <VALUE>\n
    [envs.<ENV_NAME>.overrides]\n<SOURCE>.<CONDITION>.<OPTION> = <VALUE>\n

    The type of the selected option determines the types of values.

    "},{"location":"config/environment/advanced/#platform-overrides","title":"Platform overrides","text":"

    Options can be modified based on the current platform using the platform source.

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.overrides]\nplatform.windows.scripts = [\n  'run=pytest -m \"not io_uring\"',\n]\n
    [envs.test.overrides]\nplatform.windows.scripts = [\n  'run=pytest -m \"not io_uring\"',\n]\n

    The following platforms are supported:

    • linux
    • windows
    • macos
    "},{"location":"config/environment/advanced/#environment-variable-overrides","title":"Environment variable overrides","text":"

    Environment variables can modify options using the env source.

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.overrides]\nenv.GITHUB_ACTIONS.dev-mode = { value = false, if = [\"true\"] }\n
    [envs.test.overrides]\nenv.GITHUB_ACTIONS.dev-mode = { value = false, if = [\"true\"] }\n
    "},{"location":"config/environment/advanced/#matrix-variable-overrides","title":"Matrix variable overrides","text":"

    The matrix variables used to generate each environment can be used to modify options within using the matrix source.

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.overrides]\nmatrix.version.env-vars = \"PRODUCT_VERSION\"\nmatrix.auth.features = [\n  { value = \"oauth\", if = [\"oauth2\"] },\n  { value = \"kerberos\", if = [\"kerberos\"] },\n]\n\n[[tool.hatch.envs.test.matrix]]\npython = [\"3.11\", \"3.12\"]\nversion = [\"legacy\", \"latest\"]\nauth = [\"oauth2\", \"kerberos\", \"noauth\"]\n
    [envs.test.overrides]\nmatrix.version.env-vars = \"PRODUCT_VERSION\"\nmatrix.auth.features = [\n  { value = \"oauth\", if = [\"oauth2\"] },\n  { value = \"kerberos\", if = [\"kerberos\"] },\n]\n\n[[envs.test.matrix]]\npython = [\"3.11\", \"3.12\"]\nversion = [\"legacy\", \"latest\"]\nauth = [\"oauth2\", \"kerberos\", \"noauth\"]\n
    "},{"location":"config/environment/advanced/#name-overrides","title":"Name overrides","text":"

    When a matrix is defined, the name source can be used for regular expression matching on the generated name, minus the prefix for non-default environments.

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.overrides]\nname.\"^0\".env-vars = \"TESTING_UNSTABLE=true\"\n\n[[tool.hatch.envs.test.matrix]]\nversion = [\"0.1.0\", \"0.2.0\", \"1.0.0\"]\n
    [envs.test.overrides]\nname.\"^0\".env-vars = \"TESTING_UNSTABLE=true\"\n\n[[envs.test.matrix]]\nversion = [\"0.1.0\", \"0.2.0\", \"1.0.0\"]\n
    "},{"location":"config/environment/advanced/#types","title":"Types","text":"
    • Literal types like strings for the Python version or booleans for skipping installation can be set using the value itself, an inline table, or an array. For example:

      pyproject.toml hatch.toml
      [tool.hatch.envs.test.overrides]\nmatrix.foo.python = \"3.10\"\nmatrix.bar.skip-install = { value = true, if = [\"...\"] }\nenv.CI.dev-mode = [\n  { value = false, if = [\"...\"] },\n  true,\n]\n
      [envs.test.overrides]\nmatrix.foo.python = \"3.10\"\nmatrix.bar.skip-install = { value = true, if = [\"...\"] }\nenv.CI.dev-mode = [\n  { value = false, if = [\"...\"] },\n  true,\n]\n

      For arrays, the first allowed value will be used.

    • Array types like dependencies or commands can be appended to using an array of strings or inline tables. For example:

      pyproject.toml hatch.toml
      [tool.hatch.envs.test.overrides]\nmatrix.foo.dependencies = [\n  \"httpx\",\n  { value = \"cryptography\" },\n]\n
      [envs.test.overrides]\nmatrix.foo.dependencies = [\n  \"httpx\",\n  { value = \"cryptography\" },\n]\n
    • Mapping types like environment variables or scripts can have keys set using a string, or an array of strings or inline tables. For example:

      pyproject.toml hatch.toml
      [tool.hatch.envs.test.overrides]\nmatrix.foo.env-vars = \"KEY=VALUE\"\nmatrix.bar.env-vars = [\n  \"KEY1=VALUE1\",\n  { key = \"KEY2\", value = \"VALUE2\" },\n]\n
      [envs.test.overrides]\nmatrix.foo.env-vars = \"KEY=VALUE\"\nmatrix.bar.env-vars = [\n  \"KEY1=VALUE1\",\n  { key = \"KEY2\", value = \"VALUE2\" },\n]\n

      If the value is missing (no = for strings, no value key for inline tables), then the value will be set to the value of the source condition.

    "},{"location":"config/environment/advanced/#overwriting","title":"Overwriting","text":"

    Rather than supplementing the values within mapping types or array types, you can overwrite the option as a whole by prefixing the name with set-:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.overrides]\nmatrix.foo.set-platforms = [\"macos\", \"linux\"]\n
    [envs.test.overrides]\nmatrix.foo.set-platforms = [\"macos\", \"linux\"]\n

    When overwriting entire options or keys within mappings, override sources are applied in the following order:

    1. platform
    2. environment variables
    3. matrix variables
    4. names
    "},{"location":"config/environment/advanced/#conditions","title":"Conditions","text":"

    You may specify certain extra keys for any inline table that will determine whether or not to apply that entry. These modifiers may be combined with others and any negative evaluation will immediately cause the entry to be skipped.

    "},{"location":"config/environment/advanced/#allowed-values","title":"Allowed values","text":"

    The if key represents the allowed values for that condition. If the value of the condition is not listed, then that entry will not be applied:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.overrides]\nmatrix.version.python = { value = \"pypy\", if = [\"3.14\"] }\nmatrix.version.env-vars = [\n  { key = \"KEY1\", value = \"VALUE1\", if = [\"42\"] },\n  { key = \"KEY2\", value = \"VALUE2\", if = [\"3.14\"] },\n]\n\n[[tool.hatch.envs.test.matrix]]\nversion = [\"42\", \"3.14\"]\n
    [envs.test.overrides]\nmatrix.version.python = { value = \"pypy\", if = [\"3.14\"] }\nmatrix.version.env-vars = [\n  { key = \"KEY1\", value = \"VALUE1\", if = [\"42\"] },\n  { key = \"KEY2\", value = \"VALUE2\", if = [\"3.14\"] },\n]\n\n[[envs.test.matrix]]\nversion = [\"42\", \"3.14\"]\n
    "},{"location":"config/environment/advanced/#specific-platforms","title":"Specific platforms","text":"

    The platform key represents the desired platforms. If the current platform is not listed, then that entry will not be applied:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.overrides]\nenv.EXPERIMENTAL.python = { value = \"pypy\", if = [\"1\"], platform = [\"macos\"] }\nmatrix.version.env-vars = [\n  { key = \"KEY1\", value = \"VALUE1\", if = [\"42\"], platform = [\"linux\"] },\n  { key = \"KEY2\", value = \"VALUE2\", if = [\"3.14\"] },\n]\n\n[[tool.hatch.envs.test.matrix]]\nversion = [\"42\", \"3.14\"]\n
    [envs.test.overrides]\nenv.EXPERIMENTAL.python = { value = \"pypy\", if = [\"1\"], platform = [\"macos\"] }\nmatrix.version.env-vars = [\n  { key = \"KEY1\", value = \"VALUE1\", if = [\"42\"], platform = [\"linux\"] },\n  { key = \"KEY2\", value = \"VALUE2\", if = [\"3.14\"] },\n]\n\n[[envs.test.matrix]]\nversion = [\"42\", \"3.14\"]\n
    "},{"location":"config/environment/advanced/#required-environment-variables","title":"Required environment variables","text":"

    The env key represents the required environment variables. If any of the listed environment variables are not set or the defined value does not match, then that entry will not be applied:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.overrides]\nplatform.windows.python = { value = \"pypy\", env = [\"EXPERIMENTAL\"] }\nmatrix.version.env-vars = [\n  { key = \"KEY1\", value = \"VALUE1\", if = [\"42\"], env = [\"FOO\", \"BAR=BAZ\"] },\n  { key = \"KEY2\", value = \"VALUE2\", if = [\"3.14\"] },\n]\n\n[[tool.hatch.envs.test.matrix]]\nversion = [\"42\", \"3.14\"]\n
    [envs.test.overrides]\nplatform.windows.python = { value = \"pypy\", env = [\"EXPERIMENTAL\"] }\nmatrix.version.env-vars = [\n  { key = \"KEY1\", value = \"VALUE1\", if = [\"42\"], env = [\"FOO\", \"BAR=BAZ\"] },\n  { key = \"KEY2\", value = \"VALUE2\", if = [\"3.14\"] },\n]\n\n[[envs.test.matrix]]\nversion = [\"42\", \"3.14\"]\n
    "},{"location":"config/environment/overview/","title":"Environment configuration","text":"

    All environments are defined as sections within the tool.hatch.envs table.

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\n
    [envs.<ENV_NAME>]\n

    The storage location for environments is completely configurable.

    Unless an environment is explicitly selected on the command line, the default environment will be used. The type of this environment defaults to virtual.

    Info

    Environments prefixed by hatch- are used for special purposes e.g. testing.

    "},{"location":"config/environment/overview/#inheritance","title":"Inheritance","text":"

    All environments inherit from the environment defined by its template option, which defaults to default.

    So for the following configuration:

    pyproject.toml hatch.toml
    [tool.hatch.envs.foo]\ntype = \"baz\"\nskip-install = true\n\n[tool.hatch.envs.bar]\ntemplate = \"foo\"\nskip-install = false\n
    [envs.foo]\ntype = \"baz\"\nskip-install = true\n\n[envs.bar]\ntemplate = \"foo\"\nskip-install = false\n

    the environment bar will be of type baz with skip-install set to false.

    Note

    Environments do not inherit matrices.

    "},{"location":"config/environment/overview/#self-referential-environments","title":"Self-referential environments","text":"

    You can disable inheritance by setting template to the environment's own name:

    pyproject.toml hatch.toml
    [tool.hatch.envs.foo]\ntemplate = \"foo\"\n
    [envs.foo]\ntemplate = \"foo\"\n
    "},{"location":"config/environment/overview/#detached-environments","title":"Detached environments","text":"

    A common use case is standalone environments that do not require inheritance nor the installation of the project, such as for linting or sometimes building documentation. Enabling the detached option will make the environment self-referential and will skip project installation:

    pyproject.toml hatch.toml
    [tool.hatch.envs.lint]\ndetached = true\n
    [envs.lint]\ndetached = true\n
    "},{"location":"config/environment/overview/#dependencies","title":"Dependencies","text":"

    You can install dependencies in addition to the ones defined by your project's metadata. Entries support context formatting.

    pyproject.toml hatch.toml
    [tool.hatch.envs.test]\ndependencies = [\n  \"coverage[toml]\",\n  \"pytest\",\n  \"pytest-cov\",\n  \"pytest-mock\",\n]\n
    [envs.test]\ndependencies = [\n  \"coverage[toml]\",\n  \"pytest\",\n  \"pytest-cov\",\n  \"pytest-mock\",\n]\n

    If you define environments with dependencies that only slightly differ from their inherited environments, you can use the extra-dependencies option to avoid redeclaring the dependencies option:

    pyproject.toml hatch.toml
    [tool.hatch.envs.default]\ndependencies = [\n  \"foo\",\n  \"bar\",\n]\n\n[tool.hatch.envs.experimental]\nextra-dependencies = [\n  \"baz\",\n]\n
    [envs.default]\ndependencies = [\n  \"foo\",\n  \"bar\",\n]\n\n[envs.experimental]\nextra-dependencies = [\n  \"baz\",\n]\n

    Tip

    Hatch uses pip to install dependencies so any configuration it supports Hatch does as well. For example, if you wanted to only use a private repository you could set the PIP_INDEX_URL environment variable.

    "},{"location":"config/environment/overview/#installation","title":"Installation","text":""},{"location":"config/environment/overview/#features","title":"Features (extras)","text":"

    If your project defines optional dependencies, you can select which groups to install using the features option:

    pyproject.toml hatch.toml
    [tool.hatch.envs.nightly]\nfeatures = [\n  \"server\",\n  \"grpc\",\n]\n
    [envs.nightly]\nfeatures = [\n  \"server\",\n  \"grpc\",\n]\n

    Note

    Features/optional dependencies are also known as extras in other tools.

    "},{"location":"config/environment/overview/#dev-mode","title":"Dev mode","text":"

    By default, environments will always reflect the current state of your project on disk. Set dev-mode to false to disable this behavior:

    pyproject.toml hatch.toml
    [tool.hatch.envs.static]\ndev-mode = false\n
    [envs.static]\ndev-mode = false\n
    "},{"location":"config/environment/overview/#skip-install","title":"Skip install","text":"

    By default, environments will install your project during creation. To ignore this step, set skip-install to true:

    pyproject.toml hatch.toml
    [tool.hatch.envs.lint]\nskip-install = true\n
    [envs.lint]\nskip-install = true\n
    "},{"location":"config/environment/overview/#environment-variables","title":"Environment variables","text":""},{"location":"config/environment/overview/#defined","title":"Defined","text":"

    You can define environment variables with the env-vars option:

    pyproject.toml hatch.toml
    [tool.hatch.envs.docs]\ndependencies = [\n  \"mkdocs\"\n]\n[tool.hatch.envs.docs.env-vars]\nSOURCE_DATE_EPOCH = \"1580601600\"\n
    [envs.docs]\ndependencies = [\n  \"mkdocs\"\n]\n[envs.docs.env-vars]\nSOURCE_DATE_EPOCH = \"1580601600\"\n

    Values support context formatting.

    "},{"location":"config/environment/overview/#filters","title":"Filters","text":"

    By default, environments will have access to all environment variables. You can filter with wildcard patterns using the env-include/env-exclude options:

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\nenv-include = [\n  \"FOO*\",\n]\nenv-exclude = [\n  \"BAR\",\n]\n
    [envs.<ENV_NAME>]\nenv-include = [\n  \"FOO*\",\n]\nenv-exclude = [\n  \"BAR\",\n]\n

    Exclusion patterns take precedence but will never affect defined environment variables.

    "},{"location":"config/environment/overview/#scripts","title":"Scripts","text":"

    You can define named scripts that may be executed or referenced at the beginning of other scripts. Context formatting is supported.

    For example, in the following configuration:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test]\ndependencies = [\n  \"coverage[toml]\",\n  \"pytest\",\n  \"pytest-cov\",\n  \"pytest-mock\",\n]\n[tool.hatch.envs.test.scripts]\nrun-coverage = \"pytest --cov-config=pyproject.toml --cov=pkg --cov=tests\"\nrun = \"run-coverage --no-cov\"\n
    [envs.test]\ndependencies = [\n  \"coverage[toml]\",\n  \"pytest\",\n  \"pytest-cov\",\n  \"pytest-mock\",\n]\n[envs.test.scripts]\nrun-coverage = \"pytest --cov-config=pyproject.toml --cov=pkg --cov=tests\"\nrun = \"run-coverage --no-cov\"\n

    the run script would be expanded to:

    pytest --cov-config=pyproject.toml --cov=pkg --cov=tests --no-cov\n

    Scripts can also be defined as an array of strings.

    pyproject.toml hatch.toml
    [tool.hatch.envs.style]\ndetached = true\ndependencies = [\n  \"flake8\",\n  \"black\",\n  \"isort\",\n]\n[tool.hatch.envs.style.scripts]\ncheck = [\n  \"flake8 .\",\n  \"black --check --diff .\",\n  \"isort --check-only --diff .\",\n]\nfmt = [\n  \"isort .\",\n  \"black .\",\n  \"check\",\n]\n
    [envs.style]\ndetached = true\ndependencies = [\n  \"flake8\",\n  \"black\",\n  \"isort\",\n]\n[envs.style.scripts]\ncheck = [\n  \"flake8 .\",\n  \"black --check --diff .\",\n  \"isort --check-only --diff .\",\n]\nfmt = [\n  \"isort .\",\n  \"black .\",\n  \"check\",\n]\n

    Similar to make, you can ignore the exit code of commands that start with - (a hyphen). For example, the script error defined by the following configuration would halt after the second command with 3 as the exit code:

    pyproject.toml hatch.toml
    [tool.hatch.envs.test.scripts]\nerror = [\n  \"- exit 1\",\n  \"exit 3\",\n  \"exit 0\",\n]\n
    [envs.test.scripts]\nerror = [\n  \"- exit 1\",\n  \"exit 3\",\n  \"exit 0\",\n]\n
    "},{"location":"config/environment/overview/#extra-scripts","title":"Extra scripts","text":"

    Individual scripts inherit from parent environments just like options. To guarantee that individual scripts do not override those defined by parent environments, you can use the extra-scripts option instead which is only capable of adding scripts that have not been defined.

    "},{"location":"config/environment/overview/#commands","title":"Commands","text":"

    All commands are able to use any defined scripts. Also like scripts, context formatting is supported and the exit code of commands that start with a hyphen will be ignored.

    "},{"location":"config/environment/overview/#pre-install","title":"Pre-install","text":"

    You can run commands immediately before environments install your project.

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\npre-install-commands = [\n  \"...\",\n]\n
    [envs.<ENV_NAME>]\npre-install-commands = [\n  \"...\",\n]\n
    "},{"location":"config/environment/overview/#post-install","title":"Post-install","text":"

    You can run commands immediately after environments install your project.

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\npost-install-commands = [\n  \"...\",\n]\n
    [envs.<ENV_NAME>]\npost-install-commands = [\n  \"...\",\n]\n
    "},{"location":"config/environment/overview/#python-version","title":"Python version","text":"

    The python option specifies which version of Python to use, or an absolute path to a Python interpreter:

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\npython = \"3.10\"\n
    [envs.<ENV_NAME>]\npython = \"3.10\"\n

    All environment types should respect this option.

    "},{"location":"config/environment/overview/#supported-platforms","title":"Supported platforms","text":"

    The platforms option indicates the operating systems with which the environment is compatible:

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\nplatforms = [\"linux\", \"windows\", \"macos\"]\n
    [envs.<ENV_NAME>]\nplatforms = [\"linux\", \"windows\", \"macos\"]\n

    The following platforms are supported:

    • linux
    • windows
    • macos

    If unspecified, the environment is assumed to be compatible with all platforms.

    "},{"location":"config/environment/overview/#description","title":"Description","text":"

    The description option is purely informational and is displayed in the output of the env show command:

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\ndescription = \"\"\"\nLorem ipsum ...\n\"\"\"\n
    [envs.<ENV_NAME>]\ndescription = \"\"\"\nLorem ipsum ...\n\"\"\"\n
    "},{"location":"config/environment/overview/#type","title":"Type","text":"

    An environment's type determines which environment plugin will be used for management. The only built-in environment type is virtual, which uses virtual Python environments.

    "},{"location":"config/internal/static-analysis/","title":"Static analysis configuration","text":"

    Static analysis performed by the fmt command is (by default) backed entirely by Ruff.

    Hatch provides default settings that user configuration can extend.

    "},{"location":"config/internal/static-analysis/#extending-config","title":"Extending config","text":"

    When defining your configuration, be sure to use options that are prefixed by extend- such as extend-select, for example:

    pyproject.toml ruff.toml
    [tool.ruff.format]\npreview = true\nquote-style = \"single\"\n\n[tool.ruff.lint]\npreview = true\nextend-select = [\"C901\"]\n\n[tool.ruff.lint.extend-per-file-ignores]\n\"docs/.hooks/*\" = [\"INP001\", \"T201\"]\n\n[tool.ruff.lint.isort]\nknown-first-party = [\"foo\", \"bar\"]\n
    [format]\npreview = true\nquote-style = \"single\"\n\n[lint]\npreview = true\nextend-select = [\"C901\"]\n\n[lint.extend-per-file-ignores]\n\"docs/.hooks/*\" = [\"INP001\", \"T201\"]\n\n[lint.isort]\nknown-first-party = [\"foo\", \"bar\"]\n

    Note

    When not persisting config, there is no need to explicitly extend the defaults as Hatch automatically handles that.

    "},{"location":"config/internal/static-analysis/#persistent-config","title":"Persistent config","text":"

    If you want to store the default configuration in the project, set an explicit path like so:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-static-analysis]\nconfig-path = \"ruff_defaults.toml\"\n
    [envs.hatch-static-analysis]\nconfig-path = \"ruff_defaults.toml\"\n

    Then instruct Ruff to consider your configuration as an extension of the default file:

    pyproject.toml ruff.toml
    [tool.ruff]\nextend = \"ruff_defaults.toml\"\n
    extend = \"ruff_defaults.toml\"\n

    Anytime you wish to update the defaults (such as when upgrading Hatch), you must run the fmt command once with the --sync flag e.g.:

    hatch fmt --check --sync\n

    Tip

    This is the recommended approach since it allows other tools like IDEs to use the default configuration.

    "},{"location":"config/internal/static-analysis/#no-config","title":"No config","text":"

    If you don't want Hatch to use any of its default configuration and rely entirely on yours, set the path to anything and then simply don't extend in your Ruff config:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-static-analysis]\nconfig-path = \"none\"\n
    [envs.hatch-static-analysis]\nconfig-path = \"none\"\n
    "},{"location":"config/internal/static-analysis/#customize-behavior","title":"Customize behavior","text":"

    You can fully alter the behavior of the environment used by the fmt command. See the how-to for a detailed example.

    "},{"location":"config/internal/static-analysis/#dependencies","title":"Dependencies","text":"

    Pin the particular version of Ruff by explicitly defining the environment dependencies:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-static-analysis]\ndependencies = [\"ruff==X.Y.Z\"]\n
    [envs.hatch-static-analysis]\ndependencies = [\"ruff==X.Y.Z\"]\n
    "},{"location":"config/internal/static-analysis/#scripts","title":"Scripts","text":"

    If you want to change the default commands that are executed, you can override the scripts. The following four scripts must be defined:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-static-analysis.scripts]\nformat-check = \"...\"\nformat-fix = \"...\"\nlint-check = \"...\"\nlint-fix = \"...\"\n
    [envs.hatch-static-analysis.scripts]\nformat-check = \"...\"\nformat-fix = \"...\"\nlint-check = \"...\"\nlint-fix = \"...\"\n

    The format-* scripts correspond to the --formatter/-f flag while the lint-* scripts correspond to the --linter/-l flag. The *-fix scripts run by default while the *-check scripts correspond to the --check flag.

    Reminder

    If you choose to use different tools for static analysis, be sure to update the required dependencies.

    "},{"location":"config/internal/static-analysis/#installer","title":"Installer","text":"

    By default, UV is enabled. You may disable that behavior as follows:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-static-analysis]\ninstaller = \"pip\"\n
    [envs.hatch-static-analysis]\ninstaller = \"pip\"\n
    "},{"location":"config/internal/static-analysis/#default-settings","title":"Default settings","text":""},{"location":"config/internal/static-analysis/#non-rule-settings","title":"Non-rule settings","text":"
    • Line length set to 120
    • Docstring formatting enabled with line length set to 80
    • Only absolute imports are allowed, except for tests
    • The normalized project name is a known first party import
    "},{"location":"config/internal/static-analysis/#per-file-ignored-rules","title":"Per-file ignored rules","text":"
    • **/scripts/*: INP001, T201
    • **/tests/**/*: PLC1901, PLR2004, PLR6301, S, TID252
    "},{"location":"config/internal/static-analysis/#selected-rules","title":"Selected rules","text":"

    The following rules are based on version 0.4.5 of Ruff. Rules with a P are only selected when preview mode is enabled.

    There are 525 selected stable rules and 129 selected preview rules.

    Selected rules
    • A001, A002, A003
    • ARG001, ARG002, ARG003, ARG004, ARG005
    • ASYNC100, ASYNC101, ASYNC102
    • B002, B003, B004, B005, B006, B007, B008, B009, B010, B011, B012, B013, B014, B015, B016, B017, B018, B019, B020, B021, B022, B023, B024, B025, B026, B028, B029, B030, B031, B032, B033, B034, B035, B904, B905, B909P
    • BLE001
    • C400, C401, C402, C403, C404, C405, C406, C408, C409, C410, C411, C413, C414, C415, C416, C417, C418, C419
    • COM818
    • DTZ001, DTZ002, DTZ003, DTZ004, DTZ005, DTZ006, DTZ007, DTZ011, DTZ012
    • E101, E112P, E113P, E115P, E116P, E201P, E202P, E203P, E211P, E221P, E222P, E223P, E224P, E225P, E226P, E227P, E228P, E231P, E241P, E242P, E251P, E252P, E261P, E262P, E265P, E266P, E271P, E272P, E273P, E274P, E275P, E401, E402, E502P, E701, E702, E703, E711, E712, E713, E714, E721, E722, E731, E741, E742, E743, E902, E999
    • EM101, EM102, EM103
    • EXE001, EXE002, EXE003, EXE004, EXE005
    • F401, F402, F403, F404, F405, F406, F407, F501, F502, F503, F504, F505, F506, F507, F508, F509, F521, F522, F523, F524, F525, F541, F601, F602, F621, F622, F631, F632, F633, F634, F701, F702, F704, F706, F707, F722, F811, F821, F822, F823, F841, F842, F901
    • FA100, FA102
    • FBT001, FBT002
    • FLY002
    • FURB105P, FURB110P, FURB113P, FURB116P, FURB118P, FURB129P, FURB131P, FURB132P, FURB136P, FURB142P, FURB145P, FURB148P, FURB152P, FURB157P, FURB161P, FURB163P, FURB164P, FURB166P, FURB167P, FURB168P, FURB169P, FURB171P, FURB177P, FURB180P, FURB181P, FURB187P, FURB192P
    • G001, G002, G003, G004, G010, G101, G201, G202
    • I001, I002
    • ICN001, ICN002, ICN003
    • INP001
    • INT001, INT002, INT003
    • ISC003
    • LOG001, LOG002, LOG007, LOG009
    • N801, N802, N803, N804, N805, N806, N807, N811, N812, N813, N814, N815, N816, N817, N818, N999
    • PERF101, PERF102, PERF401, PERF402, PERF403P
    • PGH005
    • PIE790, PIE794, PIE796, PIE800, PIE804, PIE807, PIE808, PIE810
    • PLC0105, PLC0131, PLC0132, PLC0205, PLC0208, PLC0414, PLC0415P, PLC1901P, PLC2401P, PLC2403P, PLC2701P, PLC2801P, PLC3002
    • PLE0100, PLE0101, PLE0116, PLE0117, PLE0118, PLE0237, PLE0241, PLE0302, PLE0307, PLE0604, PLE0605, PLE0115P, PLE0303P, PLE0304P, PLE0305P, PLE0308P, PLE0309P, PLE0643P, PLE0704P, PLE1142, PLE1205, PLE1206, PLE1300, PLE1307, PLE1310, PLE1507, PLE1700, PLE1132P, PLE1141P, PLE1519P, PLE1520P, PLE2502, PLE2510, PLE2512, PLE2513, PLE2514, PLE2515, PLE4703P
    • PLR0124, PLR0133, PLR0206, PLR0402, PLR0202P, PLR0203P, PLR1701, PLR1711, PLR1714, PLR1722, PLR1704P, PLR1730P, PLR1733P, PLR1736P, PLR2004, PLR2044P, PLR5501, PLR6104P, PLR6201P, PLR6301P
    • PLW0120, PLW0127, PLW0129, PLW0131, PLW0406, PLW0602, PLW0603, PLW0711, PLW0108P, PLW0128P, PLW0133P, PLW0177P, PLW0211P, PLW0245P, PLW0604P, PLW0642P, PLW1508, PLW1509, PLW1510, PLW1501P, PLW1514P, PLW1641P, PLW2901, PLW2101P, PLW3301, PLW3201P
    • PT001, PT002, PT003, PT006, PT007, PT008, PT009, PT010, PT011, PT012, PT013, PT014, PT015, PT016, PT017, PT018, PT019, PT020, PT021, PT022, PT023, PT024, PT025, PT026, PT027
    • PYI001, PYI002, PYI003, PYI004, PYI005, PYI006, PYI007, PYI008, PYI009, PYI010, PYI011, PYI012, PYI013, PYI014, PYI015, PYI016, PYI017, PYI018, PYI019, PYI020, PYI021, PYI024, PYI025, PYI026, PYI029, PYI030, PYI032, PYI033, PYI034, PYI035, PYI036, PYI041, PYI042, PYI043, PYI044, PYI045, PYI046, PYI047, PYI048, PYI049, PYI050, PYI051, PYI052, PYI053, PYI054, PYI055, PYI056, PYI058, PYI059P, PYI062P
    • RET503, RET504, RET505, RET506, RET507, RET508
    • RSE102
    • RUF001, RUF002, RUF003, RUF005, RUF006, RUF007, RUF008, RUF009, RUF010, RUF012, RUF013, RUF015, RUF016, RUF017, RUF018, RUF019, RUF020, RUF021P, RUF022P, RUF023P, RUF024P, RUF025P, RUF026P, RUF027P, RUF028P, RUF029P, RUF100, RUF101P
    • S101, S102, S103, S104, S105, S106, S107, S108, S110, S112, S113, S201, S202, S301, S302, S303, S304, S305, S306, S307, S308, S310, S311, S312, S313, S314, S315, S316, S317, S318, S319, S320, S321, S323, S324, S401P, S402P, S403P, S405P, S406P, S407P, S408P, S409P, S411P, S412P, S413P, S415P, S501, S502, S503, S504, S505, S506, S507, S508, S509, S601, S602, S604, S605, S606, S607, S608, S609, S611, S612, S610P, S701, S702
    • SIM101, SIM102, SIM103, SIM105, SIM107, SIM108, SIM109, SIM110, SIM112, SIM113, SIM114, SIM115, SIM116, SIM117, SIM118, SIM201, SIM202, SIM208, SIM210, SIM211, SIM212, SIM220, SIM221, SIM222, SIM223, SIM300, SIM910, SIM911
    • SLF001
    • SLOT000, SLOT001, SLOT002
    • T100, T201, T203
    • TCH001, TCH002, TCH003, TCH004, TCH005, TCH010
    • TD004, TD005, TD006, TD007
    • TID251, TID252, TID253
    • TRIO100, TRIO105, TRIO109, TRIO110, TRIO115
    • TRY002, TRY003, TRY004, TRY201, TRY300, TRY301, TRY302, TRY400, TRY401
    • UP001, UP003, UP004, UP005, UP006, UP007, UP008, UP009, UP010, UP011, UP012, UP013, UP014, UP015, UP017, UP018, UP019, UP020, UP021, UP022, UP023, UP024, UP025, UP026, UP027, UP028, UP029, UP030, UP031, UP032, UP033, UP034, UP035, UP036, UP037, UP038, UP039, UP040, UP041, UP042P
    • W291, W292, W293, W391P, W505, W605
    • YTT101, YTT102, YTT103, YTT201, YTT202, YTT203, YTT204, YTT301, YTT302, YTT303
    "},{"location":"config/internal/static-analysis/#unselected","title":"Unselected","text":"

    There are 175 unselected rules.

    Unselected rules
    • AIR001
    • ANN001, ANN002, ANN003, ANN101, ANN102, ANN201, ANN202, ANN204, ANN205, ANN206, ANN401
    • B027
    • C901
    • COM812, COM819
    • CPY001
    • D100, D101, D102, D103, D104, D105, D106, D107, D200, D201, D202, D203, D204, D205, D206, D207, D208, D209, D210, D211, D212, D213, D214, D215, D300, D301, D400, D401, D402, D403, D404, D405, D406, D407, D408, D409, D410, D411, D412, D413, D414, D415, D416, D417, D418, D419
    • DJ001, DJ003, DJ006, DJ007, DJ008, DJ012, DJ013
    • E111, E114, E117, E301, E302, E303, E304, E305, E306, E501
    • ERA001
    • FBT003
    • FIX001, FIX002, FIX003, FIX004
    • FURB101, FURB103, FURB140
    • ISC001, ISC002
    • NPY001, NPY002, NPY003, NPY201
    • PD002, PD003, PD004, PD007, PD008, PD009, PD010, PD011, PD012, PD013, PD015, PD101, PD901
    • PERF203
    • PGH001, PGH002, PGH003, PGH004
    • PLR0904, PLR0911, PLR0912, PLR0913, PLR0914, PLR0915, PLR0916, PLR0917, PLR1702, PLR1706
    • PT004, PT005
    • PTH100, PTH101, PTH102, PTH103, PTH104, PTH105, PTH106, PTH107, PTH108, PTH109, PTH110, PTH111, PTH112, PTH113, PTH114, PTH115, PTH116, PTH117, PTH118, PTH119, PTH120, PTH121, PTH122, PTH123, PTH124, PTH201, PTH202, PTH203, PTH204, PTH205, PTH206, PTH207
    • Q000, Q001, Q002, Q003, Q004
    • RET501, RET502
    • RUF011, RUF200
    • S404, S410, S603
    • SIM401
    • TD001, TD002, TD003
    • TRY200
    • W191
    "},{"location":"config/internal/testing/","title":"Testing configuration","text":"

    Check out the testing overview tutorial for a more comprehensive walk-through.

    "},{"location":"config/internal/testing/#settings","title":"Settings","text":"

    If an option has a corresponding test command flag, the flag will always take precedence.

    "},{"location":"config/internal/testing/#default-arguments","title":"Default arguments","text":"

    You can define default arguments for the test command by setting the default-args option, which must be an array of strings. The following is the default configuration:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test]\ndefault-args = [\"tests\"]\n
    [envs.hatch-test]\ndefault-args = [\"tests\"]\n
    "},{"location":"config/internal/testing/#extra-arguments","title":"Extra arguments","text":"

    You can define extra internal arguments for test scripts by setting the extra-args option, which must be an array of strings. For example, if you wanted to increase the verbosity of pytest, you could set the following:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test]\nextra-args = [\"-vv\"]\n
    [envs.hatch-test]\nextra-args = [\"-vv\"]\n
    "},{"location":"config/internal/testing/#randomize-test-order","title":"Randomize test order","text":"

    You can randomize the order of tests by enabling the randomize option which corresponds to the --randomize/-r flag:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test]\nrandomize = true\n
    [envs.hatch-test]\nrandomize = true\n
    "},{"location":"config/internal/testing/#parallelize-test-execution","title":"Parallelize test execution","text":"

    You can parallelize test execution by enabling the parallel option which corresponds to the --parallel/-p flag:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test]\nparallel = true\n
    [envs.hatch-test]\nparallel = true\n
    "},{"location":"config/internal/testing/#retry-failed-tests","title":"Retry failed tests","text":"

    You can retry failed tests by setting the retries option which corresponds to the --retries flag:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test]\nretries = 2\n
    [envs.hatch-test]\nretries = 2\n

    You can also set the number of seconds to wait between retries by setting the retry-delay option which corresponds to the --retry-delay flag:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test]\nretry-delay = 1\n
    [envs.hatch-test]\nretry-delay = 1\n
    "},{"location":"config/internal/testing/#customize-environment","title":"Customize environment","text":"

    You can fully alter the behavior of the environment used by the test command.

    "},{"location":"config/internal/testing/#dependencies","title":"Dependencies","text":"

    You can define extra dependencies that your tests may require:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test]\nextra-dependencies = [\n  \"pyfakefs\",\n  \"pytest-asyncio\",\n  \"pytest-benchmark\",\n  \"pytest-memray\",\n  \"pytest-playwright\",\n  \"pytest-print\",\n]\n
    [envs.hatch-test]\nextra-dependencies = [\n  \"pyfakefs\",\n  \"pytest-asyncio\",\n  \"pytest-benchmark\",\n  \"pytest-memray\",\n  \"pytest-playwright\",\n  \"pytest-print\",\n]\n

    The following is the default configuration:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test]\ndependencies = [\n  \"coverage-enable-subprocess==1.0\",\n  \"coverage[toml]~=7.4\",\n  \"pytest~=8.1\",\n  \"pytest-mock~=3.12\",\n  \"pytest-randomly~=3.15\",\n  \"pytest-rerunfailures~=14.0\",\n  \"pytest-xdist[psutil]~=3.5\",\n]\n
    [envs.hatch-test]\ndependencies = [\n  \"coverage-enable-subprocess==1.0\",\n  \"coverage[toml]~=7.4\",\n  \"pytest~=8.1\",\n  \"pytest-mock~=3.12\",\n  \"pytest-randomly~=3.15\",\n  \"pytest-rerunfailures~=14.0\",\n  \"pytest-xdist[psutil]~=3.5\",\n]\n
    "},{"location":"config/internal/testing/#matrix","title":"Matrix","text":"

    You can override the default series of matrices:

    pyproject.toml hatch.toml
    [[tool.hatch.envs.hatch-test.matrix]]\npython = [\"3.13\", \"3.12\", \"3.11\", \"3.10\", \"3.9\", \"3.8\"]\n
    [[envs.hatch-test.matrix]]\npython = [\"3.13\", \"3.12\", \"3.11\", \"3.10\", \"3.9\", \"3.8\"]\n
    "},{"location":"config/internal/testing/#scripts","title":"Scripts","text":"

    If you want to change the default commands that are executed, you can override the scripts. The following default scripts must be redefined:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test.scripts]\nrun = \"pytest{env:HATCH_TEST_ARGS:} {args}\"\nrun-cov = \"coverage run -m pytest{env:HATCH_TEST_ARGS:} {args}\"\ncov-combine = \"coverage combine\"\ncov-report = \"coverage report\"\n
    [envs.hatch-test.scripts]\nrun = \"pytest{env:HATCH_TEST_ARGS:} {args}\"\nrun-cov = \"coverage run -m pytest{env:HATCH_TEST_ARGS:} {args}\"\ncov-combine = \"coverage combine\"\ncov-report = \"coverage report\"\n

    The run script is the default behavior while the run-cov script is used instead when measuring code coverage. The cov-combine script runs after all tests complete when measuring code coverage, as well as the cov-report script when not using the --cover-quiet flag.

    Note

    The HATCH_TEST_ARGS environment variable is how the test command's flags are translated and internally populated without affecting the user's arguments. This is also the way that extra arguments are passed.

    "},{"location":"config/internal/testing/#installer","title":"Installer","text":"

    By default, UV is enabled. You may disable that behavior as follows:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test]\ninstaller = \"pip\"\n
    [envs.hatch-test]\ninstaller = \"pip\"\n
    "},{"location":"history/hatch/","title":"Hatch history","text":"

    All notable changes to Hatch will be documented in this file.

    The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

    "},{"location":"history/hatch/#unreleased","title":"Unreleased","text":""},{"location":"history/hatch/#hatch-v1.13.0","title":"1.13.0 - 2024-10-13","text":"

    Added:

    • Support managing Python 3.13 distributions
    "},{"location":"history/hatch/#hatch-v1.12.0","title":"1.12.0 - 2024-05-28","text":"

    Changed:

    • The run/env run and test commands now treat inclusion variable options as an intersection rather than a union to allow for specific targeting of environments

    Added:

    • Add ability to control the source of Python distributions
    • Upgrade Ruff to 0.4.5
    • Upgrade PyApp to 0.22.0 for binary builds

    Fixed:

    • The fmt command no longer hides the commands that are being executed
    • Add default timeout for network requests, useful when installing Python distributions
    • Fix syntax highlighting contrast for the config show command
    "},{"location":"history/hatch/#hatch-v1.11.1","title":"1.11.1 - 2024-05-23","text":"

    Added:

    • Add official GitHub Action for installing Hatch

    Fixed:

    • Fix terminal.styles.spinner configuration
    • Fix entry points in the pre-built distributions that binaries use
    "},{"location":"history/hatch/#hatch-v1.11.0","title":"1.11.0 - 2024-05-14","text":"

    Added:

    • Upgrade PyApp to 0.21.1 for binary builds

    Fixed:

    • On Linux, install the highest compatible Python distribution variant based on CPU architecture rather than assuming recent hardware
    "},{"location":"history/hatch/#hatch-v1.10.0","title":"1.10.0 - 2024-05-02","text":"

    Changed:

    • The run/env run, fmt and shell commands now only change the current working directory to the project root if not already inside the project
    • The shell command now accepts a single argument to specify the environment to enter which overrides the standard choice mechanisms. The arguments determining shell options have been converted to flags.

    Added:

    • Add test command
    • The run command can now execute scripts that define inline metadata for dependencies and Python version constraints
    • The virtual environment type now supports the ability to use UV in place of pip & virtualenv
    • Add self report command for submitting pre-populated bug reports to GitHub
    • The reserved environment used for static analysis is now completely configurable
    • Add the following methods to the environment interface for complete control over output during life cycle management: app_status_creation, app_status_pre_installation, app_status_post_installation, app_status_project_installation, app_status_dependency_state_check, app_status_dependency_installation_check, app_status_dependency_synchronization
    • Add binaries for 32-bit versions of Windows
    • Read configuration from any ~/.pypirc file for the index publisher
    • Use the Git user as the default username for new project URL metadata
    • Add HATCH_DEBUG environment variable that when enabled will show local variables in the case of unhandled tracebacks
    • The env show command now outputs data about all internal environments when using the --json flag
    • Upgrade default CPython distributions to 20240415
    • Upgrade default PyPy distributions to 7.3.15
    • Upgrade Ruff to 0.4.2
    • Upgrade PyApp to 0.19.0 for binary builds
    • Bump the minimum supported version of Hatchling to 1.24.2
    • Bump the minimum supported version of virtualenv to 20.26.1

    Fixed:

    • Maintain consistent data paths for case insensitive file systems
    • When projects derive dependencies from metadata hooks, there is now by default a status indicator for when the hooks are executed for better responsiveness
    • Properly support projects with a pyproject.toml file but no project table e.g. applications
    • Fix the fmt command when automatically installing plugin dependencies
    • Fix dependency inheritance for the template of the types environment for new projects
    • Fix warnings related to tar file extraction on Python 3.12+ when unpacking Python distributions for installation
    • De-select Ruff rule E501 for the fmt command by default since it conflicts with the formatter
    • Fix colored output from build targets on the first run (build environment creation status indicator issue)
    • Set the packaging dependency version as >=23.2 to avoid its URL validation which can conflict with context formatting
    • Fix the exit code when there happens to be an unhandled exception
    • No longer capture both stdout and stderr streams when parsing metadata payloads from build environments
    • Fix the README.md file template for new projects to avoid Markdown linting issues
    "},{"location":"history/hatch/#hatch-v1.9.7","title":"1.9.7 - 2024-04-24","text":"

    Fixed:

    • Limit the maximum version of virtualenv due to a backward incompatible change
    • Upgrade PyApp to 0.12.0 for binary builds
    "},{"location":"history/hatch/#hatch-v1.9.4","title":"1.9.4 - 2024-03-12","text":"

    Fixed:

    • Limit the maximum version of Hatchling in anticipation of backward incompatible changes
    "},{"location":"history/hatch/#hatch-v1.9.3","title":"1.9.3 - 2024-01-25","text":"

    Fixed:

    • Fix loading of local plugins to account for newly released versions of a dependency
    "},{"location":"history/hatch/#hatch-v1.9.2","title":"1.9.2 - 2024-01-21","text":"

    Fixed:

    • Fix the default token variable name for publishing to PyPI
    "},{"location":"history/hatch/#hatch-v1.9.1","title":"1.9.1 - 2023-12-25","text":"

    Fixed:

    • Ensure that the dependency_hash method of the environment interface is called after sync_dependencies for cases where the hash is only known at that point, such as for dependency lockers
    • Only acknowledge the HATCH_PYTHON_VARIANT_* environment variables for Python resolution for supported platforms and architectures
    • Fix Python resolution when there are metadata hooks with unsatisfied dependencies
    "},{"location":"history/hatch/#hatch-v1.9.0","title":"1.9.0 - 2023-12-19","text":"

    Changed:

    • Environments prefixed by hatch- are now considered internal and used for special purposes such as configuration for static analysis

    Added:

    • Enable docstring formatting by default for static analysis
    • Allow for overriding config of internal environments
    • Concretely state the expected API contract for the environment interface methods find and check_compatibility
    • Upgrade Ruff to 0.1.8
    • Bump the minimum supported version of Hatchling to 1.21.0

    Fixed:

    • Ignore a project's Python requirement for environments where the project is not installed
    • When not persisting config for static analysis, properly manage internal settings when Ruff's top level table already exists
    • Ignore compatibility checks when environments have already been created, significantly improving performance of environment usage
    • Properly allow overriding of the path option for the virtual environment type
    • Fix nushell activation on non-Windows systems
    "},{"location":"history/hatch/#hatch-v1.8.1","title":"1.8.1 - 2023-12-14","text":"

    Fixed:

    • Fix regression in calling subprocesses with updated PATH
    • Fix automatic installation of environment plugins when running as a standalone binary
    • Change default location of Python installations
    "},{"location":"history/hatch/#hatch-v1.8.0","title":"1.8.0 - 2023-12-11","text":"

    Changed:

    • Drop support for Python 3.7
    • The get_build_process method of the environment interface has been removed; plugins should use the new run_builder method instead
    • Remove pyperclip dependency and the --copy flag of the config find command
    • When running the build command all output from builders is now displayed as-is in real time without the stripping of ANSI codes
    • Version information (for Hatch itself) is now derived from Git

    Added:

    • Support Python 3.12
    • Add installers and standalone binaries
    • Add the ability to manage Python installations
    • Add fmt command
    • The virtual environment type can now automatically download requested versions of Python that are not installed
    • Add dependency_hash method to the environment interface
    • The state of installed dependencies for environments is saved as metadata so if dependency definitions have not changed then no checking is performed, which can be computationally expensive
    • The build command now supports backends other than Hatchling
    • Allow the use of features for environments when skip-install is enabled
    • The default is now __token__ when prompting for a username for the publish command
    • Add a new run_builder method to the environment interface
    • Bump the minimum supported version of Hatchling to 1.19.0
    • Bump the minimum supported version of click to 8.0.6

    Fixed:

    • Fix nushell activation
    • Better handling of flat storage directory hierarchies for the virtual environment type
    • Display useful information when running the version command outside of a project rather than erroring
    • Fix the project metadata command by only capturing stdout from the backend
    • Properly support Google Artifact Registry
    • Fix parsing dependencies for environments when warnings are emitted
    "},{"location":"history/hatch/#hatch-v1.7.0","title":"1.7.0 - 2023-04-03","text":"

    Changed:

    • The src-layout project template option is now enabled by default
    • Non-critical output now goes to stderr

    Added:

    • Add tool.hatch.env.requires configuration to automatically install dependencies for environment and environment collector plugins
    • Add custom environment collector
    • Improve syncing of dependencies provided through Git direct references
    • Add isolated_data_directory attribute to the environment interface
    • Increase the timeout for and add retries to the index publisher
    • Expand home and environment variables in configured cache and data directories
    • Improve readability of exceptions
    • Update project templates
    • Bump the minimum supported version of Hatchling to 1.14.0

    Fixed:

    • Fix displaying the version with the version command when the version is static and build dependencies are unmet
    • Fix build environments for the virtual environment type when storing within a relative path
    • Work around System Integrity Protection on macOS when running commands
    • Allow setuptools metadata migration for projects without setup.py if setup.cfg is present
    • Handle additional edge cases for setuptools metadata migration
    • Support boolean values for the config set command
    "},{"location":"history/hatch/#hatch-v1.6.3","title":"1.6.3 - 2022-10-24","text":"

    Fixed:

    • Fix version command when the version is dynamic and build dependencies are unmet
    "},{"location":"history/hatch/#hatch-v1.6.2","title":"1.6.2 - 2022-10-20","text":"

    Fixed:

    • Fix getting dynamic metadata from hooks for environments when dependencies are not dynamic
    "},{"location":"history/hatch/#hatch-v1.6.1","title":"1.6.1 - 2022-10-16","text":"

    Fixed:

    • Computing the path to the user's home directory now gracefully falls back to ~ when it cannot be determined
    "},{"location":"history/hatch/#hatch-v1.6.0","title":"1.6.0 - 2022-10-08","text":"

    Changed:

    • The run_shell_command environment interface method now accepts arbitrary subprocess.Popen keyword arguments. This is not strictly breaking, but will be utilized in upcoming features.
    • The internal directory structure for storing virtual environments is now more nested. This is not breaking, but any local environments will be created anew.

    Added:

    • Add project command group to view details about the project like PEP 621 metadata
    • Better support for auto-detection of environments by tools like Visual Studio Code now that the storage directory of virtual environments will be flat if Hatch's configured virtual environment directory resides somewhere within the project root or if it is set to a .virtualenvs directory within the user's home directory
    • Build environments for the virtual environment type are now cached for improved performance
    • Add build_environment_exists method to the environment interface for implementations that cache the build environment
    • Add path option to the virtual environment type
    • Add --initialize-auth flag to the index publisher to allow for the saving of authentication information before publishing
    • Support Bash on Windows for the shell command
    • The setuptools migration script no longer modifies the formatting of existing pyproject.toml configuration
    • Bump the minimum supported version of Hatchling to 1.11.0

    Fixed:

    • Environments now respect dynamically defined project dependencies
    • The dep hash and all dep show commands now respect dynamically defined project dependencies
    • The env show, dep hash, and all dep show commands now honor context formatting
    • Fix matrix variable inclusion filtering of the run and env run commands when there are multiple possible variables
    • Build environment compatibility is now checked before use
    • Decreasing verbosity now has no affect on output that should always be displayed
    • Handle more edge cases in the setuptools migration script
    • Environments now respect user defined environment variables for context formatting
    • Update the scripts in the generated test environment template for new projects to reflect the documentation
    • Allow extra-dependencies in environment overrides
    • Depend on packaging explicitly rather than relying on it being a transitive dependency of Hatchling
    "},{"location":"history/hatch/#hatch-v1.5.0","title":"1.5.0 - 2022-08-28","text":"

    Added:

    • The index publisher now recognizes repository-specific options
    • Add the --ignore-compat flag to the env run command
    • Setting the HATCH_PYTHON environment variable to self will now force the use of the Python executable Hatch is running on for virtual environment creation

    Fixed:

    • Fix the --force-continue flag of the env run command
    • Handle more edge cases in the setuptools migration script
    "},{"location":"history/hatch/#hatch-v1.4.2","title":"1.4.2 - 2022-08-16","text":"

    Fixed:

    • Fix check for updating static versions with the version command when metadata hooks are in use
    "},{"location":"history/hatch/#hatch-v1.4.1","title":"1.4.1 - 2022-08-13","text":"

    Fixed:

    • Fix non-detached inheritance disabling for environments
    "},{"location":"history/hatch/#hatch-v1.4.0","title":"1.4.0 - 2022-08-06","text":"

    Added:

    • The default Python for virtual environments now checks PATH before using the one Hatch is running on
    • Values for environment env-vars now support context formatting
    • Add name override for environments to allow for regular expression matching
    • The index publisher now better supports non-PyPI indices
    • Add certificate options to the index publisher
    • Display waiting text when checking dependencies and removing environments
    • Display help text the first time the shell command is executed
    • Update project templates with Python 3.11 and the latest versions of various GitHub Actions
    • Add support for Almquist (ash) shells
    • Add hyperlink as a dependency for better handling of package index URLs
    • Bump the minimum supported version of virtualenv to 20.16.2
    • Bump the minimum supported version of tomlkit to 0.11.1

    Fixed:

    • Acknowledge extra-dependencies for the env show command
    • Fix locating executables within virtual environments on Debian
    • Fix managing the terminal size inside the shell command
    • Fix default code coverage file omission for the src-layout project template option
    "},{"location":"history/hatch/#hatch-v1.3.1","title":"1.3.1 - 2022-07-11","text":"

    Fixed:

    • Support -h/--help flag for the run command
    "},{"location":"history/hatch/#hatch-v1.3.0","title":"1.3.0 - 2022-07-10","text":"

    Changed:

    • Rename the default publishing plugin from pypi to the more generic index

    Added:

    • Support the absence of pyproject.toml files, as is the case for apps and non-Python projects
    • Hide scripts that start with an underscore for the env show command by default
    • Ignoring the exit codes of commands by prefixing with hyphens now works with entire named scripts
    • Add a way to require confirmation for publishing
    • Add --force-continue flag to the env run command
    • Make tracebacks colorful and less verbose
    • When shell configuration has not been defined, attempt to use the current shell based on parent processes before resorting to the defaults
    • The shell name pwsh is now an alias for powershell
    • Remove atomicwrites dependency
    • Relax constraint on userpath dependency
    • Bump the minimum supported version of Hatchling to 1.4.1

    Fixed:

    • Keep environments in sync with the dependencies of the selected features
    • Use utf-8 for all files generated for new projects
    • Escape special characters Git may return in the user name when writing generated files for new projects
    • Normalize the package name to lowercase in setuptools migration script
    • Fix parsing of source distributions during publishing
    "},{"location":"history/hatch/#hatch-v1.2.1","title":"1.2.1 - 2022-05-30","text":"

    Fixed:

    • Fix handling of top level data_files in setuptools migration script
    "},{"location":"history/hatch/#hatch-v1.2.0","title":"1.2.0 - 2022-05-22","text":"

    Changed:

    • The enter_shell environment plugin method now accepts an additional args parameter

    Added:

    • Allow context string formatting for environment dependencies
    • Add environment context string formatting fields env_name, env_type, matrix, verbosity, and args
    • Support overriding the default arguments used to spawn shells on non-Windows systems
    • Bump the minimum supported version of Hatchling to 1.3.0

    Fixed:

    • Improve setuptools migration script
    "},{"location":"history/hatch/#hatch-v1.1.2","title":"1.1.2 - 2022-05-20","text":"

    Fixed:

    • Bump the minimum supported version of Hatchling to 1.2.0
    • Update project metadata to reflect support for Python 3.11
    "},{"location":"history/hatch/#hatch-v1.1.1","title":"1.1.1 - 2022-05-12","text":"

    Fixed:

    • Fix setuptools migration script for non-Windows systems
    "},{"location":"history/hatch/#hatch-v1.1.0","title":"1.1.0 - 2022-05-12","text":"

    Changed:

    • In order to simplify the implementation of command execution for environment plugins, the run_shell_commands method has been replaced by the singular run_shell_command. A new command_context method has been added to more easily satisfy complex use cases.
    • The finalize_command environment plugin method has been removed in favor of the newly introduced context formatting functionality.

    Added:

    • Add context formatting functionality i.e. the ability to insert values into configuration like environment variables and command line arguments
    • Any verbosity for command execution will now always display headers, even for single environments
    • Every executed command is now displayed when running multiple commands or when verbosity is enabled
    • Similar to make, ignore the exit code of executed commands that start with - (a hyphen)
    • Add ability for the --init flag of the new command to automatically migrate setuptools configuration
    • Update project metadata to reflect the adoption by PyPA and production stability
    "},{"location":"history/hatch/#hatch-v1.0.0","title":"1.0.0 - 2022-04-28","text":"

    This is the first stable release of Hatch v1, a complete rewrite. Enjoy!

    "},{"location":"history/hatchling/","title":"Hatchling history","text":"

    All notable changes to Hatchling will be documented in this file.

    The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

    "},{"location":"history/hatchling/#unreleased","title":"Unreleased","text":"

    Fixed:

    • Ignore manylinux/musllinux tags for the wheel target artifact name when enabling the infer_tag build data
    "},{"location":"history/hatchling/#hatchling-v1.24.2","title":"1.24.2 - 2024-04-22","text":"

    Fixed:

    • Add .venv to the list of directories that cannot be traversed
    • Output from the core Application utility now writes to stderr
    "},{"location":"history/hatchling/#hatchling-v1.24.1","title":"1.24.1 - 2024-04-18","text":"

    Fixed:

    • Maintain file permissions for shared-scripts option/shared_scripts build data of the wheel target
    "},{"location":"history/hatchling/#hatchling-v1.24.0","title":"1.24.0 - 2024-04-16","text":"

    Added:

    • Add shared_data and shared_scripts build data for the wheel target
    "},{"location":"history/hatchling/#hatchling-v1.23.0","title":"1.23.0 - 2024-04-14","text":"

    Added:

    • Add shared-scripts option for the wheel target

    Fixed:

    • Support recursive optional dependencies
    • Set the packaging dependency version as >=23.2 to avoid its URL validation which can conflict with context formatting
    "},{"location":"history/hatchling/#hatchling-v1.22.5","title":"1.22.5 - 2024-04-04","text":"

    Fixed:

    • Fix reading metadata from source distributions when fields are dynamic but not part of core metadata like entry points
    "},{"location":"history/hatchling/#hatchling-v1.22.4","title":"1.22.4 - 2024-03-23","text":"

    Fixed:

    • Only read source distribution metadata for fields that are explicitly defined as dynamic
    "},{"location":"history/hatchling/#hatchling-v1.22.3","title":"1.22.3 - 2024-03-19","text":"

    Fixed:

    • Fix the custom build hook when using dynamic dependencies
    "},{"location":"history/hatchling/#hatchling-v1.22.2","title":"1.22.2 - 2024-03-16","text":"

    Fixed:

    • Fix regression when loading metadata from source distributions
    • Fix metadata hooks when building wheels from source distributions
    "},{"location":"history/hatchling/#hatchling-v1.22.1","title":"1.22.1 - 2024-03-16","text":"

    Fixed:

    • Update the default version of core metadata to 2.3
    "},{"location":"history/hatchling/#hatchling-v1.22.0","title":"1.22.0 - 2024-03-16","text":"

    Deprecated:

    • The app build target has been renamed to binary to reduce ambiguity with the name of an upcoming feature. The former name will still be usable for several minor releases.

    Added:

    • Metadata for the wheel target now defaults to the PKG-INFO metadata within source distributions
    • Add dependencies method to the build hook interface so that hooks can themselves dynamically define dependencies
    • Update the default version of core metadata to 2.2
    • Update SPDX license information to version 3.23
    • Improve error message for when the default heuristics for wheel file inclusion fail

    Fixed:

    • Properly support core metadata version 2.2
    • Remove editables as a direct dependency
    • Fix default wheel tag when the supported Python version declaration is strict
    • Load VCS ignore patterns first so that whitelisted patterns can be excluded by project configuration
    • Don't consider VCS ignore files that are outside of the VCS boundary
    • The sdist build target now gracefully ignores UNIX socket files
    • Begin ignoring certain files ubiquitously, like .DS_Store on macOS
    "},{"location":"history/hatchling/#hatchling-v1.21.1","title":"1.21.1 - 2024-01-25","text":"

    Fixed:

    • Fix loading of local plugins to account for newly released versions of a dependency
    "},{"location":"history/hatchling/#hatchling-v1.21.0","title":"1.21.0 - 2023-12-18","text":"

    Added:

    • Add parent context modifier for path fields
    "},{"location":"history/hatchling/#hatchling-v1.20.0","title":"1.20.0 - 2023-12-13","text":"

    Added:

    • Add bypass-selection option to the wheel build target to allow for empty (metadata-only) wheels

    Fixed:

    • Fix regression in 1.19.1 that allowed exclude to count toward inclusion selection, thus bypassing the default inclusion selection heuristics
    • Fix writing optional dependency core metadata in situations where there are multiple environment markers
    "},{"location":"history/hatchling/#hatchling-v1.19.1","title":"1.19.1 - 2023-12-12","text":"

    Fixed:

    • Add better error message when the wheel build target cannot determine what to ship
    • Consider forced inclusion patterns and build-time artifacts as file selection since some build hooks generate the entire wheel contents without user configuration
    "},{"location":"history/hatchling/#hatchling-v1.19.0","title":"1.19.0 - 2023-12-11","text":"

    Changed:

    • An error will now be raised if a force-included path does not exist
    • An error will now be raised for the wheel build target if no file selection options are defined

    Added:

    • Officially support Python 3.12
    • Allow using an empty string for the sources option to add a prefix to distribution paths

    Fixed:

    • Properly handle non-zero version epoch for the standard version scheme
    • Fix the wheel build target for case insensitive file systems when the project metadata name does not match the directory name on disk
    • The app build target no longer has suppressed output
    • Prevent duplicate paths when projects require the sources option while build hooks overwrite included paths
    • Properly escape spaces for URI context formatting
    "},{"location":"history/hatchling/#hatchling-v1.18.0","title":"1.18.0 - 2023-06-12","text":"

    Changed:

    • Drop support for Python 3.7

    Added:

    • Update the list of directories that are always excluded for builds
    "},{"location":"history/hatchling/#hatchling-v1.17.1","title":"1.17.1 - 2023-06-03","text":"

    Fixed:

    • Fix dev mode when the project has symlinks and file inclusion is defined with the packages or only-include options
    • Change the name of generated PTH files for dev mode so they come first lexicographically and therefore load first
    "},{"location":"history/hatchling/#hatchling-v1.17.0","title":"1.17.0 - 2023-05-12","text":"

    Added:

    • The app build target now embeds the project version in the name of binaries
    "},{"location":"history/hatchling/#hatchling-v1.16.1","title":"1.16.1 - 2023-05-11","text":"

    Fixed:

    • Fix determining the built executable path for the app build target option when using a local copy of PyApp when there is an explicit target triple set
    "},{"location":"history/hatchling/#hatchling-v1.16.0","title":"1.16.0 - 2023-05-11","text":"

    Added:

    • Add app build target option to build using a local copy of the PyApp repository
    "},{"location":"history/hatchling/#hatchling-v1.15.0","title":"1.15.0 - 2023-05-09","text":"

    Added:

    • Add app build target
    "},{"location":"history/hatchling/#hatchling-v1.14.1","title":"1.14.1 - 2023-04-23","text":"

    Fixed:

    • Fix internal archive root naming for the sdist target when strict-naming is disabled to match the file name in order to support the expectation of some frontends
    "},{"location":"history/hatchling/#hatchling-v1.14.0","title":"1.14.0 - 2023-04-02","text":"

    Added:

    • Add trove-classifiers as a dependency

    Fixed:

    • Properly normalize metadata descriptions that contain line breaks
    "},{"location":"history/hatchling/#hatchling-v1.13.0","title":"1.13.0 - 2023-02-09","text":"

    Added:

    • Update the set of known trove classifiers to version 2023.2.8
    "},{"location":"history/hatchling/#hatchling-v1.12.2","title":"1.12.2 - 2023-01-05","text":"

    Fixed:

    • Add macos-max-compat option to the wheel target that is enabled by default to support the latest version 22.0 of the packaging library
    "},{"location":"history/hatchling/#hatchling-v1.12.1","title":"1.12.1 - 2022-12-31","text":"

    Fixed:

    • Fix minor regression in the PEP 517/660 function signatures that was discovered by Fedora
    "},{"location":"history/hatchling/#hatchling-v1.12.0","title":"1.12.0 - 2022-12-30","text":"

    Added:

    • Improve readability of exceptions
    • Add extra_metadata build data to the wheel target
    • Retroactively support License-Expression core metadata starting at version 2.1
    • Add more type hints
    • Update the set of known trove classifiers to version 2022.12.22
    • Update SPDX license information to version 3.19
    • Store Hatchling's metadata in pyproject.toml

    Fixed:

    • Acknowledge the ARCHFLAGS environment variable on macOS for the wheel target when build hooks set the infer_tag build data to true
    • Fix dependency checking when encountering broken distributions
    • Fix the support-legacy option for the sdist target when using a src-layout project structure
    • Remove unnecessary encoding declaration in the default template for the version build hook
    "},{"location":"history/hatchling/#hatchling-v1.11.1","title":"1.11.1 - 2022-10-19","text":"

    Fixed:

    • Fix default file selection behavior of the wheel target when there is a single top-level module
    "},{"location":"history/hatchling/#hatchling-v1.11.0","title":"1.11.0 - 2022-10-08","text":"

    Added:

    • Add env version source to retrieve the version from an environment variable
    • Add validate-bump option to the standard version scheme

    Fixed:

    • Use proper CSV formatting for the RECORD metadata file of the wheel target to avoid warnings during installation by pip if, for example, file names contain commas
    • Fix installations with pip for build hooks that modify runtime dependencies
    • Decreasing verbosity now has no affect on output that should always be displayed
    "},{"location":"history/hatchling/#hatchling-v1.10.0","title":"1.10.0 - 2022-09-18","text":"

    Added:

    • Add the following to the list of directories that cannot be traversed: __pypackages__, .hg, .hatch, .tox, .nox
    • Add deprecated option to allow ambiguous features

    Fixed:

    • Improve tracking of dynamic metadata
    • Fix core metadata for entries in project.optional-dependencies that use direct references
    "},{"location":"history/hatchling/#hatchling-v1.9.0","title":"1.9.0 - 2022-09-09","text":"

    Changed:

    • File pattern matching now more closely resembles Git's behavior

    Added:

    • Implement a minimal version of prepare_metadata_for_build_wheel and prepare_metadata_for_build_editable for non-frontend tools that only need to inspect a project's metadata
    • Add metadata command to view PEP 621 project metadata
    • Improve error messages for SPDX license errors
    • Retroactively support License-File for core metadata starting at version 2.1
    • Bump the minimum supported version of pathspec to 0.10.1

    Fixed:

    • Allow the valid non-SPDX license values LicenseRef-Public-Domain and LicenseRef-Proprietary
    • Show the help text of the CLI when no subcommand is selected
    "},{"location":"history/hatchling/#hatchling-v1.8.1","title":"1.8.1 - 2022-08-25","text":"

    Fixed:

    • Fix default file inclusion for wheel build targets when both the project name and package directory name are not normalized
    "},{"location":"history/hatchling/#hatchling-v1.8.0","title":"1.8.0 - 2022-08-16","text":"

    Added:

    • Add get_known_classifiers method to metadata hooks

    Fixed:

    • Fix check for updating static versions with the version command when metadata hooks are in use
    "},{"location":"history/hatchling/#hatchling-v1.7.1","title":"1.7.1 - 2022-08-13","text":"

    Fixed:

    • Fix the value of the relative_path attribute of included files, that some build plugins may use, when selecting explicit paths
    "},{"location":"history/hatchling/#hatchling-v1.7.0","title":"1.7.0 - 2022-08-12","text":"

    Added:

    • Add require-runtime-features option for builders and build hooks
    • Check for unknown trove classifiers
    • Update SPDX license information to version 3.18

    Fixed:

    • Add better error message for wheel target dev mode installations that define path rewrites with the sources option
    • Note the allow-direct-references option in the relevant error messages
    "},{"location":"history/hatchling/#hatchling-v1.6.0","title":"1.6.0 - 2022-07-23","text":"

    Changed:

    • When no build targets are specified on the command line, now default to sdist and wheel targets rather than what happens to be defined in config
    • The code version source now only supports files with known extensions
    • Global build hooks now run before target-specific build hooks to better match expected behavior

    Added:

    • The code version source now supports loading extension modules
    • Add search-paths option for the code version source

    Fixed:

    • Fix removing sources using an empty string value in the mapping
    • The strict-naming option now also applies to the metadata directory of wheel targets
    "},{"location":"history/hatchling/#hatchling-v1.5.0","title":"1.5.0 - 2022-07-11","text":"

    Added:

    • Support the final draft of PEP 639
    • Add strict-naming option for sdist and wheel targets

    Fixed:

    • Project names are now stored in sdist and wheel target core metadata exactly as defined in pyproject.toml without normalization to allow control of how PyPI displays them
    "},{"location":"history/hatchling/#hatchling-v1.4.1","title":"1.4.1 - 2022-07-04","text":"

    Fixed:

    • Fix forced inclusion of important files like licenses for sdist targets when using the explicit selection options
    • Don't sort project URL metadata so that the rendered order on PyPI can be controlled
    "},{"location":"history/hatchling/#hatchling-v1.4.0","title":"1.4.0 - 2022-07-03","text":"

    Changed:

    • The packages option uses the new only-include option to provide targeted inclusion, since that is desired most of the time. You can retain the old behavior by using the include and sources options together.

    Added:

    • Support PEP 561 type hinting
    • Add version build hook
    • Add only-include option
    • The editable version of wheel targets now respects the force-include option by default
    • The force-include option now supports path rewriting with the sources option
    • The wheel target shared-data and extra-metadata options now respect file selection options
    • The wheel target now auto-detects single module layouts
    • Improve performance by never entering directories that are guaranteed to be undesirable like __pycache__ rather than excluding individual files within
    • Update SPDX license information to version 3.17

    Fixed:

    • Don't write empty entry points file for wheel targets if there are no entry points defined
    • Allow metadata hooks to set the version in all cases
    • Prevent duplicate file entries from inclusion when using the force-include option
    "},{"location":"history/hatchling/#hatchling-v1.3.1","title":"1.3.1 - 2022-05-30","text":"

    Fixed:

    • Better populate global variables for the code version source
    "},{"location":"history/hatchling/#hatchling-v1.3.0","title":"1.3.0 - 2022-05-22","text":"

    Removed:

    • Remove unused global args context string formatting field

    Added:

    • Improve error messages for the env context string formatting field

    Fixed:

    • Fix uri context string formatting modifier on Windows
    "},{"location":"history/hatchling/#hatchling-v1.2.0","title":"1.2.0 - 2022-05-20","text":"

    Added:

    • Allow context formatting for project.dependencies and project.optional-dependencies
    "},{"location":"history/hatchling/#hatchling-v1.1.0","title":"1.1.0 - 2022-05-19","text":"

    Added:

    • Add uri and real context string formatting modifiers for file system paths
    "},{"location":"history/hatchling/#hatchling-v1.0.0","title":"1.0.0 - 2022-05-17","text":"

    Changed:

    • Drop support for Python 2

    Added:

    • Improve error messaging for invalid versions
    • Update project metadata to reflect support for Python 3.11
    "},{"location":"history/hatchling/#hatchling-v0.25.1","title":"0.25.1 - 2022-06-14","text":"

    Fixed:

    • Fix support for Windows on Python 2 by removing its support for symlinks
    "},{"location":"history/hatchling/#hatchling-v0.25.0","title":"0.25.0 - 2022-05-15","text":"

    Added:

    • Add skip-excluded-dirs build option
    • Allow build data to add additional project dependencies for wheel and sdist build targets
    • Add force_include_editable build data for the wheel build target
    • Add build_hooks build data
    • Add support for Mercurial's .hgignore files when using glob syntax
    • Update project metadata to reflect the adoption by PyPA

    Fixed:

    • Properly use underscores for the name of force_include build data
    • No longer greedily skip excluded directories by default
    "},{"location":"history/hatchling/#hatchling-v0.24.0","title":"0.24.0 - 2022-04-28","text":"

    This is the initial public release of the Hatchling build system. Support for Python 2 will be dropped in version 1.

    "},{"location":"how-to/config/dynamic-metadata/","title":"How to configure custom dynamic metadata","text":"

    If you have project metadata that is not appropriate for static entry into pyproject.toml you will need to provide a custom metadata hook to apply such data during builds.

    Alternatives

    Dynamic metadata is a way to have a single source of truth that will be available at build time and at run time. Another way to achieve that is to enter the build data statically and then look up the same information dynamically in the program or package, using importlib.metadata.

    If the version field is the only metadata of concern, Hatchling provides a few built-in ways such as the regex version source and also third-party plugins. The approach here will also work, but is more complex.

    "},{"location":"how-to/config/dynamic-metadata/#update-project-metadata","title":"Update project metadata","text":"

    Change the [project] section of pyproject.toml:

    1. Define the dynamic field as an array of all the fields you will set dynamically e.g. dynamic = [\"version\", \"license\", \"authors\", \"maintainers\"]
    2. If any of those fields have static definitions in pyproject.toml, delete those definitions. It is verboten to define a field statically and dynamically.

    Add a section to trigger loading of dynamic metadata plugins: [tool.hatch.metadata.hooks.custom]. Use exactly that name, regardless of the name of the class you will use or its PLUGIN_NAME. There doesn't need to be anything in the section.

    If your plugin requires additional third-party packages to do its work, add them to the requires array in the [build-system] section of pyproject.toml.

    "},{"location":"how-to/config/dynamic-metadata/#implement-hook","title":"Implement hook","text":"

    The dynamic lookup must happen in a custom plugin that you write. The default expectation is that it is in a hatch_build.py file at the root of the project. Subclass MetadataHookInterface and implement update(); for example, here's plugin that reads metadata from a JSON file:

    hatch_build.py
    import json\nimport os\n\nfrom hatchling.metadata.plugin.interface import MetadataHookInterface\n\n\nclass JSONMetaDataHook(MetadataHookInterface):\n    def update(self, metadata):\n        src_file = os.path.join(self.root, \"gnumeric\", \".constants.json\")\n        with open(src_file) as src:\n            constants = json.load(src)\n            metadata[\"version\"] = constants[\"__version__\"]\n            metadata[\"license\"] = constants[\"__license__\"]\n            metadata[\"authors\"] = [\n                {\"name\": constants[\"__author__\"], \"email\": constants[\"__author_email__\"]},\n            ]\n
    1. You must import the MetadataHookInterface to subclass it.
    2. Do your operations inside the update method.
    3. metadata refers to project metadata.
    4. When writing to metadata, use list for TOML arrays. Note that if a list is expected, it is required even if there is a single element.
    5. Use dict for TOML tables e.g. authors.

    If you want to store the hook in a different location, set the path option:

    pyproject.toml hatch.toml
    [tool.hatch.metadata.hooks.custom]\npath = \"some/where.py\"\n
    [metadata.hooks.custom]\npath = \"some/where.py\"\n
    "},{"location":"how-to/environment/dependency-resolution/","title":"How to configure dependency resolution","text":"

    Most Hatch environment types, like the default virtual, simply use pip to install dependencies. Therefore, you can use the standard environment variables that influence pip's behavior.

    Here's an example of setting up the default environment to look at 2 private indices (using context formatting for authentication) before finally falling back to PyPI:

    pyproject.toml hatch.toml
    [tool.hatch.envs.default.env-vars]\nPIP_INDEX_URL = \"https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group1_path>/-/packages/pypi/simple/\"\nPIP_EXTRA_INDEX_URL = \"https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group2_path>/-/packages/pypi/simple/ https://pypi.org/simple/\"\n
    [envs.default.env-vars]\nPIP_INDEX_URL = \"https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group1_path>/-/packages/pypi/simple/\"\nPIP_EXTRA_INDEX_URL = \"https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group2_path>/-/packages/pypi/simple/ https://pypi.org/simple/\"\n
    "},{"location":"how-to/environment/dependency-resolution/#uv","title":"UV","text":"

    If you're using UV, a different set of environment variables are available to configure its behavior. The previous example would look like this instead:

    pyproject.toml hatch.toml
    [tool.hatch.envs.default.env-vars]\nUV_EXTRA_INDEX_URL = \"https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group1_path>/-/packages/pypi/simple/\"\nUV_INDEX_URL = \"https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group2_path>/-/packages/pypi/simple/ https://pypi.org/simple/\"\n
    [envs.default.env-vars]\nUV_EXTRA_INDEX_URL = \"https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group1_path>/-/packages/pypi/simple/\"\nUV_INDEX_URL = \"https://token:{env:GITLAB_API_TOKEN}@gitlab.com/api/v4/groups/<group2_path>/-/packages/pypi/simple/ https://pypi.org/simple/\"\n

    Tip

    If you need precise control over the prioritization of package indices, then using UV is recommended because pip has no index order guarantee.

    "},{"location":"how-to/environment/select-installer/","title":"How to select the installer","text":""},{"location":"how-to/environment/select-installer/#enabling-uv","title":"Enabling UV","text":"

    The virtual environment type by default uses virtualenv for virtual environment creation and pip to install dependencies. You can speed up environment creation and dependency resolution by using UV instead of both of those tools.

    caveat

    UV is under active development and may not work for all dependencies.

    To do so, set the installer option to uv. For example, if you wanted to enable this functionality for the default environment, you could set the following:

    pyproject.toml hatch.toml
    [tool.hatch.envs.default]\ninstaller = \"uv\"\n
    [envs.default]\ninstaller = \"uv\"\n

    Tip

    All environments that enable UV will have the path to UV available as the HATCH_UV environment variable.

    "},{"location":"how-to/environment/select-installer/#configuring-the-version","title":"Configuring the version","text":"

    The UV that is shared by all environments uses a specific version range that is known to work with Hatch. If you want to use a different version, you can override the dependencies for the internal hatch-uv environment:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-uv]\ndependencies = [\n  \"uv>9000\",\n]\n
    [envs.hatch-uv]\ndependencies = [\n  \"uv>9000\",\n]\n
    "},{"location":"how-to/environment/select-installer/#externally-managed","title":"Externally managed","text":"

    If you want to manage UV yourself, you can expose it to Hatch by setting the HATCH_ENV_TYPE_VIRTUAL_UV_PATH environment variable which should be the absolute path to a UV binary for Hatch to use instead. This implicitly enables UV.

    "},{"location":"how-to/environment/select-installer/#installer-script-alias","title":"Installer script alias","text":"

    If you have scripts or commands that call pip, it may be useful to alias the uv pip command to pip so that you can use the same commands for both methods of configuration and retain your muscle memory. The following is an example of a matrix that conditionally enables UV and sets the alias:

    pyproject.toml hatch.toml
    [[tool.hatch.envs.example.matrix]]\ntool = [\"uv\", \"pip\"]\n\n[tool.hatch.envs.example.overrides]\nmatrix.tool.installer = { value = \"{matrix:tool}\" }\nmatrix.tool.scripts = [\n  { key = \"pip\", value = \"{env:HATCH_UV} pip {args}\", if = [\"uv\"] },\n]\n
    [[envs.example.matrix]]\ntool = [\"uv\", \"pip\"]\n\n[envs.example.overrides]\nmatrix.tool.installer = { value = \"{matrix:tool}\" }\nmatrix.tool.scripts = [\n  { key = \"pip\", value = \"{env:HATCH_UV} pip {args}\", if = [\"uv\"] },\n]\n

    Another common use case is to expose UV to all test environments. In this case, you often wouldn't want to modify the scripts mapping directly but rather add an extra script:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-test.extra-scripts]\npip = \"{env:HATCH_UV} pip {args}\"\n
    [envs.hatch-test.extra-scripts]\npip = \"{env:HATCH_UV} pip {args}\"\n
    "},{"location":"how-to/integrate/vscode/","title":"How to use Hatch environments from Visual Studio Code","text":"

    Visual Studio Code announced support for Hatch environment discovery in vscode-python's 2024.4 release.

    For it to work, you should install Hatch globally. If you used the GUI installers on Windows or macOS, or your system package manager on e.g. Arch Linux or Fedora, this should be taken care of.

    Setting up PATH

    If you installed Hatch with pipx rather than system-wide, you might need to add $HOME/.local/bin to your PATH environment variable for your graphical session, not just your terminal. Check like this:

    $ pgrep bin/code  # or some other graphical application\n1234\n$ cat /proc/1234/environ | tr '\\0' '\\n' | grep -E '^PATH='\nPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n

    If the directory is not in there, you need to add it in your session startup script, in a way that depends on your desktop environment:

    • KDE Plasma
    • GNOME
    "},{"location":"how-to/integrate/vscode/#project-setup","title":"Project setup","text":"
    1. Make Hatch install the project and its dependencies to an environment using the env create command.

    2. Select an interpreter using the Python: Select Interpreter command:

    3. You should now be able to use the environment. For example, if you have the python.terminal.activateEnvironment setting set to true and you open a new terminal, the environment should be activated. Alternatively, you could press the \"play\" button to run a file in the environment:

    "},{"location":"how-to/meta/report-issues/","title":"How to report issues","text":"

    All reports regarding unexpected behavior should be generated with the self report command:

    $ hatch self report\n

    By default, this will open a new tab in your default browser with pre-populated information about your environment.

    If Hatch is not installed alongside a web browser, you may also pass the --no-open/-n command which will output the URL with correct parameters for copying elsewhere:

    $ hatch self report -n\nhttps://github.com/pypa/hatch/issues/new?body=%23%23+Current+behavior%0A%3C%21--+A+clear+and+concise+description+of+the+behavior.+--%3E%0A%0A%23%23+Expected+behavior%0A%3C%21--+A+clear+and+concise+description+of+what+you+expected+to+happen.+--%3E%0A%0A%23%23+Additional+context%0A%3C%21--+Add+any+other+context+about+the+problem+here.+If+applicable%2C+add+screenshots+to+help+explain.+--%3E%0A%0A%23%23+Debug%0A%0A%23%23%23+Installation%0A%0A-+Source%3A+pip%0A-+Version%3A+1.9.2.dev5%0A-+Platform%3A+Windows%0A-+Python+version%3A%0A++++%60%60%60%0A++++3.11.1+%28tags%2Fv3.11.1%3Aa7a450f%2C+Dec++6+2022%2C+19%3A58%3A39%29+%5BMSC+v.1934+64+bit+%28AMD64%29%5D%0A++++%60%60%60%0A%0A%23%23%23+Configuration%0A%0A%60%60%60toml%0Amode+%3D+%22local%22%0Ashell+%3D+%22nu%22%0A%60%60%60%0A\n
    "},{"location":"how-to/plugins/testing-builds/","title":"Testing build plugins","text":"

    For testing Hatchling plugins, you'll usually want to generate a project to execute builds as a real user would. For example, as a minimal pytest fixture:

    from pathlib import Path\n\nimport pytest\n\n\n@pytest.fixture\ndef new_project(tmp_path):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {Path.cwd().as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n

    The issue with this is that after the first test session, the project will be forever cached by pip based on the file path. Therefore, subsequent tests runs will never use updated code.

    To invalidate the cache, copy your code to a new path for every test session:

    import shutil\nfrom pathlib import Path\nfrom tempfile import TemporaryDirectory\n\nimport pytest\n\n\n@pytest.fixture(scope='session')\ndef plugin_dir():\n    with TemporaryDirectory() as d:\n        directory = Path(d, 'plugin')\n        shutil.copytree(\n            Path.cwd(), directory, ignore=shutil.ignore_patterns('.git')\n        )\n\n        yield directory.resolve()\n\n\n@pytest.fixture\ndef new_project(tmp_path, plugin_dir):\n    project_dir = tmp_path / 'my-app'\n    project_dir.mkdir()\n\n    project_file = project_dir / 'pyproject.toml'\n    project_file.write_text(\n        f\"\"\"\\\n[build-system]\nrequires = [\"hatchling\", \"hatch-plugin-name @ {plugin_dir.as_uri()}\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-app\"\nversion = \"0.1.0\"\n\"\"\",\n        encoding='utf-8',\n    )\n    ...\n

    Note

    This example chooses to ignore copying .git for performance reasons. You may want to ignore more patterns, or copy only specific paths like this plugin does.

    "},{"location":"how-to/publish/auth/","title":"How to authenticate for index publishing","text":"

    The username is derived from the following sources, in order of precedence:

    1. The --user / -u cli option.
    2. The HATCH_INDEX_USER environment variable.
    3. The repos tables.
    4. The ~/.pypirc file.
    5. The input to an interactive prompt.

    As a fallback the value __token__ is applied.

    The password is looked up in these:

    1. The ~/.pypirc file if the username was provided by it.
    2. The --auth / -a cli option.
    3. The HATCH_INDEX_AUTH environment variable.
    4. The repos tables.
    5. A variety of OS-level credentials services backed by keyring.
    6. The input to an interactive prompt.

    If interactively provided credentials were used, the username will be stored in Hatch's cache and the password stored in the available keyring backed credentials stores.

    For automated releasing to PyPI, it is recommended to use \"Trusted Publishing\" with OIDC (e.g. PyPA's pypi-publish GitHub Action) or per-project API tokens.

    "},{"location":"how-to/publish/repo/","title":"How to configure repositories for index publishing","text":"

    You can select the repository with which to upload using the -r/--repo option or by setting the HATCH_INDEX_REPO environment variable.

    Rather than specifying the full URL of a repository, you can use a named repository from a publish.index.repos table defined in Hatch's config file:

    config.toml
    [publish.index.repos.private]\nurl = \"...\"\n...\n

    The following repository names are reserved by Hatch and cannot be overridden:

    Name Repository main https://upload.pypi.org/legacy/ test https://test.pypi.org/legacy/

    The main repository is used by default.

    "},{"location":"how-to/python/custom/","title":"How to use custom Python distributions","text":"

    The built-in Python management capabilities offer full support for using custom distributions.

    "},{"location":"how-to/python/custom/#configuration","title":"Configuration","text":"

    Configuring custom Python distributions is done entirely through three environment variables that must all be defined, for each desired distribution. In the following sections, the placeholder <NAME> is the uppercased version of the distribution name with periods replaced by underscores e.g. pypy3.10 would become PYPY3_10.

    "},{"location":"how-to/python/custom/#source","title":"Source","text":"

    The HATCH_PYTHON_CUSTOM_SOURCE_<NAME> variable is the URL to the distribution's archive. The value must end with the archive's real file extension, which is used to determine the extraction method.

    The following extensions are supported:

    Extensions Description
    • .tar.bz2
    • .bz2
    A tar file with bzip2 compression
    • .tar.gz
    • .tgz
    A tar file with gzip compression
    • .tar.zst
    • .tar.zstd
    A tar file with Zstandard compression
    • .zip
    A ZIP file with DEFLATE compression"},{"location":"how-to/python/custom/#python-path","title":"Python path","text":"

    The HATCH_PYTHON_CUSTOM_PATH_<NAME> variable is the path to the Python interpreter within the archive. This path is relative to the root of the archive and must be a Unix-style path, even on Windows.

    "},{"location":"how-to/python/custom/#version","title":"Version","text":"

    The HATCH_PYTHON_CUSTOM_VERSION_<NAME> variable is the version of the distribution. This value is used to determine whether updates are required and is displayed in the output of the python show command.

    "},{"location":"how-to/run/python-scripts/","title":"How to run Python scripts","text":"

    The run command supports executing Python scripts with inline metadata, such that a dedicated environment is automatically created with the required dependencies and with the correct version of Python.

    A script metadata block is a comment block that starts with # /// script and ends with # ///. Every line between those two lines must be a comment line that starts with # and contains a TOML document when the comment characters are removed.

    The top-level fields are:

    • dependencies: A list of strings that specifies the runtime dependencies of the script. Each entry must be a valid dependency specifier.
    • requires-python: A string that specifies the Python version(s) with which the script is compatible. The value of this field must be a valid version specifier.

    The following is an example of Python script with a valid metadata block:

    script.py
    # /// script\n# requires-python = \">=3.11\"\n# dependencies = [\n#   \"httpx\",\n#   \"rich\",\n# ]\n# ///\n\nimport httpx\nfrom rich.pretty import pprint\n\nresp = httpx.get(\"https://peps.python.org/api/peps.json\")\ndata = resp.json()\npprint([(k, v[\"title\"]) for k, v in data.items()][:10])\n

    Run it directly:

    $ hatch run /path/to/script.py\nCreating environment: SyB4bPbL\nChecking dependencies\nSyncing dependencies\n[\n\u2502   ('1', 'PEP Purpose and Guidelines'),\n\u2502   ('2', 'Procedure for Adding New Modules'),\n\u2502   ('3', 'Guidelines for Handling Bug Reports'),\n\u2502   ('4', 'Deprecation of Standard Modules'),\n\u2502   ('5', 'Guidelines for Language Evolution'),\n\u2502   ('6', 'Bug Fix Releases'),\n\u2502   ('7', 'Style Guide for C Code'),\n\u2502   ('8', 'Style Guide for Python Code'),\n\u2502   ('9', 'Sample Plaintext PEP Template'),\n\u2502   ('10', 'Voting Guidelines')\n]\n

    notes

    • The informational text in this example is only temporarily shown in your terminal on the first run.
    • Although the environment name is based on the script's absolute path, the command line argument does not have to be.
    "},{"location":"how-to/run/python-scripts/#environment-configuration","title":"Environment configuration","text":"

    You may use the [tool.hatch] table directly to control the script's environment. For example, if you wanted to disable UV (which is enabled by default for scripts), you could add the following:

    script.py
    # /// script\n# ...\n# [tool.hatch]\n# installer = \"pip\"\n# ///\n
    "},{"location":"how-to/static-analysis/behavior/","title":"Customize static analysis behavior","text":"

    You can fully alter the static analysis performed by the fmt command by modifying the reserved environment named hatch-static-analysis. For example, you could define the following if you wanted to replace the default behavior with a mix of Black, isort and basic flake8:

    pyproject.toml hatch.toml
    [tool.hatch.envs.hatch-static-analysis]\ndependencies = [\"black\", \"flake8\", \"isort\"]\n\n[tool.hatch.envs.hatch-static-analysis.scripts]\nformat-check = [\n  \"black --check --diff {args:.}\",\n  \"isort --check-only --diff {args:.}\",\n]\nformat-fix = [\n  \"isort {args:.}\",\n  \"black {args:.}\",\n]\nlint-check = \"flake8 {args:.}\"\nlint-fix = \"lint-check\"\n
    [envs.hatch-static-analysis]\ndependencies = [\"black\", \"flake8\", \"isort\"]\n\n[envs.hatch-static-analysis.scripts]\nformat-check = [\n  \"black --check --diff {args:.}\",\n  \"isort --check-only --diff {args:.}\",\n]\nformat-fix = [\n  \"isort {args:.}\",\n  \"black {args:.}\",\n]\nlint-check = \"flake8 {args:.}\"\nlint-fix = \"lint-check\"\n

    The format-* scripts correspond to the --formatter/-f flag while the lint-* scripts correspond to the --linter/-l flag. The *-fix scripts run by default while the *-check scripts correspond to the --check flag. Based on this example, the following shows how the various scripts influence behavior:

    Command Expanded scripts hatch fmt
    • flake8 .
    • isort .
    • black .
    hatch fmt src tests
    • flake8 src tests
    • isort src tests
    • black src tests
    hatch fmt -f
    • isort .
    • black .
    hatch fmt -l
    • flake8 .
    hatch fmt --check
    • flake8 .
    • black --check --diff .
    • isort --check-only --diff .
    hatch fmt --check -f
    • black --check --diff .
    • isort --check-only --diff .
    hatch fmt --check -l
    • flake8 .
    "},{"location":"meta/authors/","title":"Authors","text":""},{"location":"meta/authors/#maintainers","title":"Maintainers","text":"
    • Ofek Lev
    "},{"location":"meta/authors/#contributors","title":"Contributors","text":"
    • Amjith Ramanujam
    • Arnaud Crowther
    • Chaojie
    • Chris Warrick
    • Lum\u00edr 'Frenzy' Balhar
    • Ofek Lev
    • Olga Matoula
    • Philip Blair
    • Robert Rosca
    "},{"location":"meta/faq/","title":"FAQ","text":""},{"location":"meta/faq/#interoperability","title":"Interoperability","text":"

    Q: What is the risk of lock-in?

    A: Not much! Other than the plugin system, everything uses Python's established standards by default. Project metadata is based entirely on the standard, the build system is compatible with PEP 517/PEP 660, versioning uses the scheme specified by PEP 440, dependencies are defined with PEP 508 strings, and environments use virtualenv.

    Q: Must one use all features?

    A: No, all features are optional! You can use just the build system, publish wheels and source distributions that were built by other tools, only use the environment management, etc.

    "},{"location":"meta/faq/#libraries-vs-applications","title":"Libraries vs applications","text":"

    Q: Are workflows for both libraries and applications supported?

    A: Yes, mostly! Applications can utilize environment management just like libraries, and plugins can be used to build projects in arbitrary formats or publish artifacts to arbitrary destinations.

    The only caveat is that currently there is no support for re-creating an environment given a set of dependencies in a reproducible manner. Although a standard lock file format may be far off since PEP 665 was rejected, resolving capabilities are coming to pip. When that is stabilized, Hatch will add locking functionality and dedicated documentation for managing applications.

    "},{"location":"meta/faq/#tool-migration","title":"Tool migration","text":"

    Q: How to migrate to Hatch?

    "},{"location":"meta/faq/#build-system","title":"Build system","text":"SetuptoolsHatch setup.py MANIFEST.in
    import os\nfrom io import open\n\nfrom setuptools import find_packages, setup\n\nabout = {}\nwith open(os.path.join('src', 'foo', '__about__.py'), 'r', 'utf-8') as f:\n    exec(f.read(), about)\n\nwith open('README.md', 'r', 'utf-8') as f:\n    readme = f.read()\n\nsetup(\n    # Metadata\n    name='foo',\n    version=about['__version__'],\n    description='...',\n    long_description=readme,\n    long_description_content_type='text/markdown',\n    author='...',\n    author_email='...',\n    project_urls={\n        'Documentation': '...',\n        'Source': '...',\n    },\n    classifiers=[\n        '...',\n    ],\n    keywords=[\n        '...',\n    ],\n    python_requires='>=3.8',\n    install_requires=[\n        '...',\n    ],\n    extras_require={\n        'feature': ['...'],\n    },\n\n    # Packaging\n    packages=find_packages(where='src'),\n    package_dir={'': 'src'},\n    package_data={\n        'foo': ['py.typed'],\n    },\n    zip_safe=False,\n    entry_points={\n        'console_scripts': [\n            'foo = foo.cli:main',\n        ],\n    },\n)\n
    graft tests\n\nglobal-exclude *.py[cod] __pycache__\n
    pyproject.toml
    [build-system]\nrequires = [\"hatchling\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"foo\"\ndescription = \"...\"\nreadme = \"README.md\"\nauthors = [\n  { name = \"...\", email = \"...\" },\n]\nclassifiers = [\n  \"...\",\n]\nkeywords = [\n  \"...\",\n]\nrequires-python = \">=3.8\"\ndependencies = [\n  \"...\",\n]\ndynamic = [\"version\"]\n\n[project.urls]\nDocumentation = \"...\"\nSource = \"...\"\n\n[project.optional-dependencies]\nfeature = [\"...\"]\n\n[project.scripts]\nfoo = \"foo.cli:main\"\n\n[tool.hatch.version]\npath = \"src/foo/__about__.py\"\n\n[tool.hatch.build.targets.sdist]\ninclude = [\n  \"/src\",\n  \"/tests\",\n]\n
    "},{"location":"meta/faq/#environments","title":"Environments","text":"ToxHatch

    Invocation:

    tox\n
    tox.ini
    [tox]\nenvlist =\n    py{38,39}-{42,3.14}\n    py{39,310}-{9000}-{foo,bar}\n\n[testenv]\nusedevelop = true\ndeps =\n    coverage[toml]\n    pytest\n    pytest-cov\n    foo: cryptography\ncommands =\n    pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests {posargs}\nsetenv =\n    3.14: PRODUCT_VERSION=3.14\n    42: PRODUCT_VERSION=42\n    9000: PRODUCT_VERSION=9000\n    {foo,bar}: EXPERIMENTAL=true\n

    Invocation:

    hatch run test\n
    pyproject.toml hatch.toml
    [tool.hatch.envs.default]\ndependencies = [\n  \"coverage[toml]\",\n  \"pytest\",\n  \"pytest-cov\",\n]\n\n[tool.hatch.envs.default.scripts]\ntest = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests'\n\n[tool.hatch.envs.default.overrides]\nmatrix.version.env-vars = \"PRODUCT_VERSION\"\nmatrix.feature.env-vars = \"EXPERIMENTAL=true\"\nmatrix.feature.dependencies = [\n  { value = \"cryptography\", if = [\"foo\"] },\n]\n\n[[tool.hatch.envs.default.matrix]]\npython = [\"3.8\", \"3.9\"]\nversion = [\"42\", \"3.14\"]\n\n[[tool.hatch.envs.default.matrix]]\npython = [\"3.9\", \"3.10\"]\nversion = [\"9000\"]\nfeature = [\"foo\", \"bar\"]\n
    [envs.default]\ndependencies = [\n  \"coverage[toml]\",\n  \"pytest\",\n  \"pytest-cov\",\n]\n\n[envs.default.scripts]\ntest = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg --cov=tests'\n\n[envs.default.overrides]\nmatrix.version.env-vars = \"PRODUCT_VERSION\"\nmatrix.feature.env-vars = \"EXPERIMENTAL=true\"\nmatrix.feature.dependencies = [\n  { value = \"cryptography\", if = [\"foo\"] },\n]\n\n[[envs.default.matrix]]\npython = [\"3.8\", \"3.9\"]\nversion = [\"42\", \"3.14\"]\n\n[[envs.default.matrix]]\npython = [\"3.9\", \"3.10\"]\nversion = [\"9000\"]\nfeature = [\"foo\", \"bar\"]\n
    "},{"location":"meta/faq/#fast-cli","title":"Fast CLI?","text":"

    The claim about being faster than other tools is based on timings that are always checked in CI.

    Hatch achieves this by using lazy imports, lazily performing computation manually and with functools.cached_property, using hacks like not not ... instead of bool(...), etc.

    "},{"location":"plugins/about/","title":"Plugins","text":"

    Hatch utilizes pluggy for its plugin functionality.

    "},{"location":"plugins/about/#overview","title":"Overview","text":"

    All plugins provide registration hooks that return one or more classes that inherit from a particular type interface.

    Each registration hook must be decorated by Hatch's hook marker. For example, if you wanted to create a new kind of environment you could do:

    hooks.py
    from hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialEnvironment\n\n\n@hookimpl\ndef hatch_register_environment():\n    return SpecialEnvironment\n

    The hooks can return a single class or a list of classes.

    Every class must define an attribute called PLUGIN_NAME that users will select when they wish to use the plugin. So in the example above, the class might be defined like:

    plugin.py
    ...\nclass SpecialEnvironment(...):\n    PLUGIN_NAME = 'special'\n    ...\n
    "},{"location":"plugins/about/#project-configuration","title":"Project configuration","text":""},{"location":"plugins/about/#naming","title":"Naming","text":"

    It is recommended that plugin project names are prefixed with hatch-. For example, if you wanted to make a plugin that provides some functionality for a product named foo you might do:

    pyproject.toml
    [project]\nname = \"hatch-foo\"\n
    "},{"location":"plugins/about/#discovery","title":"Discovery","text":"

    You'll need to define your project as a Python plugin for Hatch:

    pyproject.toml
    [project.entry-points.hatch]\nfoo = \"pkg.hooks\"\n

    The name of the plugin should be the project name (excluding any hatch- prefix) and the path should represent the module that contains the registration hooks.

    "},{"location":"plugins/about/#classifier","title":"Classifier","text":"

    Add Framework :: Hatch to your project's classifiers to make it easy to search for Hatch plugins:

    pyproject.toml
    [project]\nclassifiers = [\n  ...\n  \"Framework :: Hatch\",\n  ...\n]\n
    "},{"location":"plugins/about/#types","title":"Types","text":""},{"location":"plugins/about/#hatchling","title":"Hatchling","text":"

    These are all involved in building projects and therefore any defined dependencies are automatically installed in each build environment.

    • Builder
    • Build hook
    • Metadata hook
    • Version source
    • Version scheme
    "},{"location":"plugins/about/#hatch","title":"Hatch","text":"

    These must be installed in the same environment as Hatch itself.

    • Environment
    • Environment collector
    • Publisher
    "},{"location":"plugins/utilities/","title":"Plugin utilities","text":""},{"location":"plugins/utilities/#hatchling.builders.utils.get_reproducible_timestamp","title":"hatchling.builders.utils.get_reproducible_timestamp() -> int","text":"

    Returns an int derived from the SOURCE_DATE_EPOCH environment variable; see https://reproducible-builds.org/specs/source-date-epoch/.

    The default value will always be: 1580601600

    Source code in backend/src/hatchling/builders/utils.py
    def get_reproducible_timestamp() -> int:\n    \"\"\"\n    Returns an `int` derived from the `SOURCE_DATE_EPOCH` environment variable; see\n    https://reproducible-builds.org/specs/source-date-epoch/.\n\n    The default value will always be: `1580601600`\n    \"\"\"\n    return int(os.environ.get('SOURCE_DATE_EPOCH', '1580601600'))\n
    "},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig","title":"BuilderConfig","text":""},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.directory","title":"directory: str property","text":""},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.ignore_vcs","title":"ignore_vcs: bool property","text":""},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.reproducible","title":"reproducible: bool property","text":"

    Whether or not the target should be built in a reproducible manner, defaulting to true.

    "},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.dev_mode_dirs","title":"dev_mode_dirs: list[str] property","text":"

    Directories which must be added to Python's search path in dev mode.

    "},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.versions","title":"versions: list[str] property","text":""},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.dependencies","title":"dependencies: list[str] property","text":""},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.default_include","title":"default_include() -> list","text":""},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.default_exclude","title":"default_exclude() -> list","text":""},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.default_packages","title":"default_packages() -> list","text":""},{"location":"plugins/utilities/#hatchling.builders.config.BuilderConfig.default_only_include","title":"default_only_include() -> list","text":""},{"location":"plugins/utilities/#hatchling.bridge.app.Application","title":"Application","text":"

    The way output is displayed can be configured by users.

    Important

    Never import this directly; Hatch judiciously decides if a type of plugin requires the capabilities herein and will grant access via an attribute.

    "},{"location":"plugins/utilities/#hatchling.bridge.app.Application.verbosity","title":"verbosity: int property","text":"

    The verbosity level of the application, with 0 as the default.

    "},{"location":"plugins/utilities/#hatchling.bridge.app.Application.abort","title":"abort(message: str = '', code: int = 1, **kwargs: Any) -> None","text":"

    Terminate the program with the given return code.

    "},{"location":"plugins/utilities/#hatchling.bridge.app.Application.display_debug","title":"display_debug(message: str = '', level: int = 1, **kwargs: Any) -> None","text":"

    Meant to be used for messages that are not useful for most user experiences. The level option must be between 1 and 3 (inclusive).

    "},{"location":"plugins/utilities/#hatchling.bridge.app.Application.display_error","title":"display_error(message: str = '', **kwargs: Any) -> None","text":"

    Meant to be used for messages indicating some unrecoverable error.

    "},{"location":"plugins/utilities/#hatchling.bridge.app.Application.display_info","title":"display_info(message: str = '', **kwargs: Any) -> None","text":"

    Meant to be used for messages conveying basic information.

    "},{"location":"plugins/utilities/#hatchling.bridge.app.Application.display_success","title":"display_success(message: str = '', **kwargs: Any) -> None","text":"

    Meant to be used for messages indicating some positive outcome.

    "},{"location":"plugins/utilities/#hatchling.bridge.app.Application.display_waiting","title":"display_waiting(message: str = '', **kwargs: Any) -> None","text":"

    Meant to be used for messages shown before potentially time consuming operations.

    "},{"location":"plugins/utilities/#hatchling.bridge.app.Application.display_warning","title":"display_warning(message: str = '', **kwargs: Any) -> None","text":"

    Meant to be used for messages conveying important information.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform","title":"Platform","text":""},{"location":"plugins/utilities/#hatch.utils.platform.Platform.default_shell","title":"default_shell: str property","text":"

    Returns the default shell of the system.

    On Windows systems first try the SHELL environment variable, if present, followed by the COMSPEC environment variable, defaulting to cmd. On all other platforms only the SHELL environment variable will be used, defaulting to bash.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.modules","title":"modules: LazilyLoadedModules property","text":"

    Accessor for lazily loading modules that either take multiple milliseconds to import (like shutil and subprocess) or are not used on all platforms (like shlex).

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.home","title":"home: Path property","text":"

    The user's home directory as a path-like object.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.name","title":"name: str property","text":"

    One of the following:

    • linux
    • windows
    • macos
    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.display_name","title":"display_name: str property","text":"

    One of the following:

    • Linux
    • Windows
    • macOS
    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.windows","title":"windows: bool property","text":"

    Indicates whether Hatch is running on Windows.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.macos","title":"macos: bool property","text":"

    Indicates whether Hatch is running on macOS.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.linux","title":"linux: bool property","text":"

    Indicates whether Hatch is running on neither Windows nor macOS.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.format_for_subprocess","title":"format_for_subprocess(command: str | list[str], *, shell: bool) -> str | list[str]","text":"

    Format the given command in a cross-platform manner for immediate consumption by subprocess utilities.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.run_command","title":"run_command(command: str | list[str], *, shell: bool = False, **kwargs: Any) -> CompletedProcess","text":"

    Equivalent to the standard library's subprocess.run, with the command first being properly formatted.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.check_command","title":"check_command(command: str | list[str], *, shell: bool = False, **kwargs: Any) -> CompletedProcess","text":"

    Equivalent to run_command, but non-zero exit codes will gracefully end program execution.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.check_command_output","title":"check_command_output(command: str | list[str], *, shell: bool = False, **kwargs: Any) -> str","text":"

    Equivalent to the output from the process returned by capture_process, but non-zero exit codes will gracefully end program execution.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.capture_process","title":"capture_process(command: str | list[str], *, shell: bool = False, **kwargs: Any) -> Popen","text":"

    Equivalent to the standard library's subprocess.Popen, with all output captured by stdout and the command first being properly formatted.

    "},{"location":"plugins/utilities/#hatch.utils.platform.Platform.exit_with_command","title":"exit_with_command(command: list[str]) -> None","text":"

    Run the given command and exit with its exit code. On non-Windows systems, this uses the standard library's os.execvp.

    "},{"location":"plugins/utilities/#hatch.env.context.EnvironmentContextFormatter","title":"EnvironmentContextFormatter","text":""},{"location":"plugins/utilities/#hatch.env.context.EnvironmentContextFormatter.formatters","title":"formatters()","text":"

    This returns a mapping of supported field names to their respective formatting functions. Each function accepts 2 arguments:

    • the value that was passed to the format call, defaulting to None
    • the modifier data, defaulting to an empty string
    "},{"location":"plugins/build-hook/custom/","title":"Custom build hook","text":"

    This is a custom class in a given Python file that inherits from the BuildHookInterface.

    "},{"location":"plugins/build-hook/custom/#configuration","title":"Configuration","text":"

    The build hook plugin name is custom.

    pyproject.toml hatch.toml
    [tool.hatch.build.hooks.custom]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.custom]\n
    [build.hooks.custom]\n[build.targets.<TARGET_NAME>.hooks.custom]\n
    "},{"location":"plugins/build-hook/custom/#options","title":"Options","text":"Option Default Description path hatch_build.py The path of the Python file"},{"location":"plugins/build-hook/custom/#example","title":"Example","text":"hatch_build.py
    from hatchling.builders.hooks.plugin.interface import BuildHookInterface\n\n\nclass CustomBuildHook(BuildHookInterface):\n    ...\n

    If multiple subclasses are found, you must define a function named get_build_hook that returns the desired build hook.

    Note

    Any defined PLUGIN_NAME is ignored and will always be custom.

    "},{"location":"plugins/build-hook/reference/","title":"Build hook plugins","text":"

    A build hook provides code that will be executed at various stages of the build process. See the documentation for build hook configuration.

    "},{"location":"plugins/build-hook/reference/#known-third-party","title":"Known third-party","text":"
    • hatch-argparse-manpage - generate man pages for argparse-based CLIs
    • hatch-autorun - used to inject code into an installation that will automatically run before the first import
    • hatch-build-scripts - run arbitrary shell commands that create artifacts
    • hatch-cython - build Cython extensions
    • hatch-gettext - compiles multi-lingual messages with GNU gettext tools
    • hatch-jupyter-builder - used for packages in the Project Jupyter ecosystem
    • hatch-mypyc - compiles code with Mypyc
    • hatch-odoo - package Odoo add-ons into the appropriate namespace
    • scikit-build-core - build extension modules with CMake
    "},{"location":"plugins/build-hook/reference/#overview","title":"Overview","text":"

    Build hooks run for every selected version of build targets.

    The initialization stage occurs immediately before each build and the finalization stage occurs immediately after. Each stage has the opportunity to view or modify build data.

    "},{"location":"plugins/build-hook/reference/#build-data","title":"Build data","text":"

    Build data is a simple mapping whose contents can influence the behavior of builds. Which fields exist and are recognized depends on each build target.

    The following fields are always present and recognized by the build system itself:

    Field Type Description artifacts list[str] This is a list of extra artifact patterns and should generally only be appended to force_include dict[str, str] This is a mapping of extra forced inclusion paths, with this mapping taking precedence in case of conflicts build_hooks tuple[str, ...] This is an immutable sequence of the names of the configured build hooks and matches the order in which they run

    Attention

    While user-facing TOML options are hyphenated, build data fields should be named with underscores to allow plugins to use them as valid Python identifiers.

    "},{"location":"plugins/build-hook/reference/#notes","title":"Notes","text":"

    In some cases it may be necessary to use force_include rather than artifacts. For example, say that you want to install a lib.so directly at the root of site-packages and a project defines a package src/foo. If you create src/lib.so, there will never be a match because the directory traversal starts at src/foo rather than src. In that case you must do either:

    build_data['force_include']['src/lib.so'] = 'src/lib.so'\n

    or

    build_data['force_include']['/absolute/path/to/src/lib.so'] = 'src/lib.so'\n
    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface","title":"BuildHookInterface","text":"

    Example usage:

    plugin.py hooks.py
    from hatchling.builders.hooks.plugin.interface import BuildHookInterface\n\n\nclass SpecialBuildHook(BuildHookInterface):\n    PLUGIN_NAME = 'special'\n    ...\n
    from hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialBuildHook\n\n\n@hookimpl\ndef hatch_register_build_hook():\n    return SpecialBuildHook\n
    Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
    class BuildHookInterface(Generic[BuilderConfigBound]):  # no cov\n    \"\"\"\n    Example usage:\n\n    ```python tab=\"plugin.py\"\n    from hatchling.builders.hooks.plugin.interface import BuildHookInterface\n\n\n    class SpecialBuildHook(BuildHookInterface):\n        PLUGIN_NAME = 'special'\n        ...\n    ```\n\n    ```python tab=\"hooks.py\"\n    from hatchling.plugin import hookimpl\n\n    from .plugin import SpecialBuildHook\n\n\n    @hookimpl\n    def hatch_register_build_hook():\n        return SpecialBuildHook\n    ```\n    \"\"\"\n\n    PLUGIN_NAME = ''\n    \"\"\"The name used for selection.\"\"\"\n\n    def __init__(\n        self,\n        root: str,\n        config: dict[str, Any],\n        build_config: BuilderConfigBound,\n        metadata: ProjectMetadata,\n        directory: str,\n        target_name: str,\n        app: Application | None = None,\n    ) -> None:\n        self.__root = root\n        self.__config = config\n        self.__build_config = build_config\n        self.__metadata = metadata\n        self.__directory = directory\n        self.__target_name = target_name\n        self.__app = app\n\n    @property\n    def app(self) -> Application:\n        \"\"\"\n        An instance of [Application](../utilities.md#hatchling.bridge.app.Application).\n        \"\"\"\n        if self.__app is None:\n            from hatchling.bridge.app import Application\n\n            self.__app = cast(Application, Application().get_safe_application())\n\n        return self.__app\n\n    @property\n    def root(self) -> str:\n        \"\"\"\n        The root of the project tree.\n        \"\"\"\n        return self.__root\n\n    @property\n    def config(self) -> dict[str, Any]:\n        \"\"\"\n        The cumulative hook configuration.\n\n        ```toml config-example\n        [tool.hatch.build.hooks.<PLUGIN_NAME>]\n        [tool.hatch.build.targets.<TARGET_NAME>.hooks.<PLUGIN_NAME>]\n        ```\n        \"\"\"\n        return self.__config\n\n    @property\n    def metadata(self) -> ProjectMetadata:\n        # Undocumented for now\n        return self.__metadata\n\n    @property\n    def build_config(self) -> BuilderConfigBound:\n        \"\"\"\n        An instance of [BuilderConfig](../utilities.md#hatchling.builders.config.BuilderConfig).\n        \"\"\"\n        return self.__build_config\n\n    @property\n    def directory(self) -> str:\n        \"\"\"\n        The build directory.\n        \"\"\"\n        return self.__directory\n\n    @property\n    def target_name(self) -> str:\n        \"\"\"\n        The plugin name of the build target.\n        \"\"\"\n        return self.__target_name\n\n    def dependencies(self) -> list[str]:  # noqa: PLR6301\n        \"\"\"\n        A list of extra [dependencies](../../config/dependency.md) that must be installed\n        prior to builds.\n\n        !!! warning\n            - For this to have any effect the hook dependency itself cannot be dynamic and\n                must always be defined in `build-system.requires`.\n            - As the hook must be imported to call this method, imports that require these\n                dependencies must be evaluated lazily.\n        \"\"\"\n        return []\n\n    def clean(self, versions: list[str]) -> None:\n        \"\"\"\n        This occurs before the build process if the `-c`/`--clean` flag was passed to\n        the [`build`](../../cli/reference.md#hatch-build) command, or when invoking\n        the [`clean`](../../cli/reference.md#hatch-clean) command.\n        \"\"\"\n\n    def initialize(self, version: str, build_data: dict[str, Any]) -> None:\n        \"\"\"\n        This occurs immediately before each build.\n\n        Any modifications to the build data will be seen by the build target.\n        \"\"\"\n\n    def finalize(self, version: str, build_data: dict[str, Any], artifact_path: str) -> None:\n        \"\"\"\n        This occurs immediately after each build and will not run if the `--hooks-only` flag\n        was passed to the [`build`](../../cli/reference.md#hatch-build) command.\n\n        The build data will reflect any modifications done by the target during the build.\n        \"\"\"\n
    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.PLUGIN_NAME","title":"PLUGIN_NAME = '' class-attribute instance-attribute","text":"

    The name used for selection.

    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.app","title":"app: Application property","text":"

    An instance of Application.

    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.root","title":"root: str property","text":"

    The root of the project tree.

    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.config","title":"config: dict[str, Any] property","text":"

    The cumulative hook configuration.

    pyproject.toml hatch.toml
    [tool.hatch.build.hooks.<PLUGIN_NAME>]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.<PLUGIN_NAME>]\n
    [build.hooks.<PLUGIN_NAME>]\n[build.targets.<TARGET_NAME>.hooks.<PLUGIN_NAME>]\n
    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.build_config","title":"build_config: BuilderConfigBound property","text":"

    An instance of BuilderConfig.

    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.target_name","title":"target_name: str property","text":"

    The plugin name of the build target.

    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.directory","title":"directory: str property","text":"

    The build directory.

    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.dependencies","title":"dependencies() -> list[str]","text":"

    A list of extra dependencies that must be installed prior to builds.

    Warning

    • For this to have any effect the hook dependency itself cannot be dynamic and must always be defined in build-system.requires.
    • As the hook must be imported to call this method, imports that require these dependencies must be evaluated lazily.
    Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
    def dependencies(self) -> list[str]:  # noqa: PLR6301\n    \"\"\"\n    A list of extra [dependencies](../../config/dependency.md) that must be installed\n    prior to builds.\n\n    !!! warning\n        - For this to have any effect the hook dependency itself cannot be dynamic and\n            must always be defined in `build-system.requires`.\n        - As the hook must be imported to call this method, imports that require these\n            dependencies must be evaluated lazily.\n    \"\"\"\n    return []\n
    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.clean","title":"clean(versions: list[str]) -> None","text":"

    This occurs before the build process if the -c/--clean flag was passed to the build command, or when invoking the clean command.

    Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
    def clean(self, versions: list[str]) -> None:\n    \"\"\"\n    This occurs before the build process if the `-c`/`--clean` flag was passed to\n    the [`build`](../../cli/reference.md#hatch-build) command, or when invoking\n    the [`clean`](../../cli/reference.md#hatch-clean) command.\n    \"\"\"\n
    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.initialize","title":"initialize(version: str, build_data: dict[str, Any]) -> None","text":"

    This occurs immediately before each build.

    Any modifications to the build data will be seen by the build target.

    Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
    def initialize(self, version: str, build_data: dict[str, Any]) -> None:\n    \"\"\"\n    This occurs immediately before each build.\n\n    Any modifications to the build data will be seen by the build target.\n    \"\"\"\n
    "},{"location":"plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.finalize","title":"finalize(version: str, build_data: dict[str, Any], artifact_path: str) -> None","text":"

    This occurs immediately after each build and will not run if the --hooks-only flag was passed to the build command.

    The build data will reflect any modifications done by the target during the build.

    Source code in backend/src/hatchling/builders/hooks/plugin/interface.py
    def finalize(self, version: str, build_data: dict[str, Any], artifact_path: str) -> None:\n    \"\"\"\n    This occurs immediately after each build and will not run if the `--hooks-only` flag\n    was passed to the [`build`](../../cli/reference.md#hatch-build) command.\n\n    The build data will reflect any modifications done by the target during the build.\n    \"\"\"\n
    "},{"location":"plugins/build-hook/version/","title":"Version build hook","text":"

    This writes the project's version to a file.

    "},{"location":"plugins/build-hook/version/#configuration","title":"Configuration","text":"

    The build hook plugin name is version.

    pyproject.toml hatch.toml
    [tool.hatch.build.hooks.version]\n[tool.hatch.build.targets.<TARGET_NAME>.hooks.version]\n
    [build.hooks.version]\n[build.targets.<TARGET_NAME>.hooks.version]\n
    "},{"location":"plugins/build-hook/version/#options","title":"Options","text":"Option Description path (required) A relative path to the desired file template A string representing the entire contents of path that will be formatted with a version variable pattern Rather than updating the entire file, a regular expression may be used that has a named group called version that represents the version. If set to true, a pattern will be used that looks for a variable named __version__ or VERSION that is set to a string containing the version, optionally prefixed with the lowercase letter v."},{"location":"plugins/builder/binary/","title":"Binary builder","text":"

    This uses PyApp to build an application that is able to bootstrap itself at runtime.

    Note

    This requires an installation of Rust.

    "},{"location":"plugins/builder/binary/#configuration","title":"Configuration","text":"

    The builder plugin name is binary.

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.binary]\n
    [build.targets.binary]\n
    "},{"location":"plugins/builder/binary/#options","title":"Options","text":"Option Default Description scripts all defined An array of defined script names to limit what gets built python-version latest compatible Python minor version The Python version ID to use pyapp-version The version of PyApp to use"},{"location":"plugins/builder/binary/#build-behavior","title":"Build behavior","text":"

    If any scripts are defined then each one will be built (limited by the scripts option). Otherwise, a single executable will be built based on the project name assuming there is an equivalently named module with a __main__.py file.

    Every executable will be built inside an app directory in the output directory.

    If the CARGO environment variable is set then that path will be used as the executable for performing builds.

    If the CARGO_BUILD_TARGET environment variable is set then its value will be appended to the file name stems.

    If the PYAPP_REPO environment variable is set then a local build will be performed inside that directory rather than installing from crates.io. Note that this is required if the CARGO environment variable refers to cross.

    "},{"location":"plugins/builder/custom/","title":"Custom builder","text":"

    This is a custom class in a given Python file that inherits from the BuilderInterface.

    "},{"location":"plugins/builder/custom/#configuration","title":"Configuration","text":"

    The builder plugin name is custom.

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.custom]\n
    [build.targets.custom]\n
    "},{"location":"plugins/builder/custom/#options","title":"Options","text":"Option Default Description path hatch_build.py The path of the Python file"},{"location":"plugins/builder/custom/#example","title":"Example","text":"hatch_build.py
    from hatchling.builders.plugin.interface import BuilderInterface\n\n\nclass CustomBuilder(BuilderInterface):\n    ...\n

    If multiple subclasses are found, you must define a function named get_builder that returns the desired builder.

    Note

    Any defined PLUGIN_NAME is ignored and will always be custom.

    "},{"location":"plugins/builder/reference/","title":"Builder plugins","text":"

    See the documentation for build configuration.

    "},{"location":"plugins/builder/reference/#known-third-party","title":"Known third-party","text":"
    • hatch-aws - used for building AWS Lambda functions with SAM
    • hatch-zipped-directory - used for building ZIP archives for installation into various foreign package installation systems
    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface","title":"BuilderInterface","text":"

    Example usage:

    plugin.py hooks.py
    from hatchling.builders.plugin.interface import BuilderInterface\n\n\nclass SpecialBuilder(BuilderInterface):\n    PLUGIN_NAME = 'special'\n    ...\n
    from hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialBuilder\n\n\n@hookimpl\ndef hatch_register_builder():\n    return SpecialBuilder\n
    Source code in backend/src/hatchling/builders/plugin/interface.py
    class BuilderInterface(ABC, Generic[BuilderConfigBound, PluginManagerBound]):\n    \"\"\"\n    Example usage:\n\n    ```python tab=\"plugin.py\"\n    from hatchling.builders.plugin.interface import BuilderInterface\n\n\n    class SpecialBuilder(BuilderInterface):\n        PLUGIN_NAME = 'special'\n        ...\n    ```\n\n    ```python tab=\"hooks.py\"\n    from hatchling.plugin import hookimpl\n\n    from .plugin import SpecialBuilder\n\n\n    @hookimpl\n    def hatch_register_builder():\n        return SpecialBuilder\n    ```\n    \"\"\"\n\n    PLUGIN_NAME = ''\n    \"\"\"The name used for selection.\"\"\"\n\n    def __init__(\n        self,\n        root: str,\n        plugin_manager: PluginManagerBound | None = None,\n        config: dict[str, Any] | None = None,\n        metadata: ProjectMetadata | None = None,\n        app: Application | None = None,\n    ) -> None:\n        self.__root = root\n        self.__plugin_manager = cast(PluginManagerBound, plugin_manager)\n        self.__raw_config = config\n        self.__metadata = metadata\n        self.__app = app\n        self.__config = cast(BuilderConfigBound, None)\n        self.__project_config: dict[str, Any] | None = None\n        self.__hatch_config: dict[str, Any] | None = None\n        self.__build_config: dict[str, Any] | None = None\n        self.__build_targets: list[str] | None = None\n        self.__target_config: dict[str, Any] | None = None\n\n        # Metadata\n        self.__project_id: str | None = None\n\n    def build(\n        self,\n        *,\n        directory: str | None = None,\n        versions: list[str] | None = None,\n        hooks_only: bool | None = None,\n        clean: bool | None = None,\n        clean_hooks_after: bool | None = None,\n        clean_only: bool | None = False,\n    ) -> Generator[str, None, None]:\n        # Fail early for invalid project metadata\n        self.metadata.validate_fields()\n\n        if directory is None:\n            directory = (\n                self.config.normalize_build_directory(os.environ[BuildEnvVars.LOCATION])\n                if BuildEnvVars.LOCATION in os.environ\n                else self.config.directory\n            )\n\n        if not os.path.isdir(directory):\n            os.makedirs(directory)\n\n        version_api = self.get_version_api()\n\n        versions = versions or self.config.versions\n        if versions:\n            unknown_versions = set(versions) - set(version_api)\n            if unknown_versions:\n                message = (\n                    f'Unknown versions for target `{self.PLUGIN_NAME}`: {\", \".join(map(str, sorted(unknown_versions)))}'\n                )\n                raise ValueError(message)\n\n        if hooks_only is None:\n            hooks_only = env_var_enabled(BuildEnvVars.HOOKS_ONLY)\n\n        configured_build_hooks = self.get_build_hooks(directory)\n        build_hooks = list(configured_build_hooks.values())\n\n        if clean_only:\n            clean = True\n        elif clean is None:\n            clean = env_var_enabled(BuildEnvVars.CLEAN)\n        if clean:\n            if not hooks_only:\n                self.clean(directory, versions)\n\n            for build_hook in build_hooks:\n                build_hook.clean(versions)\n\n            if clean_only:\n                return\n\n        if clean_hooks_after is None:\n            clean_hooks_after = env_var_enabled(BuildEnvVars.CLEAN_HOOKS_AFTER)\n\n        for version in versions:\n            self.app.display_debug(f'Building `{self.PLUGIN_NAME}` version `{version}`')\n\n            build_data = self.get_default_build_data()\n            self.set_build_data_defaults(build_data)\n\n            # Allow inspection of configured build hooks and the order in which they run\n            build_data['build_hooks'] = tuple(configured_build_hooks)\n\n            # Execute all `initialize` build hooks\n            for build_hook in build_hooks:\n                build_hook.initialize(version, build_data)\n\n            if hooks_only:\n                self.app.display_debug(f'Only ran build hooks for `{self.PLUGIN_NAME}` version `{version}`')\n                continue\n\n            # Build the artifact\n            with self.config.set_build_data(build_data):\n                artifact = version_api[version](directory, **build_data)\n\n            # Execute all `finalize` build hooks\n            for build_hook in build_hooks:\n                build_hook.finalize(version, build_data, artifact)\n\n            if clean_hooks_after:\n                for build_hook in build_hooks:\n                    build_hook.clean([version])\n\n            yield artifact\n\n    def recurse_included_files(self) -> Iterable[IncludedFile]:\n        \"\"\"\n        Returns a consistently generated series of file objects for every file that should be distributed. Each file\n        object has three `str` attributes:\n\n        - `path` - the absolute path\n        - `relative_path` - the path relative to the project root; will be an empty string for external files\n        - `distribution_path` - the path to be distributed as\n        \"\"\"\n        yield from self.recurse_selected_project_files()\n        yield from self.recurse_forced_files(self.config.get_force_include())\n\n    def recurse_selected_project_files(self) -> Iterable[IncludedFile]:\n        if self.config.only_include:\n            yield from self.recurse_explicit_files(self.config.only_include)\n        else:\n            yield from self.recurse_project_files()\n\n    def recurse_project_files(self) -> Iterable[IncludedFile]:\n        for root, dirs, files in safe_walk(self.root):\n            relative_path = get_relative_path(root, self.root)\n\n            dirs[:] = sorted(d for d in dirs if not self.config.directory_is_excluded(d, relative_path))\n\n            files.sort()\n            is_package = '__init__.py' in files\n            for f in files:\n                if f in EXCLUDED_FILES:\n                    continue\n\n                relative_file_path = os.path.join(relative_path, f)\n                distribution_path = self.config.get_distribution_path(relative_file_path)\n                if self.config.path_is_reserved(distribution_path):\n                    continue\n\n                if self.config.include_path(relative_file_path, is_package=is_package):\n                    yield IncludedFile(\n                        os.path.join(root, f), relative_file_path, self.config.get_distribution_path(relative_file_path)\n                    )\n\n    def recurse_forced_files(self, inclusion_map: dict[str, str]) -> Iterable[IncludedFile]:\n        for source, target_path in inclusion_map.items():\n            external = not source.startswith(self.root)\n            if os.path.isfile(source):\n                yield IncludedFile(\n                    source,\n                    '' if external else os.path.relpath(source, self.root),\n                    self.config.get_distribution_path(target_path),\n                )\n            elif os.path.isdir(source):\n                for root, dirs, files in safe_walk(source):\n                    relative_directory = get_relative_path(root, source)\n\n                    dirs[:] = sorted(d for d in dirs if d not in EXCLUDED_DIRECTORIES)\n\n                    files.sort()\n                    for f in files:\n                        if f in EXCLUDED_FILES:\n                            continue\n\n                        relative_file_path = os.path.join(target_path, relative_directory, f)\n                        distribution_path = self.config.get_distribution_path(relative_file_path)\n                        if not self.config.path_is_reserved(distribution_path):\n                            yield IncludedFile(\n                                os.path.join(root, f),\n                                '' if external else relative_file_path,\n                                distribution_path,\n                            )\n            else:\n                msg = f'Forced include not found: {source}'\n                raise FileNotFoundError(msg)\n\n    def recurse_explicit_files(self, inclusion_map: dict[str, str]) -> Iterable[IncludedFile]:\n        for source, target_path in inclusion_map.items():\n            external = not source.startswith(self.root)\n            if os.path.isfile(source):\n                distribution_path = self.config.get_distribution_path(target_path)\n                if not self.config.path_is_reserved(distribution_path):\n                    yield IncludedFile(\n                        source,\n                        '' if external else os.path.relpath(source, self.root),\n                        self.config.get_distribution_path(target_path),\n                    )\n            elif os.path.isdir(source):\n                for root, dirs, files in safe_walk(source):\n                    relative_directory = get_relative_path(root, source)\n\n                    dirs[:] = sorted(d for d in dirs if d not in EXCLUDED_DIRECTORIES)\n\n                    files.sort()\n                    is_package = '__init__.py' in files\n                    for f in files:\n                        if f in EXCLUDED_FILES:\n                            continue\n\n                        relative_file_path = os.path.join(target_path, relative_directory, f)\n                        distribution_path = self.config.get_distribution_path(relative_file_path)\n                        if self.config.path_is_reserved(distribution_path):\n                            continue\n\n                        if self.config.include_path(relative_file_path, explicit=True, is_package=is_package):\n                            yield IncludedFile(\n                                os.path.join(root, f), '' if external else relative_file_path, distribution_path\n                            )\n\n    @property\n    def root(self) -> str:\n        \"\"\"\n        The root of the project tree.\n        \"\"\"\n        return self.__root\n\n    @property\n    def plugin_manager(self) -> PluginManagerBound:\n        if self.__plugin_manager is None:\n            from hatchling.plugin.manager import PluginManager\n\n            self.__plugin_manager = PluginManager()\n\n        return self.__plugin_manager\n\n    @property\n    def metadata(self) -> ProjectMetadata:\n        if self.__metadata is None:\n            from hatchling.metadata.core import ProjectMetadata\n\n            self.__metadata = ProjectMetadata(self.root, self.plugin_manager, self.__raw_config)\n\n        return self.__metadata\n\n    @property\n    def app(self) -> Application:\n        \"\"\"\n        An instance of [Application](../utilities.md#hatchling.bridge.app.Application).\n        \"\"\"\n        if self.__app is None:\n            from hatchling.bridge.app import Application\n\n            self.__app = cast(Application, Application().get_safe_application())\n\n        return self.__app\n\n    @property\n    def raw_config(self) -> dict[str, Any]:\n        if self.__raw_config is None:\n            self.__raw_config = self.metadata.config\n\n        return self.__raw_config\n\n    @property\n    def project_config(self) -> dict[str, Any]:\n        if self.__project_config is None:\n            self.__project_config = self.metadata.core.config\n\n        return self.__project_config\n\n    @property\n    def hatch_config(self) -> dict[str, Any]:\n        if self.__hatch_config is None:\n            self.__hatch_config = self.metadata.hatch.config\n\n        return self.__hatch_config\n\n    @property\n    def config(self) -> BuilderConfigBound:\n        \"\"\"\n        An instance of [BuilderConfig](../utilities.md#hatchling.builders.config.BuilderConfig).\n        \"\"\"\n        if self.__config is None:\n            self.__config = self.get_config_class()(\n                self, self.root, self.PLUGIN_NAME, self.build_config, self.target_config\n            )\n\n        return self.__config\n\n    @property\n    def build_config(self) -> dict[str, Any]:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.build]\n        ```\n        \"\"\"\n        if self.__build_config is None:\n            self.__build_config = self.metadata.hatch.build_config\n\n        return self.__build_config\n\n    @property\n    def target_config(self) -> dict[str, Any]:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.build.targets.<PLUGIN_NAME>]\n        ```\n        \"\"\"\n        if self.__target_config is None:\n            target_config: dict[str, Any] = self.metadata.hatch.build_targets.get(self.PLUGIN_NAME, {})\n            if not isinstance(target_config, dict):\n                message = f'Field `tool.hatch.build.targets.{self.PLUGIN_NAME}` must be a table'\n                raise TypeError(message)\n\n            self.__target_config = target_config\n\n        return self.__target_config\n\n    @property\n    def project_id(self) -> str:\n        if self.__project_id is None:\n            self.__project_id = f'{self.normalize_file_name_component(self.metadata.core.name)}-{self.metadata.version}'\n\n        return self.__project_id\n\n    def get_build_hooks(self, directory: str) -> dict[str, BuildHookInterface]:\n        configured_build_hooks = {}\n        for hook_name, config in self.config.hook_config.items():\n            build_hook = self.plugin_manager.build_hook.get(hook_name)\n            if build_hook is None:\n                from hatchling.plugin.exceptions import UnknownPluginError\n\n                message = f'Unknown build hook: {hook_name}'\n                raise UnknownPluginError(message)\n\n            configured_build_hooks[hook_name] = build_hook(\n                self.root, config, self.config, self.metadata, directory, self.PLUGIN_NAME, self.app\n            )\n\n        return configured_build_hooks\n\n    @abstractmethod\n    def get_version_api(self) -> dict[str, Callable]:\n        \"\"\"\n        A mapping of `str` versions to a callable that is used for building.\n        Each callable must have the following signature:\n\n        ```python\n        def ...(build_dir: str, build_data: dict) -> str:\n        ```\n\n        The return value must be the absolute path to the built artifact.\n        \"\"\"\n\n    def get_default_versions(self) -> list[str]:\n        \"\"\"\n        A list of versions to build when users do not specify any, defaulting to all versions.\n        \"\"\"\n        return list(self.get_version_api())\n\n    def get_default_build_data(self) -> dict[str, Any]:  # noqa: PLR6301\n        \"\"\"\n        A mapping that can be modified by [build hooks](../build-hook/reference.md) to influence the behavior of builds.\n        \"\"\"\n        return {}\n\n    def set_build_data_defaults(self, build_data: dict[str, Any]) -> None:  # noqa: PLR6301\n        build_data.setdefault('artifacts', [])\n        build_data.setdefault('force_include', {})\n\n    def clean(self, directory: str, versions: list[str]) -> None:\n        \"\"\"\n        Called before builds if the `-c`/`--clean` flag was passed to the\n        [`build`](../../cli/reference.md#hatch-build) command.\n        \"\"\"\n\n    @classmethod\n    def get_config_class(cls) -> type[BuilderConfig]:\n        \"\"\"\n        Must return a subclass of [BuilderConfig](../utilities.md#hatchling.builders.config.BuilderConfig).\n        \"\"\"\n        return BuilderConfig\n\n    @staticmethod\n    def normalize_file_name_component(file_name: str) -> str:\n        \"\"\"\n        https://peps.python.org/pep-0427/#escaping-and-unicode\n        \"\"\"\n        return re.sub(r'[^\\w\\d.]+', '_', file_name, flags=re.UNICODE)\n
    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.PLUGIN_NAME","title":"PLUGIN_NAME = '' class-attribute instance-attribute","text":"

    The name used for selection.

    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.app","title":"app: Application property","text":"

    An instance of Application.

    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.root","title":"root: str property","text":"

    The root of the project tree.

    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.build_config","title":"build_config: dict[str, Any] property","text":"pyproject.toml hatch.toml
    [tool.hatch.build]\n
    [build]\n
    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.target_config","title":"target_config: dict[str, Any] property","text":"pyproject.toml hatch.toml
    [tool.hatch.build.targets.<PLUGIN_NAME>]\n
    [build.targets.<PLUGIN_NAME>]\n
    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.config","title":"config: BuilderConfigBound property","text":"

    An instance of BuilderConfig.

    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.get_config_class","title":"get_config_class() -> type[BuilderConfig] classmethod","text":"

    Must return a subclass of BuilderConfig.

    Source code in backend/src/hatchling/builders/plugin/interface.py
    @classmethod\ndef get_config_class(cls) -> type[BuilderConfig]:\n    \"\"\"\n    Must return a subclass of [BuilderConfig](../utilities.md#hatchling.builders.config.BuilderConfig).\n    \"\"\"\n    return BuilderConfig\n
    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.get_version_api","title":"get_version_api() -> dict[str, Callable] abstractmethod","text":"

    A mapping of str versions to a callable that is used for building. Each callable must have the following signature:

    def ...(build_dir: str, build_data: dict) -> str:\n

    The return value must be the absolute path to the built artifact.

    Source code in backend/src/hatchling/builders/plugin/interface.py
    @abstractmethod\ndef get_version_api(self) -> dict[str, Callable]:\n    \"\"\"\n    A mapping of `str` versions to a callable that is used for building.\n    Each callable must have the following signature:\n\n    ```python\n    def ...(build_dir: str, build_data: dict) -> str:\n    ```\n\n    The return value must be the absolute path to the built artifact.\n    \"\"\"\n
    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.get_default_versions","title":"get_default_versions() -> list[str]","text":"

    A list of versions to build when users do not specify any, defaulting to all versions.

    Source code in backend/src/hatchling/builders/plugin/interface.py
    def get_default_versions(self) -> list[str]:\n    \"\"\"\n    A list of versions to build when users do not specify any, defaulting to all versions.\n    \"\"\"\n    return list(self.get_version_api())\n
    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.clean","title":"clean(directory: str, versions: list[str]) -> None","text":"

    Called before builds if the -c/--clean flag was passed to the build command.

    Source code in backend/src/hatchling/builders/plugin/interface.py
    def clean(self, directory: str, versions: list[str]) -> None:\n    \"\"\"\n    Called before builds if the `-c`/`--clean` flag was passed to the\n    [`build`](../../cli/reference.md#hatch-build) command.\n    \"\"\"\n
    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.recurse_included_files","title":"recurse_included_files() -> Iterable[IncludedFile]","text":"

    Returns a consistently generated series of file objects for every file that should be distributed. Each file object has three str attributes:

    • path - the absolute path
    • relative_path - the path relative to the project root; will be an empty string for external files
    • distribution_path - the path to be distributed as
    Source code in backend/src/hatchling/builders/plugin/interface.py
    def recurse_included_files(self) -> Iterable[IncludedFile]:\n    \"\"\"\n    Returns a consistently generated series of file objects for every file that should be distributed. Each file\n    object has three `str` attributes:\n\n    - `path` - the absolute path\n    - `relative_path` - the path relative to the project root; will be an empty string for external files\n    - `distribution_path` - the path to be distributed as\n    \"\"\"\n    yield from self.recurse_selected_project_files()\n    yield from self.recurse_forced_files(self.config.get_force_include())\n
    "},{"location":"plugins/builder/reference/#hatchling.builders.plugin.interface.BuilderInterface.get_default_build_data","title":"get_default_build_data() -> dict[str, Any]","text":"

    A mapping that can be modified by build hooks to influence the behavior of builds.

    Source code in backend/src/hatchling/builders/plugin/interface.py
    def get_default_build_data(self) -> dict[str, Any]:  # noqa: PLR6301\n    \"\"\"\n    A mapping that can be modified by [build hooks](../build-hook/reference.md) to influence the behavior of builds.\n    \"\"\"\n    return {}\n
    "},{"location":"plugins/builder/sdist/","title":"Source distribution builder","text":"

    A source distribution, or sdist, is an archive of Python \"source code\". Although largely unspecified, by convention it should include everything that is required to build a wheel without making network requests.

    "},{"location":"plugins/builder/sdist/#configuration","title":"Configuration","text":"

    The builder plugin name is sdist.

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.sdist]\n
    [build.targets.sdist]\n
    "},{"location":"plugins/builder/sdist/#options","title":"Options","text":"Option Default Description core-metadata-version \"2.3\" The version of core metadata to use strict-naming true Whether or not file names should contain the normalized version of the project name support-legacy false Whether or not to include a setup.py file to support legacy installation mechanisms"},{"location":"plugins/builder/sdist/#versions","title":"Versions","text":"Version Description standard (default) The latest conventional format"},{"location":"plugins/builder/sdist/#default-file-selection","title":"Default file selection","text":"

    When the user has not set any file selection options, all files that are not ignored by your VCS will be included.

    Note

    The following files are always included and cannot be excluded:

    • /pyproject.toml
    • /hatch.toml
    • /hatch_build.py
    • /.gitignore or /.hgignore
    • Any defined readme file
    • All defined license-files
    "},{"location":"plugins/builder/sdist/#reproducibility","title":"Reproducibility","text":"

    Reproducible builds are supported.

    "},{"location":"plugins/builder/sdist/#build-data","title":"Build data","text":"

    This is data that can be modified by build hooks.

    Data Default Description dependencies Extra project dependencies"},{"location":"plugins/builder/wheel/","title":"Wheel builder","text":"

    A wheel is a binary distribution of a Python package that can be installed directly into an environment.

    "},{"location":"plugins/builder/wheel/#configuration","title":"Configuration","text":"

    The builder plugin name is wheel.

    pyproject.toml hatch.toml
    [tool.hatch.build.targets.wheel]\n
    [build.targets.wheel]\n
    "},{"location":"plugins/builder/wheel/#options","title":"Options","text":"Option Default Description core-metadata-version \"2.3\" The version of core metadata to use shared-data A mapping similar to the forced inclusion option corresponding to the data subdirectory within the standard data directory that will be installed globally in a given Python environment, usually under sys.prefix shared-scripts A mapping similar to the forced inclusion option corresponding to the scripts subdirectory within the standard data directory that will be installed in a given Python environment, usually under Scripts on Windows or bin otherwise, and would normally be available on PATH extra-metadata A mapping similar to the forced inclusion option corresponding to extra metadata that will be shipped in a directory named extra_metadata strict-naming true Whether or not file names should contain the normalized version of the project name macos-max-compat false Whether or not on macOS, when build hooks have set the infer_tag build data, the wheel name should signal broad support rather than specific versions for newer SDK versions.Note: This option will eventually be removed. bypass-selection false Whether or not to suppress the error when one has not defined any file selection options and all heuristics have failed to determine what to ship"},{"location":"plugins/builder/wheel/#versions","title":"Versions","text":"Version Description standard (default) The latest standardized format editable A wheel that only ships .pth files or import hooks for real-time development"},{"location":"plugins/builder/wheel/#default-file-selection","title":"Default file selection","text":"

    When the user has not set any file selection options, the project name will be used to determine the package to ship in the following heuristic order:

    1. <NAME>/__init__.py
    2. src/<NAME>/__init__.py
    3. <NAME>.py
    4. <NAMESPACE>/<NAME>/__init__.py

    If none of these heuristics are satisfied, an error will be raised.

    "},{"location":"plugins/builder/wheel/#reproducibility","title":"Reproducibility","text":"

    Reproducible builds are supported.

    "},{"location":"plugins/builder/wheel/#build-data","title":"Build data","text":"

    This is data that can be modified by build hooks.

    Data Default Description tag The full tag part of the filename (e.g. py3-none-any), defaulting to a cross-platform wheel with the supported major versions of Python based on project metadata infer_tag False When tag is not set, this may be enabled to use the one most specific to the platform, Python interpreter, and ABI pure_python True Whether or not to write metadata indicating that the package does not contain any platform-specific files dependencies Extra project dependencies shared_data Additional shared-data entries, which take precedence in case of conflicts shared_scripts Additional shared-scripts entries, which take precedence in case of conflicts extra_metadata Additional extra-metadata entries, which take precedence in case of conflicts force_include_editable Similar to the force_include option but specifically for the editable version and takes precedence"},{"location":"plugins/environment/reference/","title":"Environment plugins","text":"

    See the documentation for environment configuration.

    "},{"location":"plugins/environment/reference/#known-third-party","title":"Known third-party","text":"
    • hatch-conda - environments backed by Conda/Mamba
    • hatch-containers - environments run inside containers
    • hatch-pip-compile - use pip-compile to manage project dependencies and lockfiles
    • hatch-pip-deepfreeze - virtual environments with dependency locking by pip-deepfreeze
    "},{"location":"plugins/environment/reference/#installation","title":"Installation","text":"

    Any required environment types that are not built-in must be manually installed alongside Hatch or listed in the tool.hatch.env.requires array for automatic management:

    pyproject.toml hatch.toml
    [tool.hatch.env]\nrequires = [\n  \"...\",\n]\n
    [env]\nrequires = [\n  \"...\",\n]\n
    "},{"location":"plugins/environment/reference/#life-cycle","title":"Life cycle","text":"

    Whenever an environment is used, the following logic is performed:

    Source code in src/hatch/cli/application.py
    def prepare_environment(self, environment: EnvironmentInterface):\n    if not environment.exists():\n        self.env_metadata.reset(environment)\n\n        with environment.app_status_creation():\n            environment.create()\n\n        if not environment.skip_install:\n            if environment.pre_install_commands:\n                with environment.app_status_pre_installation():\n                    self.run_shell_commands(\n                        ExecutionContext(\n                            environment,\n                            shell_commands=environment.pre_install_commands,\n                            source='pre-install',\n                            show_code_on_error=True,\n                        )\n                    )\n\n            with environment.app_status_project_installation():\n                if environment.dev_mode:\n                    environment.install_project_dev_mode()\n                else:\n                    environment.install_project()\n\n            if environment.post_install_commands:\n                with environment.app_status_post_installation():\n                    self.run_shell_commands(\n                        ExecutionContext(\n                            environment,\n                            shell_commands=environment.post_install_commands,\n                            source='post-install',\n                            show_code_on_error=True,\n                        )\n                    )\n\n    with environment.app_status_dependency_state_check():\n        new_dep_hash = environment.dependency_hash()\n\n    current_dep_hash = self.env_metadata.dependency_hash(environment)\n    if new_dep_hash != current_dep_hash:\n        with environment.app_status_dependency_installation_check():\n            dependencies_in_sync = environment.dependencies_in_sync()\n\n        if not dependencies_in_sync:\n            with environment.app_status_dependency_synchronization():\n                environment.sync_dependencies()\n                new_dep_hash = environment.dependency_hash()\n\n        self.env_metadata.update_dependency_hash(environment, new_dep_hash)\n
    "},{"location":"plugins/environment/reference/#build-environments","title":"Build environments","text":"

    All environment types should offer support for a special sub-environment in which projects can be built. This environment is used in the following scenarios:

    • the build command
    • commands that read dependencies, like dep hash, if any project dependencies are set dynamically
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface","title":"EnvironmentInterface","text":"

    Example usage:

    plugin.py hooks.py
        from hatch.env.plugin.interface import EnvironmentInterface\n\n\n    class SpecialEnvironment(EnvironmentInterface):\n        PLUGIN_NAME = 'special'\n        ...\n
        from hatchling.plugin import hookimpl\n\n    from .plugin import SpecialEnvironment\n\n\n    @hookimpl\n    def hatch_register_environment():\n        return SpecialEnvironment\n
    Source code in src/hatch/env/plugin/interface.py
    class EnvironmentInterface(ABC):\n    \"\"\"\n    Example usage:\n\n    ```python tab=\"plugin.py\"\n        from hatch.env.plugin.interface import EnvironmentInterface\n\n\n        class SpecialEnvironment(EnvironmentInterface):\n            PLUGIN_NAME = 'special'\n            ...\n    ```\n\n    ```python tab=\"hooks.py\"\n        from hatchling.plugin import hookimpl\n\n        from .plugin import SpecialEnvironment\n\n\n        @hookimpl\n        def hatch_register_environment():\n            return SpecialEnvironment\n    ```\n    \"\"\"\n\n    PLUGIN_NAME = ''\n    \"\"\"The name used for selection.\"\"\"\n\n    def __init__(\n        self,\n        root,\n        metadata,\n        name,\n        config,\n        matrix_variables,\n        data_directory,\n        isolated_data_directory,\n        platform,\n        verbosity,\n        app=None,\n    ):\n        self.__root = root\n        self.__metadata = metadata\n        self.__name = name\n        self.__config = config\n        self.__matrix_variables = matrix_variables\n        self.__data_directory = data_directory\n        self.__isolated_data_directory = isolated_data_directory\n        self.__platform = platform\n        self.__verbosity = verbosity\n        self.__app = app\n        self.__context = None\n\n        self._system_python = None\n        self._env_vars = None\n        self._env_include = None\n        self._env_exclude = None\n        self._environment_dependencies_complex = None\n        self._environment_dependencies = None\n        self._dependencies_complex = None\n        self._dependencies = None\n        self._platforms = None\n        self._skip_install = None\n        self._dev_mode = None\n        self._features = None\n        self._description = None\n        self._scripts = None\n        self._pre_install_commands = None\n        self._post_install_commands = None\n\n    @property\n    def matrix_variables(self):\n        return self.__matrix_variables\n\n    @property\n    def app(self):\n        \"\"\"\n        An instance of [Application](../utilities.md#hatchling.bridge.app.Application).\n        \"\"\"\n        if self.__app is None:\n            from hatchling.bridge.app import Application\n\n            self.__app = Application().get_safe_application()\n\n        return self.__app\n\n    @property\n    def context(self):\n        if self.__context is None:\n            self.__context = self.get_context()\n\n        return self.__context\n\n    @property\n    def verbosity(self):\n        return self.__verbosity\n\n    @property\n    def root(self):\n        \"\"\"\n        The root of the project tree as a path-like object.\n        \"\"\"\n        return self.__root\n\n    @property\n    def metadata(self):\n        return self.__metadata\n\n    @property\n    def name(self) -> str:\n        \"\"\"\n        The name of the environment.\n        \"\"\"\n        return self.__name\n\n    @property\n    def platform(self):\n        \"\"\"\n        An instance of [Platform](../utilities.md#hatch.utils.platform.Platform).\n        \"\"\"\n        return self.__platform\n\n    @property\n    def data_directory(self):\n        \"\"\"\n        The [directory](../../config/hatch.md#environments) this plugin should use for storage as a path-like object.\n        If the user has not configured one then this will be the same as the\n        [isolated data directory](reference.md#hatch.env.plugin.interface.EnvironmentInterface.isolated_data_directory).\n        \"\"\"\n        return self.__data_directory\n\n    @property\n    def isolated_data_directory(self):\n        \"\"\"\n        The default [directory](../../config/hatch.md#environments) reserved exclusively for this plugin as a path-like\n        object.\n        \"\"\"\n        return self.__isolated_data_directory\n\n    @property\n    def config(self) -> dict:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.envs.<ENV_NAME>]\n        ```\n        \"\"\"\n        return self.__config\n\n    @property\n    def system_python(self):\n        if self._system_python is None:\n            system_python = os.environ.get(AppEnvVars.PYTHON)\n            if system_python == 'self':\n                system_python = sys.executable\n\n            system_python = (\n                system_python\n                or self.platform.modules.shutil.which('python')\n                or self.platform.modules.shutil.which('python3')\n                or sys.executable\n            )\n            if not isabs(system_python):\n                system_python = self.platform.modules.shutil.which(system_python)\n\n            self._system_python = system_python\n\n        return self._system_python\n\n    @property\n    def env_vars(self) -> dict:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.envs.<ENV_NAME>.env-vars]\n        ```\n        \"\"\"\n        if self._env_vars is None:\n            env_vars = self.config.get('env-vars', {})\n            if not isinstance(env_vars, dict):\n                message = f'Field `tool.hatch.envs.{self.name}.env-vars` must be a mapping'\n                raise TypeError(message)\n\n            for key, value in env_vars.items():\n                if not isinstance(value, str):\n                    message = (\n                        f'Environment variable `{key}` of field `tool.hatch.envs.{self.name}.env-vars` must be a string'\n                    )\n                    raise TypeError(message)\n\n            new_env_vars = {}\n            with self.metadata.context.apply_context(self.context):\n                for key, value in env_vars.items():\n                    new_env_vars[key] = self.metadata.context.format(value)\n\n            new_env_vars[AppEnvVars.ENV_ACTIVE] = self.name\n            self._env_vars = new_env_vars\n\n        return self._env_vars\n\n    @property\n    def env_include(self) -> list[str]:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.envs.<ENV_NAME>]\n        env-include = [...]\n        ```\n        \"\"\"\n        if self._env_include is None:\n            env_include = self.config.get('env-include', [])\n            if not isinstance(env_include, list):\n                message = f'Field `tool.hatch.envs.{self.name}.env-include` must be an array'\n                raise TypeError(message)\n\n            for i, pattern in enumerate(env_include, 1):\n                if not isinstance(pattern, str):\n                    message = f'Pattern #{i} of field `tool.hatch.envs.{self.name}.env-include` must be a string'\n                    raise TypeError(message)\n\n            if env_include:\n                self._env_include = ['HATCH_BUILD_*', *env_include]\n            else:\n                self._env_include = env_include\n\n        return self._env_include\n\n    @property\n    def env_exclude(self) -> list[str]:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.envs.<ENV_NAME>]\n        env-exclude = [...]\n        ```\n        \"\"\"\n        if self._env_exclude is None:\n            env_exclude = self.config.get('env-exclude', [])\n            if not isinstance(env_exclude, list):\n                message = f'Field `tool.hatch.envs.{self.name}.env-exclude` must be an array'\n                raise TypeError(message)\n\n            for i, pattern in enumerate(env_exclude, 1):\n                if not isinstance(pattern, str):\n                    message = f'Pattern #{i} of field `tool.hatch.envs.{self.name}.env-exclude` must be a string'\n                    raise TypeError(message)\n\n            self._env_exclude = env_exclude\n\n        return self._env_exclude\n\n    @property\n    def environment_dependencies_complex(self):\n        if self._environment_dependencies_complex is None:\n            from packaging.requirements import InvalidRequirement, Requirement\n\n            dependencies_complex = []\n            with self.apply_context():\n                for option in ('dependencies', 'extra-dependencies'):\n                    dependencies = self.config.get(option, [])\n                    if not isinstance(dependencies, list):\n                        message = f'Field `tool.hatch.envs.{self.name}.{option}` must be an array'\n                        raise TypeError(message)\n\n                    for i, entry in enumerate(dependencies, 1):\n                        if not isinstance(entry, str):\n                            message = (\n                                f'Dependency #{i} of field `tool.hatch.envs.{self.name}.{option}` must be a string'\n                            )\n                            raise TypeError(message)\n\n                        try:\n                            dependencies_complex.append(Requirement(self.metadata.context.format(entry)))\n                        except InvalidRequirement as e:\n                            message = f'Dependency #{i} of field `tool.hatch.envs.{self.name}.{option}` is invalid: {e}'\n                            raise ValueError(message) from None\n\n            self._environment_dependencies_complex = dependencies_complex\n\n        return self._environment_dependencies_complex\n\n    @property\n    def environment_dependencies(self) -> list[str]:\n        \"\"\"\n        The list of all [environment dependencies](../../config/environment/overview.md#dependencies).\n        \"\"\"\n        if self._environment_dependencies is None:\n            self._environment_dependencies = [str(dependency) for dependency in self.environment_dependencies_complex]\n\n        return self._environment_dependencies\n\n    @property\n    def dependencies_complex(self):\n        if self._dependencies_complex is None:\n            all_dependencies_complex = list(self.environment_dependencies_complex)\n\n            # Ensure these are checked last to speed up initial environment creation since\n            # they will already be installed along with the project\n            if (not self.skip_install and self.dev_mode) or self.features:\n                from hatch.utils.dep import get_project_dependencies_complex\n\n                dependencies_complex, optional_dependencies_complex = get_project_dependencies_complex(self)\n\n                if not self.skip_install and self.dev_mode:\n                    all_dependencies_complex.extend(dependencies_complex.values())\n\n                for feature in self.features:\n                    if feature not in optional_dependencies_complex:\n                        message = (\n                            f'Feature `{feature}` of field `tool.hatch.envs.{self.name}.features` is not '\n                            f'defined in the dynamic field `project.optional-dependencies`'\n                        )\n                        raise ValueError(message)\n\n                    all_dependencies_complex.extend(optional_dependencies_complex[feature].values())\n\n            self._dependencies_complex = all_dependencies_complex\n\n        return self._dependencies_complex\n\n    @property\n    def dependencies(self) -> list[str]:\n        \"\"\"\n        The list of all [project dependencies](../../config/metadata.md#dependencies) (if\n        [installed](../../config/environment/overview.md#skip-install) and in\n        [dev mode](../../config/environment/overview.md#dev-mode)), selected\n        [optional dependencies](../../config/environment/overview.md#features), and\n        [environment dependencies](../../config/environment/overview.md#dependencies).\n        \"\"\"\n        if self._dependencies is None:\n            self._dependencies = [str(dependency) for dependency in self.dependencies_complex]\n\n        return self._dependencies\n\n    @property\n    def platforms(self) -> list[str]:\n        \"\"\"\n        All names are stored as their lower-cased version.\n\n        ```toml config-example\n        [tool.hatch.envs.<ENV_NAME>]\n        platforms = [...]\n        ```\n        \"\"\"\n        if self._platforms is None:\n            platforms = self.config.get('platforms', [])\n            if not isinstance(platforms, list):\n                message = f'Field `tool.hatch.envs.{self.name}.platforms` must be an array'\n                raise TypeError(message)\n\n            for i, command in enumerate(platforms, 1):\n                if not isinstance(command, str):\n                    message = f'Platform #{i} of field `tool.hatch.envs.{self.name}.platforms` must be a string'\n                    raise TypeError(message)\n\n            self._platforms = [platform.lower() for platform in platforms]\n\n        return self._platforms\n\n    @property\n    def skip_install(self) -> bool:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.envs.<ENV_NAME>]\n        skip-install = ...\n        ```\n        \"\"\"\n        if self._skip_install is None:\n            skip_install = self.config.get('skip-install', not self.metadata.has_project_file())\n            if not isinstance(skip_install, bool):\n                message = f'Field `tool.hatch.envs.{self.name}.skip-install` must be a boolean'\n                raise TypeError(message)\n\n            self._skip_install = skip_install\n\n        return self._skip_install\n\n    @property\n    def dev_mode(self) -> bool:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.envs.<ENV_NAME>]\n        dev-mode = ...\n        ```\n        \"\"\"\n        if self._dev_mode is None:\n            dev_mode = self.config.get('dev-mode', True)\n            if not isinstance(dev_mode, bool):\n                message = f'Field `tool.hatch.envs.{self.name}.dev-mode` must be a boolean'\n                raise TypeError(message)\n\n            self._dev_mode = dev_mode\n\n        return self._dev_mode\n\n    @property\n    def features(self):\n        if self._features is None:\n            from hatchling.metadata.utils import normalize_project_name\n\n            features = self.config.get('features', [])\n            if not isinstance(features, list):\n                message = f'Field `tool.hatch.envs.{self.name}.features` must be an array of strings'\n                raise TypeError(message)\n\n            all_features = set()\n            for i, feature in enumerate(features, 1):\n                if not isinstance(feature, str):\n                    message = f'Feature #{i} of field `tool.hatch.envs.{self.name}.features` must be a string'\n                    raise TypeError(message)\n\n                if not feature:\n                    message = f'Feature #{i} of field `tool.hatch.envs.{self.name}.features` cannot be an empty string'\n                    raise ValueError(message)\n\n                normalized_feature = (\n                    feature\n                    if self.metadata.hatch.metadata.allow_ambiguous_features\n                    else normalize_project_name(feature)\n                )\n                if (\n                    not self.metadata.hatch.metadata.hook_config\n                    and normalized_feature not in self.metadata.core.optional_dependencies\n                ):\n                    message = (\n                        f'Feature `{normalized_feature}` of field `tool.hatch.envs.{self.name}.features` is not '\n                        f'defined in field `project.optional-dependencies`'\n                    )\n                    raise ValueError(message)\n\n                all_features.add(normalized_feature)\n\n            self._features = sorted(all_features)\n\n        return self._features\n\n    @property\n    def description(self) -> str:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.envs.<ENV_NAME>]\n        description = ...\n        ```\n        \"\"\"\n        if self._description is None:\n            description = self.config.get('description', '')\n            if not isinstance(description, str):\n                message = f'Field `tool.hatch.envs.{self.name}.description` must be a string'\n                raise TypeError(message)\n\n            self._description = description\n\n        return self._description\n\n    @property\n    def scripts(self):\n        if self._scripts is None:\n            config = {}\n\n            # Extra scripts should come first to give less precedence\n            for field in ('extra-scripts', 'scripts'):\n                script_config = self.config.get(field, {})\n                if not isinstance(script_config, dict):\n                    message = f'Field `tool.hatch.envs.{self.name}.{field}` must be a table'\n                    raise TypeError(message)\n\n                for name, data in script_config.items():\n                    if ' ' in name:\n                        message = (\n                            f'Script name `{name}` in field `tool.hatch.envs.{self.name}.{field}` '\n                            f'must not contain spaces'\n                        )\n                        raise ValueError(message)\n\n                    commands = []\n\n                    if isinstance(data, str):\n                        commands.append(data)\n                    elif isinstance(data, list):\n                        for i, command in enumerate(data, 1):\n                            if not isinstance(command, str):\n                                message = (\n                                    f'Command #{i} in field `tool.hatch.envs.{self.name}.{field}.{name}` '\n                                    f'must be a string'\n                                )\n                                raise TypeError(message)\n\n                            commands.append(command)\n                    else:\n                        message = (\n                            f'Field `tool.hatch.envs.{self.name}.{field}.{name}` must be '\n                            f'a string or an array of strings'\n                        )\n                        raise TypeError(message)\n\n                    config[name] = commands\n\n            seen = {}\n            active = []\n            for script_name, commands in config.items():\n                commands[:] = expand_script_commands(self.name, script_name, commands, config, seen, active)\n\n            self._scripts = config\n\n        return self._scripts\n\n    @property\n    def pre_install_commands(self):\n        if self._pre_install_commands is None:\n            pre_install_commands = self.config.get('pre-install-commands', [])\n            if not isinstance(pre_install_commands, list):\n                message = f'Field `tool.hatch.envs.{self.name}.pre-install-commands` must be an array'\n                raise TypeError(message)\n\n            for i, command in enumerate(pre_install_commands, 1):\n                if not isinstance(command, str):\n                    message = (\n                        f'Command #{i} of field `tool.hatch.envs.{self.name}.pre-install-commands` must be a string'\n                    )\n                    raise TypeError(message)\n\n            self._pre_install_commands = list(pre_install_commands)\n\n        return self._pre_install_commands\n\n    @property\n    def post_install_commands(self):\n        if self._post_install_commands is None:\n            post_install_commands = self.config.get('post-install-commands', [])\n            if not isinstance(post_install_commands, list):\n                message = f'Field `tool.hatch.envs.{self.name}.post-install-commands` must be an array'\n                raise TypeError(message)\n\n            for i, command in enumerate(post_install_commands, 1):\n                if not isinstance(command, str):\n                    message = (\n                        f'Command #{i} of field `tool.hatch.envs.{self.name}.post-install-commands` must be a string'\n                    )\n                    raise TypeError(message)\n\n            self._post_install_commands = list(post_install_commands)\n\n        return self._post_install_commands\n\n    def activate(self):\n        \"\"\"\n        A convenience method called when using the environment as a context manager:\n\n        ```python\n        with environment:\n            ...\n        ```\n        \"\"\"\n\n    def deactivate(self):\n        \"\"\"\n        A convenience method called after using the environment as a context manager:\n\n        ```python\n        with environment:\n            ...\n        ```\n        \"\"\"\n\n    @abstractmethod\n    def find(self):\n        \"\"\"\n        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n        This should return information about how to locate the environment or represent its ID in\n        some way. Additionally, this is expected to return something even if the environment is\n        [incompatible](reference.md#hatch.env.plugin.interface.EnvironmentInterface.check_compatibility).\n        \"\"\"\n\n    @abstractmethod\n    def create(self):\n        \"\"\"\n        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n        This should perform the necessary steps to set up the environment.\n        \"\"\"\n\n    @abstractmethod\n    def remove(self):\n        \"\"\"\n        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n        This should perform the necessary steps to completely remove the environment from the system and will only\n        be triggered manually by users with the [`env remove`](../../cli/reference.md#hatch-env-remove) or\n        [`env prune`](../../cli/reference.md#hatch-env-prune) commands.\n\n        If the\n        [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)\n        has a caching mechanism, this should remove that as well.\n        \"\"\"\n\n    @abstractmethod\n    def exists(self) -> bool:\n        \"\"\"\n        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n        This should indicate whether or not the environment has already been created.\n        \"\"\"\n\n    @abstractmethod\n    def install_project(self):\n        \"\"\"\n        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n        This should install the project in the environment.\n        \"\"\"\n\n    @abstractmethod\n    def install_project_dev_mode(self):\n        \"\"\"\n        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n        This should install the project in the environment such that the environment\n        always reflects the current state of the project.\n        \"\"\"\n\n    @abstractmethod\n    def dependencies_in_sync(self) -> bool:\n        \"\"\"\n        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n        This should indicate whether or not the environment is compatible with the current\n        [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies).\n        \"\"\"\n\n    @abstractmethod\n    def sync_dependencies(self):\n        \"\"\"\n        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n        This should install the\n        [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies)\n        in the environment.\n        \"\"\"\n\n    def dependency_hash(self):\n        \"\"\"\n        This should return a hash of the environment's\n        [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies)\n        and any other data that is handled by the\n        [sync_dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.sync_dependencies)\n        and\n        [dependencies_in_sync](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies_in_sync)\n        methods.\n        \"\"\"\n        from hatch.utils.dep import hash_dependencies\n\n        return hash_dependencies(self.dependencies_complex)\n\n    @contextmanager\n    def app_status_creation(self):\n        \"\"\"\n        See the [life cycle of environments](reference.md#life-cycle).\n        \"\"\"\n        with self.app.status(f'Creating environment: {self.name}'):\n            yield\n\n    @contextmanager\n    def app_status_pre_installation(self):\n        \"\"\"\n        See the [life cycle of environments](reference.md#life-cycle).\n        \"\"\"\n        with self.app.status('Running pre-installation commands'):\n            yield\n\n    @contextmanager\n    def app_status_post_installation(self):\n        \"\"\"\n        See the [life cycle of environments](reference.md#life-cycle).\n        \"\"\"\n        with self.app.status('Running post-installation commands'):\n            yield\n\n    @contextmanager\n    def app_status_project_installation(self):\n        \"\"\"\n        See the [life cycle of environments](reference.md#life-cycle).\n        \"\"\"\n        if self.dev_mode:\n            with self.app.status('Installing project in development mode'):\n                yield\n        else:\n            with self.app.status('Installing project'):\n                yield\n\n    @contextmanager\n    def app_status_dependency_state_check(self):\n        \"\"\"\n        See the [life cycle of environments](reference.md#life-cycle).\n        \"\"\"\n        if not self.skip_install and (\n            'dependencies' in self.metadata.dynamic or 'optional-dependencies' in self.metadata.dynamic\n        ):\n            with self.app.status('Polling dependency state'):\n                yield\n        else:\n            yield\n\n    @contextmanager\n    def app_status_dependency_installation_check(self):\n        \"\"\"\n        See the [life cycle of environments](reference.md#life-cycle).\n        \"\"\"\n        with self.app.status('Checking dependencies'):\n            yield\n\n    @contextmanager\n    def app_status_dependency_synchronization(self):\n        \"\"\"\n        See the [life cycle of environments](reference.md#life-cycle).\n        \"\"\"\n        with self.app.status('Syncing dependencies'):\n            yield\n\n    @contextmanager\n    def build_environment(\n        self,\n        dependencies: list[str],  # noqa: ARG002\n    ):\n        \"\"\"\n        This should set up an isolated environment in which to [`build`](../../cli/reference.md#hatch-build) the project\n        given a set of dependencies and must be a context manager:\n\n        ```python\n        with environment.build_environment([...]):\n            ...\n        ```\n\n        The build environment should reflect any\n        [environment variables](reference.md#hatch.env.plugin.interface.EnvironmentInterface.get_env_vars)\n        the user defined either currently or at the time of\n        [creation](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).\n        \"\"\"\n        with self.get_env_vars():\n            yield\n\n    def run_builder(\n        self,\n        build_environment,  # noqa: ARG002\n        **kwargs,\n    ):\n        \"\"\"\n        This will be called when the\n        [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)\n        is active:\n\n        ```python\n        with environment.build_environment([...]) as build_env:\n            process = environment.run_builder(build_env, ...)\n        ```\n\n        This should return the standard library's\n        [subprocess.CompletedProcess](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess).\n        The command is constructed by passing all keyword arguments to\n        [construct_build_command](reference.md#hatch.env.plugin.interface.EnvironmentInterface.construct_build_command).\n\n        For an example, open the default implementation below:\n        \"\"\"\n        return self.platform.run_command(self.construct_build_command(**kwargs))\n\n    def build_environment_exists(self):  # noqa: PLR6301\n        \"\"\"\n        If the\n        [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)\n        has a caching mechanism, this should indicate whether or not it has already been created.\n        \"\"\"\n        return False\n\n    def enter_shell(\n        self,\n        name: str,  # noqa: ARG002\n        path: str,\n        args: Iterable[str],\n    ):\n        \"\"\"\n        Spawn a [shell](../../config/hatch.md#shell) within the environment.\n\n        This should either use\n        [command_context](reference.md#hatch.env.plugin.interface.EnvironmentInterface.command_context)\n        directly or provide the same guarantee.\n        \"\"\"\n        with self.command_context():\n            self.platform.exit_with_command([path, *args])\n\n    def run_shell_command(self, command: str, **kwargs):\n        \"\"\"\n        This should return the standard library's\n        [subprocess.CompletedProcess](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess)\n        and will always be called when the\n        [command_context](reference.md#hatch.env.plugin.interface.EnvironmentInterface.command_context)\n        is active, with the expectation of providing the same guarantee.\n        \"\"\"\n        kwargs.setdefault('shell', True)\n        return self.platform.run_command(command, **kwargs)\n\n    @contextmanager\n    def command_context(self):\n        \"\"\"\n        A context manager that when active should make executed shell commands reflect any\n        [environment variables](reference.md#hatch.env.plugin.interface.EnvironmentInterface.get_env_vars)\n        the user defined either currently or at the time of\n        [creation](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).\n\n        For an example, open the default implementation below:\n        \"\"\"\n        with self.get_env_vars():\n            yield\n\n    def resolve_commands(self, commands: list[str]):\n        \"\"\"\n        This expands each command into one or more commands based on any\n        [scripts](../../config/environment/overview.md#scripts) that the user defined.\n        \"\"\"\n        for command in commands:\n            yield from self.expand_command(command)\n\n    def expand_command(self, command):\n        possible_script, args, _ignore_exit_code = parse_script_command(command)\n\n        # Indicate undefined\n        if not args:\n            args = None\n\n        with self.apply_context():\n            if possible_script in self.scripts:\n                if args is not None:\n                    args = self.metadata.context.format(args)\n\n                for cmd in self.scripts[possible_script]:\n                    yield self.metadata.context.format(cmd, args=args).strip()\n            else:\n                yield self.metadata.context.format(command, args=args).strip()\n\n    def construct_build_command(  # noqa: PLR6301\n        self,\n        *,\n        directory=None,\n        targets=(),\n        hooks_only=False,\n        no_hooks=False,\n        clean=False,\n        clean_hooks_after=False,\n        clean_only=False,\n    ):\n        \"\"\"\n        This is the canonical way [`build`](../../cli/reference.md#hatch-build) command options are translated to\n        a subprocess command issued to [builders](../builder/reference.md).\n        \"\"\"\n        command = ['python', '-u', '-m', 'hatchling', 'build']\n\n        if directory:\n            command.extend(('--directory', directory))\n\n        if targets:\n            for target in targets:\n                command.extend(('--target', target))\n\n        if hooks_only:\n            command.append('--hooks-only')\n\n        if no_hooks:\n            command.append('--no-hooks')\n\n        if clean:\n            command.append('--clean')\n\n        if clean_hooks_after:\n            command.append('--clean-hooks-after')\n\n        if clean_only:\n            command.append('--clean-only')\n\n        return command\n\n    def construct_pip_install_command(self, args: list[str]):\n        \"\"\"\n        A convenience method for constructing a [`pip install`](https://pip.pypa.io/en/stable/cli/pip_install/)\n        command with the given verbosity. The default verbosity is set to one less than Hatch's verbosity.\n        \"\"\"\n        command = ['python', '-u', '-m', 'pip', 'install', '--disable-pip-version-check', '--no-python-version-warning']\n\n        # Default to -1 verbosity\n        add_verbosity_flag(command, self.verbosity, adjustment=-1)\n\n        command.extend(args)\n        return command\n\n    def join_command_args(self, args: list[str]):\n        \"\"\"\n        This is used by the [`run`](../../cli/reference.md#hatch-run) command to construct the root command string\n        from the received arguments.\n        \"\"\"\n        return self.platform.join_command_args(args)\n\n    def apply_features(self, requirement: str):\n        \"\"\"\n        A convenience method that applies any user defined [features](../../config/environment/overview.md#features)\n        to the given requirement.\n        \"\"\"\n        if self.features:\n            features = ','.join(self.features)\n            return f'{requirement}[{features}]'\n\n        return requirement\n\n    def check_compatibility(self):\n        \"\"\"\n        This raises an exception if the environment is not compatible with the user's setup. The default behavior\n        checks for [platform compatibility](../../config/environment/overview.md#supported-platforms)\n        and any method override should keep this check.\n\n        This check is never performed if the environment has been\n        [created](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).\n        \"\"\"\n        if self.platforms and self.platform.name not in self.platforms:\n            message = 'unsupported platform'\n            raise OSError(message)\n\n    def get_env_vars(self) -> EnvVars:\n        \"\"\"\n        Returns a mapping of environment variables that should be available to the environment. The object can\n        be used as a context manager to temporarily apply the environment variables to the current process.\n\n        !!! note\n            The environment variable `HATCH_ENV_ACTIVE` will always be set to the name of the environment.\n        \"\"\"\n        return EnvVars(self.env_vars, self.env_include, self.env_exclude)\n\n    def get_env_var_option(self, option: str) -> str:\n        \"\"\"\n        Returns the value of the upper-cased environment variable `HATCH_ENV_TYPE_<PLUGIN_NAME>_<option>`.\n        \"\"\"\n        return get_env_var_option(plugin_name=self.PLUGIN_NAME, option=option)\n\n    def get_context(self):\n        \"\"\"\n        Returns a subclass of\n        [EnvironmentContextFormatter](../utilities.md#hatch.env.context.EnvironmentContextFormatter).\n        \"\"\"\n        from hatch.env.context import EnvironmentContextFormatter\n\n        return EnvironmentContextFormatter(self)\n\n    @staticmethod\n    def get_option_types() -> dict:\n        \"\"\"\n        Returns a mapping of supported options to their respective types so that they can be used by\n        [overrides](../../config/environment/advanced.md#option-overrides).\n        \"\"\"\n        return {}\n\n    @contextmanager\n    def apply_context(self):\n        with self.get_env_vars(), self.metadata.context.apply_context(self.context):\n            yield\n\n    def __enter__(self):\n        self.activate()\n        return self\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        self.deactivate()\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.PLUGIN_NAME","title":"PLUGIN_NAME = '' class-attribute instance-attribute","text":"

    The name used for selection.

    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.app","title":"app property","text":"

    An instance of Application.

    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.root","title":"root property","text":"

    The root of the project tree as a path-like object.

    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.name","title":"name: str property","text":"

    The name of the environment.

    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.data_directory","title":"data_directory property","text":"

    The directory this plugin should use for storage as a path-like object. If the user has not configured one then this will be the same as the isolated data directory.

    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.isolated_data_directory","title":"isolated_data_directory property","text":"

    The default directory reserved exclusively for this plugin as a path-like object.

    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.config","title":"config: dict property","text":"pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\n
    [envs.<ENV_NAME>]\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.platform","title":"platform property","text":"

    An instance of Platform.

    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.environment_dependencies","title":"environment_dependencies: list[str] property","text":"

    The list of all environment dependencies.

    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.dependencies","title":"dependencies: list[str] property","text":"

    The list of all project dependencies (if installed and in dev mode), selected optional dependencies, and environment dependencies.

    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.env_vars","title":"env_vars: dict property","text":"pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>.env-vars]\n
    [envs.<ENV_NAME>.env-vars]\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.env_include","title":"env_include: list[str] property","text":"pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\nenv-include = [...]\n
    [envs.<ENV_NAME>]\nenv-include = [...]\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.env_exclude","title":"env_exclude: list[str] property","text":"pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\nenv-exclude = [...]\n
    [envs.<ENV_NAME>]\nenv-exclude = [...]\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.platforms","title":"platforms: list[str] property","text":"

    All names are stored as their lower-cased version.

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\nplatforms = [...]\n
    [envs.<ENV_NAME>]\nplatforms = [...]\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.skip_install","title":"skip_install: bool property","text":"pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\nskip-install = ...\n
    [envs.<ENV_NAME>]\nskip-install = ...\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.dev_mode","title":"dev_mode: bool property","text":"pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\ndev-mode = ...\n
    [envs.<ENV_NAME>]\ndev-mode = ...\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.description","title":"description: str property","text":"pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\ndescription = ...\n
    [envs.<ENV_NAME>]\ndescription = ...\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.find","title":"find() abstractmethod","text":"

    REQUIRED

    This should return information about how to locate the environment or represent its ID in some way. Additionally, this is expected to return something even if the environment is incompatible.

    Source code in src/hatch/env/plugin/interface.py
    @abstractmethod\ndef find(self):\n    \"\"\"\n    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n    This should return information about how to locate the environment or represent its ID in\n    some way. Additionally, this is expected to return something even if the environment is\n    [incompatible](reference.md#hatch.env.plugin.interface.EnvironmentInterface.check_compatibility).\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.create","title":"create() abstractmethod","text":"

    REQUIRED

    This should perform the necessary steps to set up the environment.

    Source code in src/hatch/env/plugin/interface.py
    @abstractmethod\ndef create(self):\n    \"\"\"\n    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n    This should perform the necessary steps to set up the environment.\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.remove","title":"remove() abstractmethod","text":"

    REQUIRED

    This should perform the necessary steps to completely remove the environment from the system and will only be triggered manually by users with the env remove or env prune commands.

    If the build environment has a caching mechanism, this should remove that as well.

    Source code in src/hatch/env/plugin/interface.py
    @abstractmethod\ndef remove(self):\n    \"\"\"\n    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n    This should perform the necessary steps to completely remove the environment from the system and will only\n    be triggered manually by users with the [`env remove`](../../cli/reference.md#hatch-env-remove) or\n    [`env prune`](../../cli/reference.md#hatch-env-prune) commands.\n\n    If the\n    [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)\n    has a caching mechanism, this should remove that as well.\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.exists","title":"exists() -> bool abstractmethod","text":"

    REQUIRED

    This should indicate whether or not the environment has already been created.

    Source code in src/hatch/env/plugin/interface.py
    @abstractmethod\ndef exists(self) -> bool:\n    \"\"\"\n    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n    This should indicate whether or not the environment has already been created.\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.install_project","title":"install_project() abstractmethod","text":"

    REQUIRED

    This should install the project in the environment.

    Source code in src/hatch/env/plugin/interface.py
    @abstractmethod\ndef install_project(self):\n    \"\"\"\n    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n    This should install the project in the environment.\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.install_project_dev_mode","title":"install_project_dev_mode() abstractmethod","text":"

    REQUIRED

    This should install the project in the environment such that the environment always reflects the current state of the project.

    Source code in src/hatch/env/plugin/interface.py
    @abstractmethod\ndef install_project_dev_mode(self):\n    \"\"\"\n    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n    This should install the project in the environment such that the environment\n    always reflects the current state of the project.\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.dependencies_in_sync","title":"dependencies_in_sync() -> bool abstractmethod","text":"

    REQUIRED

    This should indicate whether or not the environment is compatible with the current dependencies.

    Source code in src/hatch/env/plugin/interface.py
    @abstractmethod\ndef dependencies_in_sync(self) -> bool:\n    \"\"\"\n    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n    This should indicate whether or not the environment is compatible with the current\n    [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies).\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.sync_dependencies","title":"sync_dependencies() abstractmethod","text":"

    REQUIRED

    This should install the dependencies in the environment.

    Source code in src/hatch/env/plugin/interface.py
    @abstractmethod\ndef sync_dependencies(self):\n    \"\"\"\n    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n    This should install the\n    [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies)\n    in the environment.\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.dependency_hash","title":"dependency_hash()","text":"

    This should return a hash of the environment's dependencies and any other data that is handled by the sync_dependencies and dependencies_in_sync methods.

    Source code in src/hatch/env/plugin/interface.py
    def dependency_hash(self):\n    \"\"\"\n    This should return a hash of the environment's\n    [dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies)\n    and any other data that is handled by the\n    [sync_dependencies](reference.md#hatch.env.plugin.interface.EnvironmentInterface.sync_dependencies)\n    and\n    [dependencies_in_sync](reference.md#hatch.env.plugin.interface.EnvironmentInterface.dependencies_in_sync)\n    methods.\n    \"\"\"\n    from hatch.utils.dep import hash_dependencies\n\n    return hash_dependencies(self.dependencies_complex)\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.build_environment","title":"build_environment(dependencies: list[str])","text":"

    This should set up an isolated environment in which to build the project given a set of dependencies and must be a context manager:

    with environment.build_environment([...]):\n    ...\n

    The build environment should reflect any environment variables the user defined either currently or at the time of creation.

    Source code in src/hatch/env/plugin/interface.py
    @contextmanager\ndef build_environment(\n    self,\n    dependencies: list[str],  # noqa: ARG002\n):\n    \"\"\"\n    This should set up an isolated environment in which to [`build`](../../cli/reference.md#hatch-build) the project\n    given a set of dependencies and must be a context manager:\n\n    ```python\n    with environment.build_environment([...]):\n        ...\n    ```\n\n    The build environment should reflect any\n    [environment variables](reference.md#hatch.env.plugin.interface.EnvironmentInterface.get_env_vars)\n    the user defined either currently or at the time of\n    [creation](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).\n    \"\"\"\n    with self.get_env_vars():\n        yield\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.build_environment_exists","title":"build_environment_exists()","text":"

    If the build environment has a caching mechanism, this should indicate whether or not it has already been created.

    Source code in src/hatch/env/plugin/interface.py
    def build_environment_exists(self):  # noqa: PLR6301\n    \"\"\"\n    If the\n    [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)\n    has a caching mechanism, this should indicate whether or not it has already been created.\n    \"\"\"\n    return False\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.activate","title":"activate()","text":"

    A convenience method called when using the environment as a context manager:

    with environment:\n    ...\n
    Source code in src/hatch/env/plugin/interface.py
    def activate(self):\n    \"\"\"\n    A convenience method called when using the environment as a context manager:\n\n    ```python\n    with environment:\n        ...\n    ```\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.deactivate","title":"deactivate()","text":"

    A convenience method called after using the environment as a context manager:

    with environment:\n    ...\n
    Source code in src/hatch/env/plugin/interface.py
    def deactivate(self):\n    \"\"\"\n    A convenience method called after using the environment as a context manager:\n\n    ```python\n    with environment:\n        ...\n    ```\n    \"\"\"\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.app_status_creation","title":"app_status_creation()","text":"

    See the life cycle of environments.

    Source code in src/hatch/env/plugin/interface.py
    @contextmanager\ndef app_status_creation(self):\n    \"\"\"\n    See the [life cycle of environments](reference.md#life-cycle).\n    \"\"\"\n    with self.app.status(f'Creating environment: {self.name}'):\n        yield\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.app_status_pre_installation","title":"app_status_pre_installation()","text":"

    See the life cycle of environments.

    Source code in src/hatch/env/plugin/interface.py
    @contextmanager\ndef app_status_pre_installation(self):\n    \"\"\"\n    See the [life cycle of environments](reference.md#life-cycle).\n    \"\"\"\n    with self.app.status('Running pre-installation commands'):\n        yield\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.app_status_post_installation","title":"app_status_post_installation()","text":"

    See the life cycle of environments.

    Source code in src/hatch/env/plugin/interface.py
    @contextmanager\ndef app_status_post_installation(self):\n    \"\"\"\n    See the [life cycle of environments](reference.md#life-cycle).\n    \"\"\"\n    with self.app.status('Running post-installation commands'):\n        yield\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.app_status_project_installation","title":"app_status_project_installation()","text":"

    See the life cycle of environments.

    Source code in src/hatch/env/plugin/interface.py
    @contextmanager\ndef app_status_project_installation(self):\n    \"\"\"\n    See the [life cycle of environments](reference.md#life-cycle).\n    \"\"\"\n    if self.dev_mode:\n        with self.app.status('Installing project in development mode'):\n            yield\n    else:\n        with self.app.status('Installing project'):\n            yield\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.app_status_dependency_state_check","title":"app_status_dependency_state_check()","text":"

    See the life cycle of environments.

    Source code in src/hatch/env/plugin/interface.py
    @contextmanager\ndef app_status_dependency_state_check(self):\n    \"\"\"\n    See the [life cycle of environments](reference.md#life-cycle).\n    \"\"\"\n    if not self.skip_install and (\n        'dependencies' in self.metadata.dynamic or 'optional-dependencies' in self.metadata.dynamic\n    ):\n        with self.app.status('Polling dependency state'):\n            yield\n    else:\n        yield\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.app_status_dependency_installation_check","title":"app_status_dependency_installation_check()","text":"

    See the life cycle of environments.

    Source code in src/hatch/env/plugin/interface.py
    @contextmanager\ndef app_status_dependency_installation_check(self):\n    \"\"\"\n    See the [life cycle of environments](reference.md#life-cycle).\n    \"\"\"\n    with self.app.status('Checking dependencies'):\n        yield\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.app_status_dependency_synchronization","title":"app_status_dependency_synchronization()","text":"

    See the life cycle of environments.

    Source code in src/hatch/env/plugin/interface.py
    @contextmanager\ndef app_status_dependency_synchronization(self):\n    \"\"\"\n    See the [life cycle of environments](reference.md#life-cycle).\n    \"\"\"\n    with self.app.status('Syncing dependencies'):\n        yield\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.run_builder","title":"run_builder(build_environment, **kwargs)","text":"

    This will be called when the build environment is active:

    with environment.build_environment([...]) as build_env:\n    process = environment.run_builder(build_env, ...)\n

    This should return the standard library's subprocess.CompletedProcess. The command is constructed by passing all keyword arguments to construct_build_command.

    For an example, open the default implementation below:

    Source code in src/hatch/env/plugin/interface.py
    def run_builder(\n    self,\n    build_environment,  # noqa: ARG002\n    **kwargs,\n):\n    \"\"\"\n    This will be called when the\n    [build environment](reference.md#hatch.env.plugin.interface.EnvironmentInterface.build_environment)\n    is active:\n\n    ```python\n    with environment.build_environment([...]) as build_env:\n        process = environment.run_builder(build_env, ...)\n    ```\n\n    This should return the standard library's\n    [subprocess.CompletedProcess](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess).\n    The command is constructed by passing all keyword arguments to\n    [construct_build_command](reference.md#hatch.env.plugin.interface.EnvironmentInterface.construct_build_command).\n\n    For an example, open the default implementation below:\n    \"\"\"\n    return self.platform.run_command(self.construct_build_command(**kwargs))\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.construct_build_command","title":"construct_build_command(*, directory=None, targets=(), hooks_only=False, no_hooks=False, clean=False, clean_hooks_after=False, clean_only=False)","text":"

    This is the canonical way build command options are translated to a subprocess command issued to builders.

    Source code in src/hatch/env/plugin/interface.py
    def construct_build_command(  # noqa: PLR6301\n    self,\n    *,\n    directory=None,\n    targets=(),\n    hooks_only=False,\n    no_hooks=False,\n    clean=False,\n    clean_hooks_after=False,\n    clean_only=False,\n):\n    \"\"\"\n    This is the canonical way [`build`](../../cli/reference.md#hatch-build) command options are translated to\n    a subprocess command issued to [builders](../builder/reference.md).\n    \"\"\"\n    command = ['python', '-u', '-m', 'hatchling', 'build']\n\n    if directory:\n        command.extend(('--directory', directory))\n\n    if targets:\n        for target in targets:\n            command.extend(('--target', target))\n\n    if hooks_only:\n        command.append('--hooks-only')\n\n    if no_hooks:\n        command.append('--no-hooks')\n\n    if clean:\n        command.append('--clean')\n\n    if clean_hooks_after:\n        command.append('--clean-hooks-after')\n\n    if clean_only:\n        command.append('--clean-only')\n\n    return command\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.command_context","title":"command_context()","text":"

    A context manager that when active should make executed shell commands reflect any environment variables the user defined either currently or at the time of creation.

    For an example, open the default implementation below:

    Source code in src/hatch/env/plugin/interface.py
    @contextmanager\ndef command_context(self):\n    \"\"\"\n    A context manager that when active should make executed shell commands reflect any\n    [environment variables](reference.md#hatch.env.plugin.interface.EnvironmentInterface.get_env_vars)\n    the user defined either currently or at the time of\n    [creation](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).\n\n    For an example, open the default implementation below:\n    \"\"\"\n    with self.get_env_vars():\n        yield\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.enter_shell","title":"enter_shell(name: str, path: str, args: Iterable[str])","text":"

    Spawn a shell within the environment.

    This should either use command_context directly or provide the same guarantee.

    Source code in src/hatch/env/plugin/interface.py
    def enter_shell(\n    self,\n    name: str,  # noqa: ARG002\n    path: str,\n    args: Iterable[str],\n):\n    \"\"\"\n    Spawn a [shell](../../config/hatch.md#shell) within the environment.\n\n    This should either use\n    [command_context](reference.md#hatch.env.plugin.interface.EnvironmentInterface.command_context)\n    directly or provide the same guarantee.\n    \"\"\"\n    with self.command_context():\n        self.platform.exit_with_command([path, *args])\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.run_shell_command","title":"run_shell_command(command: str, **kwargs)","text":"

    This should return the standard library's subprocess.CompletedProcess and will always be called when the command_context is active, with the expectation of providing the same guarantee.

    Source code in src/hatch/env/plugin/interface.py
    def run_shell_command(self, command: str, **kwargs):\n    \"\"\"\n    This should return the standard library's\n    [subprocess.CompletedProcess](https://docs.python.org/3/library/subprocess.html#subprocess.CompletedProcess)\n    and will always be called when the\n    [command_context](reference.md#hatch.env.plugin.interface.EnvironmentInterface.command_context)\n    is active, with the expectation of providing the same guarantee.\n    \"\"\"\n    kwargs.setdefault('shell', True)\n    return self.platform.run_command(command, **kwargs)\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.resolve_commands","title":"resolve_commands(commands: list[str])","text":"

    This expands each command into one or more commands based on any scripts that the user defined.

    Source code in src/hatch/env/plugin/interface.py
    def resolve_commands(self, commands: list[str]):\n    \"\"\"\n    This expands each command into one or more commands based on any\n    [scripts](../../config/environment/overview.md#scripts) that the user defined.\n    \"\"\"\n    for command in commands:\n        yield from self.expand_command(command)\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.get_env_vars","title":"get_env_vars() -> EnvVars","text":"

    Returns a mapping of environment variables that should be available to the environment. The object can be used as a context manager to temporarily apply the environment variables to the current process.

    Note

    The environment variable HATCH_ENV_ACTIVE will always be set to the name of the environment.

    Source code in src/hatch/env/plugin/interface.py
    def get_env_vars(self) -> EnvVars:\n    \"\"\"\n    Returns a mapping of environment variables that should be available to the environment. The object can\n    be used as a context manager to temporarily apply the environment variables to the current process.\n\n    !!! note\n        The environment variable `HATCH_ENV_ACTIVE` will always be set to the name of the environment.\n    \"\"\"\n    return EnvVars(self.env_vars, self.env_include, self.env_exclude)\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.apply_features","title":"apply_features(requirement: str)","text":"

    A convenience method that applies any user defined features to the given requirement.

    Source code in src/hatch/env/plugin/interface.py
    def apply_features(self, requirement: str):\n    \"\"\"\n    A convenience method that applies any user defined [features](../../config/environment/overview.md#features)\n    to the given requirement.\n    \"\"\"\n    if self.features:\n        features = ','.join(self.features)\n        return f'{requirement}[{features}]'\n\n    return requirement\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.construct_pip_install_command","title":"construct_pip_install_command(args: list[str])","text":"

    A convenience method for constructing a pip install command with the given verbosity. The default verbosity is set to one less than Hatch's verbosity.

    Source code in src/hatch/env/plugin/interface.py
    def construct_pip_install_command(self, args: list[str]):\n    \"\"\"\n    A convenience method for constructing a [`pip install`](https://pip.pypa.io/en/stable/cli/pip_install/)\n    command with the given verbosity. The default verbosity is set to one less than Hatch's verbosity.\n    \"\"\"\n    command = ['python', '-u', '-m', 'pip', 'install', '--disable-pip-version-check', '--no-python-version-warning']\n\n    # Default to -1 verbosity\n    add_verbosity_flag(command, self.verbosity, adjustment=-1)\n\n    command.extend(args)\n    return command\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.join_command_args","title":"join_command_args(args: list[str])","text":"

    This is used by the run command to construct the root command string from the received arguments.

    Source code in src/hatch/env/plugin/interface.py
    def join_command_args(self, args: list[str]):\n    \"\"\"\n    This is used by the [`run`](../../cli/reference.md#hatch-run) command to construct the root command string\n    from the received arguments.\n    \"\"\"\n    return self.platform.join_command_args(args)\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.check_compatibility","title":"check_compatibility()","text":"

    This raises an exception if the environment is not compatible with the user's setup. The default behavior checks for platform compatibility and any method override should keep this check.

    This check is never performed if the environment has been created.

    Source code in src/hatch/env/plugin/interface.py
    def check_compatibility(self):\n    \"\"\"\n    This raises an exception if the environment is not compatible with the user's setup. The default behavior\n    checks for [platform compatibility](../../config/environment/overview.md#supported-platforms)\n    and any method override should keep this check.\n\n    This check is never performed if the environment has been\n    [created](reference.md#hatch.env.plugin.interface.EnvironmentInterface.create).\n    \"\"\"\n    if self.platforms and self.platform.name not in self.platforms:\n        message = 'unsupported platform'\n        raise OSError(message)\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.get_option_types","title":"get_option_types() -> dict staticmethod","text":"

    Returns a mapping of supported options to their respective types so that they can be used by overrides.

    Source code in src/hatch/env/plugin/interface.py
    @staticmethod\ndef get_option_types() -> dict:\n    \"\"\"\n    Returns a mapping of supported options to their respective types so that they can be used by\n    [overrides](../../config/environment/advanced.md#option-overrides).\n    \"\"\"\n    return {}\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.get_env_var_option","title":"get_env_var_option(option: str) -> str","text":"

    Returns the value of the upper-cased environment variable HATCH_ENV_TYPE_<PLUGIN_NAME>_<option>.

    Source code in src/hatch/env/plugin/interface.py
    def get_env_var_option(self, option: str) -> str:\n    \"\"\"\n    Returns the value of the upper-cased environment variable `HATCH_ENV_TYPE_<PLUGIN_NAME>_<option>`.\n    \"\"\"\n    return get_env_var_option(plugin_name=self.PLUGIN_NAME, option=option)\n
    "},{"location":"plugins/environment/reference/#hatch.env.plugin.interface.EnvironmentInterface.get_context","title":"get_context()","text":"

    Returns a subclass of EnvironmentContextFormatter.

    Source code in src/hatch/env/plugin/interface.py
    def get_context(self):\n    \"\"\"\n    Returns a subclass of\n    [EnvironmentContextFormatter](../utilities.md#hatch.env.context.EnvironmentContextFormatter).\n    \"\"\"\n    from hatch.env.context import EnvironmentContextFormatter\n\n    return EnvironmentContextFormatter(self)\n
    "},{"location":"plugins/environment/virtual/","title":"Virtual environment","text":"

    This uses virtual environments backed by virtualenv or UV.

    "},{"location":"plugins/environment/virtual/#configuration","title":"Configuration","text":"

    The environment plugin name is virtual.

    pyproject.toml hatch.toml
    [tool.hatch.envs.<ENV_NAME>]\ntype = \"virtual\"\n
    [envs.<ENV_NAME>]\ntype = \"virtual\"\n
    "},{"location":"plugins/environment/virtual/#options","title":"Options","text":"Option Default Description python The version of Python to find on your system and subsequently use to create the environment, defaulting to the HATCH_PYTHON environment variable, followed by the normal resolution logic. Setting the HATCH_PYTHON environment variable to self will force the use of the Python executable Hatch is running on. For more information, see the documentation. python-sources ['external', 'internal'] This may be set to an array of strings that are either the literal internal or external. External considers only Python executables that are already on PATH. Internal considers only internally managed Python distributions. path An explicit path to the virtual environment. The path may be absolute or relative to the project root. Any environments that inherit this option will also use this path. The environment variable HATCH_ENV_TYPE_VIRTUAL_PATH may be used, which will take precedence. system-packages false Whether or not to give the virtual environment access to the system site-packages directory installer pip When set to uv, UV will be used in place of virtualenv & pip for virtual environment creation and dependency management, respectively. If you intend to provide UV yourself, you may set the HATCH_ENV_TYPE_VIRTUAL_UV_PATH environment variable which should be the absolute path to a UV binary. This environment variable implicitly sets the installer option to uv (if unset)."},{"location":"plugins/environment/virtual/#location","title":"Location","text":"

    The location of environments is determined in the following heuristic order:

    1. The path option
    2. A directory named after the environment within the configured virtual environment directory if the directory resides somewhere within the project root or if it is set to a .virtualenvs directory within the user's home directory
    3. Otherwise, environments are stored within the configured virtual environment directory in a deeply nested structure in order to support multiple projects

    Additionally, when the path option is not used, the name of the directory for the default environment will be the normalized project name to provide a more meaningful default shell prompt.

    "},{"location":"plugins/environment/virtual/#python-resolution","title":"Python resolution","text":"

    Virtual environments necessarily require a parent installation of Python. The following rules determine how the parent is resolved.

    The Python choice is determined by the python option followed by the HATCH_PYTHON environment variable. If the choice is via the environment variable, then resolution stops and that path is used unconditionally.

    The resolvers will be based on the python-sources option and all resolved interpreters will ensure compatibility with the project's defined Python support.

    If a Python version has been chosen then each resolver will try to find an interpreter that satisfies that version.

    If no version has been chosen, then each resolver will try to find a version that matches the version of Python that Hatch is currently running on. If not found then each resolver will try to find the highest compatible version.

    Note

    Some external Python paths are considered unstable and are ignored during resolution. For example, if Hatch is installed via Homebrew then sys.executable will be ignored because the interpreter could change or be removed at any time.

    Note

    When resolution finds a match using an internally managed distribution and an update is available, the latest distribution will automatically be downloaded before environment creation.

    "},{"location":"plugins/environment/virtual/#internal-distributions","title":"Internal distributions","text":"

    The following options are recognized for internal Python resolution.

    Tip

    You can set custom sources for distributions by setting the HATCH_PYTHON_SOURCE_<NAME> environment variable where <NAME> is the uppercased version of the distribution name with periods replaced by underscores e.g. HATCH_PYTHON_SOURCE_PYPY3_10.

    "},{"location":"plugins/environment/virtual/#cpython","title":"CPython","text":"NAME 3.7 3.8 3.9 3.10 3.11 3.12 3.13

    The source of distributions is the python-build-standalone project.

    Some distributions have variants that may be configured. Options may be combined.

    Option Platforms Allowed values HATCH_PYTHON_VARIANT_CPU
    • Linux
    • v1
    • v2
    • v3 (default)
    • v4
    HATCH_PYTHON_VARIANT_GIL
    • Linux
    • Windows
    • macOS
    • freethreaded
    "},{"location":"plugins/environment/virtual/#pypy","title":"PyPy","text":"NAME pypy2.7 pypy3.9 pypy3.10

    The source of distributions is the PyPy project.

    "},{"location":"plugins/environment/virtual/#troubleshooting","title":"Troubleshooting","text":""},{"location":"plugins/environment/virtual/#macos-sip","title":"macOS SIP","text":"

    If you need to set linker environment variables like those starting with DYLD_ or LD_, any executable secured by System Integrity Protection that is invoked when running commands will not see those environment variable modifications as macOS strips those.

    Hatch interprets such commands as shell commands but deliberately ignores such paths to protected shells. This workaround suffices for the majority of use cases but there are 2 situations in which it may not:

    1. There are no unprotected sh, bash, zsh, nor fish executables found along PATH.
    2. The desired executable is a project's script, and the location of environments contains spaces or is longer than 1241 characters. In this case pip and other installers will create such an entry point with a shebang pointing to /bin/sh (which is protected) to avoid shebang limitations. Rather than changing the location, you could invoke the script as e.g. python -m pytest (if the project supports that method of invocation by shipping a __main__.py).
    1. The shebang length limit is usually 127 but 3 characters surround the executable path: #!<EXE_PATH>\\n \u21a9

    "},{"location":"plugins/environment-collector/custom/","title":"Custom environment collector","text":"

    This is a custom class in a given Python file that inherits from the EnvironmentCollectorInterface.

    "},{"location":"plugins/environment-collector/custom/#configuration","title":"Configuration","text":"

    The environment collector plugin name is custom.

    pyproject.toml hatch.toml
    [tool.hatch.env.collectors.custom]\n
    [env.collectors.custom]\n
    "},{"location":"plugins/environment-collector/custom/#options","title":"Options","text":"Option Default Description path hatch_plugins.py The path of the Python file"},{"location":"plugins/environment-collector/custom/#example","title":"Example","text":"hatch_plugins.py
        from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface\n\n\n    class CustomEnvironmentCollector(EnvironmentCollectorInterface):\n        ...\n

    If multiple subclasses are found, you must define a function named get_environment_collector that returns the desired environment collector.

    Note

    Any defined PLUGIN_NAME is ignored and will always be custom.

    "},{"location":"plugins/environment-collector/default/","title":"Default environment collector","text":"

    This adds the default environment with type set to virtual and will always be applied.

    "},{"location":"plugins/environment-collector/default/#configuration","title":"Configuration","text":"

    The environment collector plugin name is default.

    pyproject.toml hatch.toml
    [tool.hatch.env.collectors.default]\n
    [env.collectors.default]\n
    "},{"location":"plugins/environment-collector/default/#options","title":"Options","text":"

    There are no options available currently.

    "},{"location":"plugins/environment-collector/reference/","title":"Environment collector plugins","text":"

    Environment collectors allow for dynamically modifying environments or adding environments beyond those defined in config. Users can override default values provided by each environment.

    "},{"location":"plugins/environment-collector/reference/#known-third-party","title":"Known third-party","text":"
    • hatch-mkdocs - integrate MkDocs and infer dependencies into an env
    "},{"location":"plugins/environment-collector/reference/#installation","title":"Installation","text":"

    Any required environment collectors that are not built-in must be manually installed alongside Hatch or listed in the tool.hatch.env.requires array for automatic management:

    pyproject.toml hatch.toml
    [tool.hatch.env]\nrequires = [\n  \"...\",\n]\n
    [env]\nrequires = [\n  \"...\",\n]\n
    "},{"location":"plugins/environment-collector/reference/#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface","title":"EnvironmentCollectorInterface","text":"

    Example usage:

    plugin.py hooks.py
        from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface\n\n\n    class SpecialEnvironmentCollector(EnvironmentCollectorInterface):\n        PLUGIN_NAME = 'special'\n        ...\n
        from hatchling.plugin import hookimpl\n\n    from .plugin import SpecialEnvironmentCollector\n\n\n    @hookimpl\n    def hatch_register_environment_collector():\n        return SpecialEnvironmentCollector\n
    Source code in src/hatch/env/collectors/plugin/interface.py
    class EnvironmentCollectorInterface:\n    \"\"\"\n    Example usage:\n\n    ```python tab=\"plugin.py\"\n        from hatch.env.collectors.plugin.interface import EnvironmentCollectorInterface\n\n\n        class SpecialEnvironmentCollector(EnvironmentCollectorInterface):\n            PLUGIN_NAME = 'special'\n            ...\n    ```\n\n    ```python tab=\"hooks.py\"\n        from hatchling.plugin import hookimpl\n\n        from .plugin import SpecialEnvironmentCollector\n\n\n        @hookimpl\n        def hatch_register_environment_collector():\n            return SpecialEnvironmentCollector\n    ```\n    \"\"\"\n\n    PLUGIN_NAME = ''\n    \"\"\"The name used for selection.\"\"\"\n\n    def __init__(self, root, config):\n        self.__root = root\n        self.__config = config\n\n    @property\n    def root(self):\n        \"\"\"\n        The root of the project tree as a path-like object.\n        \"\"\"\n        return self.__root\n\n    @property\n    def config(self) -> dict:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.env.collectors.<PLUGIN_NAME>]\n        ```\n        \"\"\"\n        return self.__config\n\n    def get_initial_config(self) -> dict[str, dict]:  # noqa: PLR6301\n        \"\"\"\n        Returns configuration for environments keyed by the environment or matrix name.\n        \"\"\"\n        return {}\n\n    def finalize_config(self, config: dict[str, dict]):\n        \"\"\"\n        Finalizes configuration for environments keyed by the environment or matrix name. This will override\n        any user-defined settings and any collectors that ran before this call.\n\n        This is called before matrices are turned into concrete environments.\n        \"\"\"\n\n    def finalize_environments(self, config: dict[str, dict]):\n        \"\"\"\n        Finalizes configuration for environments keyed by the environment name. This will override\n        any user-defined settings and any collectors that ran before this call.\n\n        This is called after matrices are turned into concrete environments.\n        \"\"\"\n
    "},{"location":"plugins/environment-collector/reference/#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.PLUGIN_NAME","title":"PLUGIN_NAME = '' class-attribute instance-attribute","text":"

    The name used for selection.

    "},{"location":"plugins/environment-collector/reference/#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.root","title":"root property","text":"

    The root of the project tree as a path-like object.

    "},{"location":"plugins/environment-collector/reference/#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.config","title":"config: dict property","text":"pyproject.toml hatch.toml
    [tool.hatch.env.collectors.<PLUGIN_NAME>]\n
    [env.collectors.<PLUGIN_NAME>]\n
    "},{"location":"plugins/environment-collector/reference/#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.get_initial_config","title":"get_initial_config() -> dict[str, dict]","text":"

    Returns configuration for environments keyed by the environment or matrix name.

    Source code in src/hatch/env/collectors/plugin/interface.py
    def get_initial_config(self) -> dict[str, dict]:  # noqa: PLR6301\n    \"\"\"\n    Returns configuration for environments keyed by the environment or matrix name.\n    \"\"\"\n    return {}\n
    "},{"location":"plugins/environment-collector/reference/#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.finalize_config","title":"finalize_config(config: dict[str, dict])","text":"

    Finalizes configuration for environments keyed by the environment or matrix name. This will override any user-defined settings and any collectors that ran before this call.

    This is called before matrices are turned into concrete environments.

    Source code in src/hatch/env/collectors/plugin/interface.py
    def finalize_config(self, config: dict[str, dict]):\n    \"\"\"\n    Finalizes configuration for environments keyed by the environment or matrix name. This will override\n    any user-defined settings and any collectors that ran before this call.\n\n    This is called before matrices are turned into concrete environments.\n    \"\"\"\n
    "},{"location":"plugins/environment-collector/reference/#hatch.env.collectors.plugin.interface.EnvironmentCollectorInterface.finalize_environments","title":"finalize_environments(config: dict[str, dict])","text":"

    Finalizes configuration for environments keyed by the environment name. This will override any user-defined settings and any collectors that ran before this call.

    This is called after matrices are turned into concrete environments.

    Source code in src/hatch/env/collectors/plugin/interface.py
    def finalize_environments(self, config: dict[str, dict]):\n    \"\"\"\n    Finalizes configuration for environments keyed by the environment name. This will override\n    any user-defined settings and any collectors that ran before this call.\n\n    This is called after matrices are turned into concrete environments.\n    \"\"\"\n
    "},{"location":"plugins/metadata-hook/custom/","title":"Custom metadata hook","text":"

    This is a custom class in a given Python file that inherits from the MetadataHookInterface.

    "},{"location":"plugins/metadata-hook/custom/#configuration","title":"Configuration","text":"

    The metadata hook plugin name is custom.

    pyproject.toml hatch.toml
    [tool.hatch.metadata.hooks.custom]\n
    [metadata.hooks.custom]\n
    "},{"location":"plugins/metadata-hook/custom/#options","title":"Options","text":"Option Default Description path hatch_build.py The path of the Python file"},{"location":"plugins/metadata-hook/custom/#example","title":"Example","text":"hatch_build.py
    from hatchling.metadata.plugin.interface import MetadataHookInterface\n\n\nclass CustomMetadataHook(MetadataHookInterface):\n    ...\n

    If multiple subclasses are found, you must define a function named get_metadata_hook that returns the desired build hook.

    Note

    Any defined PLUGIN_NAME is ignored and will always be custom.

    "},{"location":"plugins/metadata-hook/reference/","title":"Metadata hook plugins","text":"

    Metadata hooks allow for the modification of project metadata after it has been loaded.

    "},{"location":"plugins/metadata-hook/reference/#known-third-party","title":"Known third-party","text":"
    • hatch-docstring-description - set the project description using docstrings
    • hatch-fancy-pypi-readme - dynamically construct the README
    • hatch-nodejs-version - uses fields from NodeJS package.json files
    • hatch-odoo - determine dependencies based on manifests of Odoo add-ons
    • hatch-requirements-txt - read project dependencies from requirements.txt files
    • UniDep - for unified pip and conda dependency management using a single requirements.yaml file for both
    "},{"location":"plugins/metadata-hook/reference/#hatchling.metadata.plugin.interface.MetadataHookInterface","title":"MetadataHookInterface","text":"

    Example usage:

    plugin.py hooks.py
    from hatchling.metadata.plugin.interface import MetadataHookInterface\n\n\nclass SpecialMetadataHook(MetadataHookInterface):\n    PLUGIN_NAME = 'special'\n    ...\n
    from hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialMetadataHook\n\n\n@hookimpl\ndef hatch_register_metadata_hook():\n    return SpecialMetadataHook\n
    Source code in backend/src/hatchling/metadata/plugin/interface.py
    class MetadataHookInterface(ABC):  # no cov\n    \"\"\"\n    Example usage:\n\n    ```python tab=\"plugin.py\"\n    from hatchling.metadata.plugin.interface import MetadataHookInterface\n\n\n    class SpecialMetadataHook(MetadataHookInterface):\n        PLUGIN_NAME = 'special'\n        ...\n    ```\n\n    ```python tab=\"hooks.py\"\n    from hatchling.plugin import hookimpl\n\n    from .plugin import SpecialMetadataHook\n\n\n    @hookimpl\n    def hatch_register_metadata_hook():\n        return SpecialMetadataHook\n    ```\n    \"\"\"\n\n    PLUGIN_NAME = ''\n    \"\"\"The name used for selection.\"\"\"\n\n    def __init__(self, root: str, config: dict) -> None:\n        self.__root = root\n        self.__config = config\n\n    @property\n    def root(self) -> str:\n        \"\"\"\n        The root of the project tree.\n        \"\"\"\n        return self.__root\n\n    @property\n    def config(self) -> dict:\n        \"\"\"\n        The hook configuration.\n\n        ```toml config-example\n        [tool.hatch.metadata.hooks.<PLUGIN_NAME>]\n        ```\n        \"\"\"\n        return self.__config\n\n    @abstractmethod\n    def update(self, metadata: dict) -> None:\n        \"\"\"\n        This updates the metadata mapping of the `project` table in-place.\n        \"\"\"\n\n    def get_known_classifiers(self) -> list[str]:  # noqa: PLR6301\n        \"\"\"\n        This returns extra classifiers that should be considered valid in addition to the ones known to PyPI.\n        \"\"\"\n        return []\n
    "},{"location":"plugins/metadata-hook/reference/#hatchling.metadata.plugin.interface.MetadataHookInterface.PLUGIN_NAME","title":"PLUGIN_NAME = '' class-attribute instance-attribute","text":"

    The name used for selection.

    "},{"location":"plugins/metadata-hook/reference/#hatchling.metadata.plugin.interface.MetadataHookInterface.root","title":"root: str property","text":"

    The root of the project tree.

    "},{"location":"plugins/metadata-hook/reference/#hatchling.metadata.plugin.interface.MetadataHookInterface.config","title":"config: dict property","text":"

    The hook configuration.

    pyproject.toml hatch.toml
    [tool.hatch.metadata.hooks.<PLUGIN_NAME>]\n
    [metadata.hooks.<PLUGIN_NAME>]\n
    "},{"location":"plugins/metadata-hook/reference/#hatchling.metadata.plugin.interface.MetadataHookInterface.update","title":"update(metadata: dict) -> None abstractmethod","text":"

    This updates the metadata mapping of the project table in-place.

    Source code in backend/src/hatchling/metadata/plugin/interface.py
    @abstractmethod\ndef update(self, metadata: dict) -> None:\n    \"\"\"\n    This updates the metadata mapping of the `project` table in-place.\n    \"\"\"\n
    "},{"location":"plugins/metadata-hook/reference/#hatchling.metadata.plugin.interface.MetadataHookInterface.get_known_classifiers","title":"get_known_classifiers() -> list[str]","text":"

    This returns extra classifiers that should be considered valid in addition to the ones known to PyPI.

    Source code in backend/src/hatchling/metadata/plugin/interface.py
    def get_known_classifiers(self) -> list[str]:  # noqa: PLR6301\n    \"\"\"\n    This returns extra classifiers that should be considered valid in addition to the ones known to PyPI.\n    \"\"\"\n    return []\n
    "},{"location":"plugins/publisher/package-index/","title":"Index publisher","text":"

    See the documentation for publishing.

    "},{"location":"plugins/publisher/package-index/#options","title":"Options","text":"Flag Config name Description -r/--repo repo The repository with which to publish artifacts -u/--user user The user with which to authenticate -a/--auth auth The credentials to use for authentication --ca-cert ca-cert The path to a CA bundle --client-cert client-cert The path to a client certificate, optionally containing the private key --client-key client-key The path to the client certificate's private key repos A table of named repositories to their respective options"},{"location":"plugins/publisher/package-index/#configuration","title":"Configuration","text":"

    The publisher plugin name is index.

    config.toml
    [publish.index]\n
    "},{"location":"plugins/publisher/package-index/#repositories","title":"Repositories","text":"

    All top-level options can be overridden per repository using the repos table with a required url attribute for each repository. The following shows the default configuration:

    config.toml
    [publish.index.repos.main]\nurl = \"https://upload.pypi.org/legacy/\"\n\n[publish.index.repos.test]\nurl = \"https://test.pypi.org/legacy/\"\n

    The repo and repos options have no effect.

    "},{"location":"plugins/publisher/package-index/#confirmation-prompt","title":"Confirmation prompt","text":"

    You can require a confirmation prompt or use of the -y/--yes flag by setting publishers' disable option to true in either Hatch's config file or project-specific configuration (which takes precedence):

    config.toml pyproject.toml hatch.toml
    [publish.index]\ndisable = true\n
    [tool.hatch.publish.index]\ndisable = true\n
    [publish.index]\ndisable = true\n
    "},{"location":"plugins/publisher/reference/","title":"Publisher plugins","text":""},{"location":"plugins/publisher/reference/#known-third-party","title":"Known third-party","text":"
    • hatch-aws-publisher - publish AWS Lambda functions with SAM
    "},{"location":"plugins/publisher/reference/#hatch.publish.plugin.interface.PublisherInterface","title":"PublisherInterface","text":"

    Example usage:

    plugin.py hooks.py
        from hatch.publish.plugin.interface import PublisherInterface\n\n\n    class SpecialPublisher(PublisherInterface):\n        PLUGIN_NAME = 'special'\n        ...\n
        from hatchling.plugin import hookimpl\n\n    from .plugin import SpecialPublisher\n\n\n    @hookimpl\n    def hatch_register_publisher():\n        return SpecialPublisher\n
    Source code in src/hatch/publish/plugin/interface.py
    class PublisherInterface(ABC):\n    \"\"\"\n    Example usage:\n\n    ```python tab=\"plugin.py\"\n        from hatch.publish.plugin.interface import PublisherInterface\n\n\n        class SpecialPublisher(PublisherInterface):\n            PLUGIN_NAME = 'special'\n            ...\n    ```\n\n    ```python tab=\"hooks.py\"\n        from hatchling.plugin import hookimpl\n\n        from .plugin import SpecialPublisher\n\n\n        @hookimpl\n        def hatch_register_publisher():\n            return SpecialPublisher\n    ```\n    \"\"\"\n\n    PLUGIN_NAME = ''\n    \"\"\"The name used for selection.\"\"\"\n\n    def __init__(self, app, root, cache_dir, project_config, plugin_config):\n        self.__app = app\n        self.__root = root\n        self.__cache_dir = cache_dir\n        self.__project_config = project_config\n        self.__plugin_config = plugin_config\n\n        self.__disable = None\n\n    @property\n    def app(self):\n        \"\"\"\n        An instance of [Application](../utilities.md#hatchling.bridge.app.Application).\n        \"\"\"\n        return self.__app\n\n    @property\n    def root(self):\n        \"\"\"\n        The root of the project tree as a path-like object.\n        \"\"\"\n        return self.__root\n\n    @property\n    def cache_dir(self):\n        \"\"\"\n        The directory reserved exclusively for this plugin as a path-like object.\n        \"\"\"\n        return self.__cache_dir\n\n    @property\n    def project_config(self) -> dict:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.publish.<PLUGIN_NAME>]\n        ```\n        \"\"\"\n        return self.__project_config\n\n    @property\n    def plugin_config(self) -> dict:\n        \"\"\"\n        This is defined in Hatch's [config file](../../config/hatch.md).\n\n        ```toml tab=\"config.toml\"\n        [publish.<PLUGIN_NAME>]\n        ```\n        \"\"\"\n        return self.__plugin_config\n\n    @property\n    def disable(self):\n        \"\"\"\n        Whether this plugin is disabled, thus requiring confirmation when publishing. Local\n        [project configuration](reference.md#hatch.publish.plugin.interface.PublisherInterface.project_config)\n        takes precedence over global\n        [plugin configuration](reference.md#hatch.publish.plugin.interface.PublisherInterface.plugin_config).\n        \"\"\"\n        if self.__disable is None:\n            if 'disable' in self.project_config:\n                disable = self.project_config['disable']\n                if not isinstance(disable, bool):\n                    message = f'Field `tool.hatch.publish.{self.PLUGIN_NAME}.disable` must be a boolean'\n                    raise TypeError(message)\n            else:\n                disable = self.plugin_config.get('disable', False)\n                if not isinstance(disable, bool):\n                    message = f'Global plugin configuration `publish.{self.PLUGIN_NAME}.disable` must be a boolean'\n                    raise TypeError(message)\n\n            self.__disable = disable\n\n        return self.__disable\n\n    @abstractmethod\n    def publish(self, artifacts: list[str], options: dict):\n        \"\"\"\n        :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n        This is called directly by the [`publish`](../../cli/reference.md#hatch-publish) command\n        with the arguments and options it receives.\n        \"\"\"\n
    "},{"location":"plugins/publisher/reference/#hatch.publish.plugin.interface.PublisherInterface.PLUGIN_NAME","title":"PLUGIN_NAME = '' class-attribute instance-attribute","text":"

    The name used for selection.

    "},{"location":"plugins/publisher/reference/#hatch.publish.plugin.interface.PublisherInterface.app","title":"app property","text":"

    An instance of Application.

    "},{"location":"plugins/publisher/reference/#hatch.publish.plugin.interface.PublisherInterface.root","title":"root property","text":"

    The root of the project tree as a path-like object.

    "},{"location":"plugins/publisher/reference/#hatch.publish.plugin.interface.PublisherInterface.cache_dir","title":"cache_dir property","text":"

    The directory reserved exclusively for this plugin as a path-like object.

    "},{"location":"plugins/publisher/reference/#hatch.publish.plugin.interface.PublisherInterface.project_config","title":"project_config: dict property","text":"pyproject.toml hatch.toml
    [tool.hatch.publish.<PLUGIN_NAME>]\n
    [publish.<PLUGIN_NAME>]\n
    "},{"location":"plugins/publisher/reference/#hatch.publish.plugin.interface.PublisherInterface.plugin_config","title":"plugin_config: dict property","text":"

    This is defined in Hatch's config file.

    config.toml
    [publish.<PLUGIN_NAME>]\n
    "},{"location":"plugins/publisher/reference/#hatch.publish.plugin.interface.PublisherInterface.disable","title":"disable property","text":"

    Whether this plugin is disabled, thus requiring confirmation when publishing. Local project configuration takes precedence over global plugin configuration.

    "},{"location":"plugins/publisher/reference/#hatch.publish.plugin.interface.PublisherInterface.publish","title":"publish(artifacts: list[str], options: dict) abstractmethod","text":"

    REQUIRED

    This is called directly by the publish command with the arguments and options it receives.

    Source code in src/hatch/publish/plugin/interface.py
    @abstractmethod\ndef publish(self, artifacts: list[str], options: dict):\n    \"\"\"\n    :material-align-horizontal-left: **REQUIRED** :material-align-horizontal-right:\n\n    This is called directly by the [`publish`](../../cli/reference.md#hatch-publish) command\n    with the arguments and options it receives.\n    \"\"\"\n
    "},{"location":"plugins/version-scheme/reference/","title":"Version scheme plugins","text":""},{"location":"plugins/version-scheme/reference/#known-third-party","title":"Known third-party","text":"
    • hatch-semver - uses semantic versioning
    "},{"location":"plugins/version-scheme/reference/#hatchling.version.scheme.plugin.interface.VersionSchemeInterface","title":"VersionSchemeInterface","text":"

    Example usage:

    plugin.py hooks.py
    from hatchling.version.scheme.plugin.interface import VersionSchemeInterface\n\n\nclass SpecialVersionScheme(VersionSchemeInterface):\n    PLUGIN_NAME = 'special'\n    ...\n
    from hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialVersionScheme\n\n\n@hookimpl\ndef hatch_register_version_scheme():\n    return SpecialVersionScheme\n
    Source code in backend/src/hatchling/version/scheme/plugin/interface.py
    class VersionSchemeInterface(ABC):  # no cov\n    \"\"\"\n    Example usage:\n\n    ```python tab=\"plugin.py\"\n    from hatchling.version.scheme.plugin.interface import VersionSchemeInterface\n\n\n    class SpecialVersionScheme(VersionSchemeInterface):\n        PLUGIN_NAME = 'special'\n        ...\n    ```\n\n    ```python tab=\"hooks.py\"\n    from hatchling.plugin import hookimpl\n\n    from .plugin import SpecialVersionScheme\n\n\n    @hookimpl\n    def hatch_register_version_scheme():\n        return SpecialVersionScheme\n    ```\n    \"\"\"\n\n    PLUGIN_NAME = ''\n    \"\"\"The name used for selection.\"\"\"\n\n    def __init__(self, root: str, config: dict) -> None:\n        self.__root = root\n        self.__config = config\n\n    @property\n    def root(self) -> str:\n        \"\"\"\n        The root of the project tree as a string.\n        \"\"\"\n        return self.__root\n\n    @property\n    def config(self) -> dict:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.version]\n        ```\n        \"\"\"\n        return self.__config\n\n    @abstractmethod\n    def update(self, desired_version: str, original_version: str, version_data: dict) -> str:\n        \"\"\"\n        This should return a normalized form of the desired version and verify that it\n        is higher than the original version.\n        \"\"\"\n
    "},{"location":"plugins/version-scheme/reference/#hatchling.version.scheme.plugin.interface.VersionSchemeInterface.PLUGIN_NAME","title":"PLUGIN_NAME = '' class-attribute instance-attribute","text":"

    The name used for selection.

    "},{"location":"plugins/version-scheme/reference/#hatchling.version.scheme.plugin.interface.VersionSchemeInterface.root","title":"root: str property","text":"

    The root of the project tree as a string.

    "},{"location":"plugins/version-scheme/reference/#hatchling.version.scheme.plugin.interface.VersionSchemeInterface.config","title":"config: dict property","text":"pyproject.toml hatch.toml
    [tool.hatch.version]\n
    [version]\n
    "},{"location":"plugins/version-scheme/reference/#hatchling.version.scheme.plugin.interface.VersionSchemeInterface.update","title":"update(desired_version: str, original_version: str, version_data: dict) -> str abstractmethod","text":"

    This should return a normalized form of the desired version and verify that it is higher than the original version.

    Source code in backend/src/hatchling/version/scheme/plugin/interface.py
    @abstractmethod\ndef update(self, desired_version: str, original_version: str, version_data: dict) -> str:\n    \"\"\"\n    This should return a normalized form of the desired version and verify that it\n    is higher than the original version.\n    \"\"\"\n
    "},{"location":"plugins/version-scheme/standard/","title":"Standard version scheme","text":"

    See the documentation for versioning.

    "},{"location":"plugins/version-scheme/standard/#configuration","title":"Configuration","text":"

    The version scheme plugin name is standard.

    pyproject.toml hatch.toml
    [tool.hatch.version]\nscheme = \"standard\"\n
    [version]\nscheme = \"standard\"\n
    "},{"location":"plugins/version-scheme/standard/#options","title":"Options","text":"Option Description validate-bump When setting a specific version, this determines whether to check that the new version is higher than the original. The default is true."},{"location":"plugins/version-source/code/","title":"Code version source","text":""},{"location":"plugins/version-source/code/#updates","title":"Updates","text":"

    Setting the version is not supported.

    "},{"location":"plugins/version-source/code/#configuration","title":"Configuration","text":"

    The version source plugin name is code.

    pyproject.toml hatch.toml
    [tool.hatch.version]\nsource = \"code\"\n
    [version]\nsource = \"code\"\n
    "},{"location":"plugins/version-source/code/#options","title":"Options","text":"Option Description path (required) A relative path to a Python file or extension module that will be loaded expression A Python expression that when evaluated in the context of the loaded file returns the version. The default expression is simply __version__. search-paths A list of relative paths to directories that will be prepended to Python's search path"},{"location":"plugins/version-source/code/#missing-imports","title":"Missing imports","text":"

    If the chosen path imports another module in your project, then you'll need to use absolute imports coupled with the search-paths option. For example, say you need to load the following file:

    src/pkg/__init__.py
        from ._version import get_version\n\n    __version__ = get_version()\n

    You should change it to:

    src/pkg/__init__.py
        from pkg._version import get_version\n\n    __version__ = get_version()\n

    and the configuration would become:

    pyproject.toml hatch.toml
    [tool.hatch.version]\nsource = \"code\"\npath = \"src/pkg/__init__.py\"\nsearch-paths = [\"src\"]\n
    [version]\nsource = \"code\"\npath = \"src/pkg/__init__.py\"\nsearch-paths = [\"src\"]\n
    "},{"location":"plugins/version-source/env/","title":"Environment version source","text":"

    Retrieves the version from an environment variable. This can be useful in build pipelines where the version is set by an external trigger.

    "},{"location":"plugins/version-source/env/#updates","title":"Updates","text":"

    Setting the version is not supported.

    "},{"location":"plugins/version-source/env/#configuration","title":"Configuration","text":"

    The version source plugin name is env.

    pyproject.toml hatch.toml
    [tool.hatch.version]\nsource = \"env\"\n
    [version]\nsource = \"env\"\n
    "},{"location":"plugins/version-source/env/#options","title":"Options","text":"Option Description variable (required) The name of the environment variable"},{"location":"plugins/version-source/reference/","title":"Version source plugins","text":""},{"location":"plugins/version-source/reference/#known-third-party","title":"Known third-party","text":"
    • hatch-vcs - uses your preferred version control system (like Git)
    • hatch-nodejs-version - uses the version field of NodeJS package.json files
    • hatch-regex-commit - automatically creates a Git commit and tag after version bumping
    • versioningit - determines version from Git or Mercurial tags, with customizable version formatting
    "},{"location":"plugins/version-source/reference/#hatchling.version.source.plugin.interface.VersionSourceInterface","title":"VersionSourceInterface","text":"

    Example usage:

    plugin.py hooks.py
    from hatchling.version.source.plugin.interface import VersionSourceInterface\n\n\nclass SpecialVersionSource(VersionSourceInterface):\n    PLUGIN_NAME = 'special'\n    ...\n
    from hatchling.plugin import hookimpl\n\nfrom .plugin import SpecialVersionSource\n\n\n@hookimpl\ndef hatch_register_version_source():\n    return SpecialVersionSource\n
    Source code in backend/src/hatchling/version/source/plugin/interface.py
    class VersionSourceInterface(ABC):  # no cov\n    \"\"\"\n    Example usage:\n\n    ```python tab=\"plugin.py\"\n    from hatchling.version.source.plugin.interface import VersionSourceInterface\n\n\n    class SpecialVersionSource(VersionSourceInterface):\n        PLUGIN_NAME = 'special'\n        ...\n    ```\n\n    ```python tab=\"hooks.py\"\n    from hatchling.plugin import hookimpl\n\n    from .plugin import SpecialVersionSource\n\n\n    @hookimpl\n    def hatch_register_version_source():\n        return SpecialVersionSource\n    ```\n    \"\"\"\n\n    PLUGIN_NAME = ''\n    \"\"\"The name used for selection.\"\"\"\n\n    def __init__(self, root: str, config: dict) -> None:\n        self.__root = root\n        self.__config = config\n\n    @property\n    def root(self) -> str:\n        \"\"\"\n        The root of the project tree as a string.\n        \"\"\"\n        return self.__root\n\n    @property\n    def config(self) -> dict:\n        \"\"\"\n        ```toml config-example\n        [tool.hatch.version]\n        ```\n        \"\"\"\n        return self.__config\n\n    @abstractmethod\n    def get_version_data(self) -> dict:\n        \"\"\"\n        This should return a mapping with a `version` key representing the current version of the project and will be\n        displayed when invoking the [`version`](../../cli/reference.md#hatch-version) command without any arguments.\n\n        The mapping can contain anything else and will be passed to\n        [set_version](reference.md#hatchling.version.source.plugin.interface.VersionSourceInterface.set_version)\n        when updating the version.\n        \"\"\"\n\n    def set_version(self, version: str, version_data: dict) -> None:\n        \"\"\"\n        This should update the version to the first argument with the data provided during retrieval.\n        \"\"\"\n        raise NotImplementedError\n
    "},{"location":"plugins/version-source/reference/#hatchling.version.source.plugin.interface.VersionSourceInterface.PLUGIN_NAME","title":"PLUGIN_NAME = '' class-attribute instance-attribute","text":"

    The name used for selection.

    "},{"location":"plugins/version-source/reference/#hatchling.version.source.plugin.interface.VersionSourceInterface.root","title":"root: str property","text":"

    The root of the project tree as a string.

    "},{"location":"plugins/version-source/reference/#hatchling.version.source.plugin.interface.VersionSourceInterface.config","title":"config: dict property","text":"pyproject.toml hatch.toml
    [tool.hatch.version]\n
    [version]\n
    "},{"location":"plugins/version-source/reference/#hatchling.version.source.plugin.interface.VersionSourceInterface.get_version_data","title":"get_version_data() -> dict abstractmethod","text":"

    This should return a mapping with a version key representing the current version of the project and will be displayed when invoking the version command without any arguments.

    The mapping can contain anything else and will be passed to set_version when updating the version.

    Source code in backend/src/hatchling/version/source/plugin/interface.py
    @abstractmethod\ndef get_version_data(self) -> dict:\n    \"\"\"\n    This should return a mapping with a `version` key representing the current version of the project and will be\n    displayed when invoking the [`version`](../../cli/reference.md#hatch-version) command without any arguments.\n\n    The mapping can contain anything else and will be passed to\n    [set_version](reference.md#hatchling.version.source.plugin.interface.VersionSourceInterface.set_version)\n    when updating the version.\n    \"\"\"\n
    "},{"location":"plugins/version-source/reference/#hatchling.version.source.plugin.interface.VersionSourceInterface.set_version","title":"set_version(version: str, version_data: dict) -> None","text":"

    This should update the version to the first argument with the data provided during retrieval.

    Source code in backend/src/hatchling/version/source/plugin/interface.py
    def set_version(self, version: str, version_data: dict) -> None:\n    \"\"\"\n    This should update the version to the first argument with the data provided during retrieval.\n    \"\"\"\n    raise NotImplementedError\n
    "},{"location":"plugins/version-source/regex/","title":"Regex version source","text":"

    See the documentation for versioning.

    "},{"location":"plugins/version-source/regex/#updates","title":"Updates","text":"

    Setting the version is supported.

    "},{"location":"plugins/version-source/regex/#configuration","title":"Configuration","text":"

    The version source plugin name is regex.

    pyproject.toml hatch.toml
    [tool.hatch.version]\nsource = \"regex\"\n
    [version]\nsource = \"regex\"\n
    "},{"location":"plugins/version-source/regex/#options","title":"Options","text":"Option Description path (required) A relative path to a file containing the project's version pattern A regular expression that has a named group called version that represents the version. The default pattern looks for a variable named __version__ or VERSION that is set to a string containing the version, optionally prefixed with the lowercase letter v."},{"location":"tutorials/environment/basic-usage/","title":"Managing environments","text":"

    Hatch environments are isolated workspaces that can be used for project tasks including running tests, building documentation and running code formatters and linters.

    "},{"location":"tutorials/environment/basic-usage/#the-default-environment","title":"The default environment","text":"

    When you start using Hatch, you can create the default environment. To do this use the env create command:

    hatch env create\n

    This will not only create will the default environment for you to work in but will also install your project in dev mode in this default environment.

    Tip

    You never need to manually create environments as spawning a shell or running commands within one will automatically trigger creation.

    "},{"location":"tutorials/environment/basic-usage/#using-the-default-environment","title":"Using the default environment","text":"

    Hatch will always use the default environment if an environment is not chosen explicitly when running a command.

    For instance, the following shows how to get version information for the Python in use.

    $ hatch run python -V\nPython 3.12.1\n
    "},{"location":"tutorials/environment/basic-usage/#configure-the-default-environment","title":"Configure the default environment","text":"

    You can customize the tools that are installed into the default environment by adding a table called tool.hatch.envs.default to your pyproject.toml file. Below is an example of adding the dependencies pydantic and numpy to the default environment.

    pyproject.toml hatch.toml
    [tool.hatch.envs.default]\ndependencies = [\n  \"pydantic\",\n  \"numpy\",\n]\n
    [envs.default]\ndependencies = [\n  \"pydantic\",\n  \"numpy\",\n]\n

    You can declare versions for your dependencies as well within this configuration.

    pyproject.toml hatch.toml
    [tool.hatch.envs.default]\ndependencies = [\n  \"pydantic>=2.0\",\n  \"numpy\",\n]\n
    [envs.default]\ndependencies = [\n  \"pydantic>=2.0\",\n  \"numpy\",\n]\n
    "},{"location":"tutorials/environment/basic-usage/#create-custom-environment","title":"Create custom environment","text":"

    You can create custom environments in Hatch by adding a section to your pyproject.toml file [tool.hatch.envs.<ENV_NAME>]. Below you define an environment called test and you add the pytest and pytest-cov dependencies to that environment's configuration.

    pyproject.toml hatch.toml
    [tool.hatch.envs.test]\ndependencies = [\n  \"pytest\",\n  \"pytest-cov\"\n]\n
    [envs.test]\ndependencies = [\n  \"pytest\",\n  \"pytest-cov\"\n]\n

    The first time that you call the test environment, Hatch will:

    1. Create the environment
    2. Install your project into that environment in dev mode (by default) along with its dependencies.
    3. Install the environment's dependencies
    "},{"location":"tutorials/environment/basic-usage/#run-commands-within-a-specific-environment","title":"Run commands within a specific environment","text":"

    Hatch offers a unique environment feature that allows you run a specific command within a specific environment rather than needing to activate the environment as you would using a tool such as Conda or venv.

    For instance, if you define an environment called test that contains the dependencies from the previous section, you can run the pytest command from the test environment using the syntax:

    hatch run <ENV_NAME>:command\n

    To access the test environment and run pytest, you can run:

    $ hatch run test:pytest\n============================== test session starts ===============================\nplatform darwin -- Python 3.12.1, pytest-7.4.4, pluggy-1.3.0\nrootdir: /your/path/to/yourproject\ncollected 0 items\n

    Note

    test:pytest represents the name of the environment to call (test) and the command to run (pytest).

    "},{"location":"tutorials/environment/basic-usage/#view-current-environments","title":"View current environments","text":"

    Above you defined and created a new test environment in your pyproject.toml file. You can now use the env show command to see both the currently created environments and the dependencies in each environment.

    $ hatch env show\n             Standalone\n\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2533\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2533\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513\n\u2503 Name    \u2503 Type    \u2503 Dependencies \u2503\n\u2521\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2547\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2547\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2529\n\u2502 default \u2502 virtual \u2502              \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 test    \u2502 virtual \u2502 pytest       \u2502\n\u2502         \u2502         \u2502 pytest-cov   \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n

    Note

    The output may have more columns depending on your environment configuration.

    "},{"location":"tutorials/environment/basic-usage/#locating-environments","title":"Locating environments","text":"

    To see where your current environment is located you can use the env find command.

    $ hatch env find test\n/your/path/Application Support/hatch/env/virtual/yourproject/twO2iQR3/test\n

    Note

    That path is what you would see on macOS but differs for each platform, and is configurable.

    "},{"location":"tutorials/environment/basic-usage/#launching-a-shell-within-a-specific-environment","title":"Launching a shell within a specific environment","text":"

    If you wish to launch a shell for a specific environment that you have created, like the previous test environment, you can use:

    hatch -e test shell\n

    Once the environment is active, you can run commands like you would in any Python environment.

    Notice below that when running pip list in the test environment, you can see:

    1. That you package is installed in editable mode.
    2. That the environment contains both pytest and pytest-cov as specified above in the pyproject.toml file.
    $ pip list\nPackage     Version Editable project location\n----------- ------- ----------------------------------------------------\ncoverage    7.4.1\niniconfig   2.0.0\npackaging   23.2\npip         23.3.1\npluggy      1.4.0\npytest      8.0.0\npytest-cov  4.1.0\nyourproject 0.1.0  /your/path/to/yourproject\n
    "},{"location":"tutorials/environment/basic-usage/#conda-environments","title":"Conda environments","text":"

    If you prefer to use Conda environments with Hatch, you can check out the hatch-conda plugin.

    "},{"location":"tutorials/python/manage/","title":"Managing Python distributions","text":"

    The python command group provides a set of commands to manage Python distributions that may be used by other tools.

    Note

    When using environments, manual management is not necessary since by default Hatch will automatically download and manage Python distributions internally when a requested version cannot be found.

    "},{"location":"tutorials/python/manage/#location","title":"Location","text":"

    There are two ways to control where Python distributions are installed. Both methods make it so that each installed distribution is placed in a subdirectory of the configured location named after the distribution.

    1. The globally configured default directory for Python installations.
    2. The -d/--dir option of every python subcommand, which takes precedence over the default directory.
    "},{"location":"tutorials/python/manage/#installation","title":"Installation","text":"

    To install a Python distribution, use the python install command. For example:

    hatch python install 3.12\n

    This will:

    1. Download the 3.12 Python distribution
    2. Unpack it into a directory named 3.12 within the configured default directory for Python installations
    3. Add the installation to the user PATH

    Now its python executable can be used by you or other tools.

    Note

    For PATH changes to take effect in the current shell, you will need to restart it.

    "},{"location":"tutorials/python/manage/#multiple","title":"Multiple","text":"

    You can install multiple Python distributions at once by providing multiple distribution names. For example:

    hatch python install 3.12 3.11 pypy3.10\n

    If you would like to install all available Python distributions that are compatible with your system, use all as the distribution name:

    hatch python install all\n

    Tip

    The commands for updating and removing also support this functionality.

    "},{"location":"tutorials/python/manage/#private","title":"Private","text":"

    By default, installing Python distributions will add them to the user PATH. To disable this behavior, use the --private flag like so:

    hatch python install 3.12 --private\n

    This when combined with the directory option can be used to create private, isolated installations.

    "},{"location":"tutorials/python/manage/#listing-distributions","title":"Listing distributions","text":"

    You can see all of the available and installed Python distributions by using the python show command. For example, if you already installed the 3.12 distribution you may see something like this:

    $ hatch python show\n    Installed\n\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2533\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513\n\u2503 Name \u2503 Version \u2503\n\u2521\u2501\u2501\u2501\u2501\u2501\u2501\u2547\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2529\n\u2502 3.12 \u2502 3.12.7  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n      Available\n\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2533\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513\n\u2503 Name     \u2503 Version \u2503\n\u2521\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2547\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2529\n\u2502 3.7      \u2502 3.7.9   \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 3.8      \u2502 3.8.20  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 3.9      \u2502 3.9.20  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 3.10     \u2502 3.10.15 \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 3.11     \u2502 3.11.10 \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 3.13     \u2502 3.13.0  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 pypy2.7  \u2502 7.3.15  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 pypy3.9  \u2502 7.3.15  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 pypy3.10 \u2502 7.3.15  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
    "},{"location":"tutorials/python/manage/#finding-installations","title":"Finding installations","text":"

    The Python executable of an installed distribution can be found by using the python find command. For example:

    $ hatch python find 3.12\n/home/.local/share/hatch/pythons/3.12/python/bin/python3\n

    You can instead output its parent directory by using the -p/--parent flag:

    $ hatch python find 3.12 --parent\n/home/.local/share/hatch/pythons/3.12/python/bin\n

    This is useful when other tools do not need to use the executable directly but require knowing the directory containing it.

    "},{"location":"tutorials/python/manage/#updates","title":"Updates","text":"

    To update installed Python distributions, use the python update command. For example:

    hatch python update 3.12 3.11 pypy3.10\n

    When there are no updates available for a distribution, a warning will be displayed:

    $ hatch python update 3.12\nThe latest version is already installed: 3.12.3\n
    "},{"location":"tutorials/python/manage/#removal","title":"Removal","text":"

    To remove installed Python distributions, use the python remove command. For example:

    hatch python remove 3.12 3.11 pypy3.10\n
    "},{"location":"tutorials/testing/overview/","title":"Testing projects","text":"

    The test command (by default) uses pytest with select plugins and coverage.py. View the testing configuration for more information.

    The majority of projects can be fully tested this way without the need for custom environments.

    "},{"location":"tutorials/testing/overview/#passing-arguments","title":"Passing arguments","text":"

    When you run the test command without any arguments, tests is passed as the default argument to pytest (this assumes that you have a tests directory). For example, the following command invocation:

    hatch test\n

    would be translated roughly to:

    pytest tests\n

    You can pass arguments to pytest by appending them to the test command. For example, the following command invocation:

    hatch test -vv tests/test_foo.py::test_bar\n

    would be translated roughly to:

    pytest -vv tests/test_foo.py::test_bar\n

    You can force the treatment of arguments as positional by using the -- separator, especially useful when built-in flags of the test command conflict with those of pytest, such as the --help flag. For example, the following command invocation:

    hatch test -r -- -r fE -- tests\n

    would be translated roughly to:

    pytest -r fE -- tests\n

    Note

    It's important to ensure that pytest receives an argument instructing what to run/where to locate tests. It's default behavior is . meaning that it will exhaustively search for tests in the current directory. This can not just be slow but also lead to unexpected behavior.

    "},{"location":"tutorials/testing/overview/#environment-selection","title":"Environment selection","text":""},{"location":"tutorials/testing/overview/#single-environment","title":"Single environment","text":"

    If no environment options are selected, the test command will only run tests in the first defined environment that either already exists or is compatible. Additionally, the checking order will prioritize environments that define a version of Python that matches the interpreter that Hatch is running on.

    For example, if you overrode the default matrix as follows:

    pyproject.toml hatch.toml
    [[tool.hatch.envs.hatch-test.matrix]]\npython = [\"3.12\", \"3.11\"]\n\n[[tool.hatch.envs.hatch-test.matrix]]\npython = [\"3.11\"]\nfeature = [\"foo\", \"bar\"]\n
    [[envs.hatch-test.matrix]]\npython = [\"3.12\", \"3.11\"]\n\n[[envs.hatch-test.matrix]]\npython = [\"3.11\"]\nfeature = [\"foo\", \"bar\"]\n

    the expanded environments would normally be:

    hatch-test.py3.12\nhatch-test.py3.11\nhatch-test.py3.11-foo\nhatch-test.py3.11-bar\n

    If you install Hatch on Python 3.11, the checking order would be:

    hatch-test.py3.11\nhatch-test.py3.11-foo\nhatch-test.py3.11-bar\nhatch-test.py3.12\n

    Note

    If you installed Hatch with an official installer or are using one of the standalone binaries, the version of Python that Hatch runs on is out of your control. If you are relying on the single environment resolution behavior, consider explicitly selecting environments based on the Python version instead.

    "},{"location":"tutorials/testing/overview/#all-environments","title":"All environments","text":"

    You can run tests in all compatible environments by using the --all flag. For example, say you defined the matrix and overrides as follows:

    pyproject.toml hatch.toml
    [[tool.hatch.envs.hatch-test.matrix]]\npython = [\"3.12\", \"3.11\"]\nfeature = [\"foo\", \"bar\"]\n\n[tool.hatch.envs.hatch-test.overrides]\nmatrix.feature.platforms = [\n  { value = \"linux\", if = [\"foo\", \"bar\"] },\n  { value = \"windows\", if = [\"foo\"] },\n  { value = \"macos\", if = [\"bar\"] },\n]\n
    [[envs.hatch-test.matrix]]\npython = [\"3.12\", \"3.11\"]\nfeature = [\"foo\", \"bar\"]\n\n[envs.hatch-test.overrides]\nmatrix.feature.platforms = [\n  { value = \"linux\", if = [\"foo\", \"bar\"] },\n  { value = \"windows\", if = [\"foo\"] },\n  { value = \"macos\", if = [\"bar\"] },\n]\n

    The following table shows the environments in which tests would be run:

    Environment Linux Windows macOS hatch-test.py3.12-foo hatch-test.py3.12-bar hatch-test.py3.11-foo hatch-test.py3.11-bar"},{"location":"tutorials/testing/overview/#specific-environments","title":"Specific environments","text":"

    You can select subsets of environments by using the --include/-i and --exclude/-x options. These options may be used to include or exclude certain matrix variables, optionally followed by specific comma-separated values, and may be selected multiple times.

    For example, say you defined the matrix as follows:

    pyproject.toml hatch.toml
    [[tool.hatch.envs.hatch-test.matrix]]\npython = [\"3.12\", \"3.11\"]\nfeature = [\"foo\", \"bar\", \"baz\"]\n
    [[envs.hatch-test.matrix]]\npython = [\"3.12\", \"3.11\"]\nfeature = [\"foo\", \"bar\", \"baz\"]\n

    If you wanted to run tests in all environments that have Python 3.12 and either the foo or bar feature, you could use the following command invocation:

    hatch test -i python=3.12 -i feature=foo,bar\n

    Alternatively, we could exclude the baz feature to achieve the same result:

    hatch test -i python=3.12 -x feature=baz\n

    Tip

    Since selecting the version of Python is a common use case, you can use the --python/-py option as a shorthand. For example, the previous commands could have been written as:

    hatch test -py 3.12 -i feature=foo,bar\nhatch test -py 3.12 -x feature=baz\n
    "},{"location":"tutorials/testing/overview/#measuring-code-coverage","title":"Measuring code coverage","text":"

    You can enable code coverage by using the --cover flag. For example, the following command invocation:

    hatch test --cover\n

    would be translated roughly to:

    coverage run -m pytest tests\n

    After tests run in all of the selected environments, the coverage data is combined and a report is shown. The --cover-quiet flag can be used to suppress the report and implicitly enables the --cover flag:

    hatch test --cover-quiet\n

    Note

    Coverage data files are generated at the root of the project. Be sure to exclude them from version control with the following glob-style pattern:

    .coverage*\n
    "},{"location":"tutorials/testing/overview/#retry-failed-tests","title":"Retry failed tests","text":"

    You can retry failed tests with the --retries option:

    hatch test --retries 2\n

    If a test fails every time and the number of retries is set to 2, the test will be run a total of three times.

    You can also set the number of seconds to wait between retries with the --retry-delay option:

    hatch test --retries 2 --retry-delay 1\n
    "},{"location":"tutorials/testing/overview/#parallelize-test-execution","title":"Parallelize test execution","text":"

    You can parallelize test execution with the --parallel/-p flag:

    hatch test --parallel\n

    This distributes tests within an environment across multiple workers. The number of workers corresponds to the number of logical rather than physical CPUs that are available.

    "},{"location":"tutorials/testing/overview/#randomize-test-order","title":"Randomize test order","text":"

    You can randomize the order of tests with the --randomize/-r flag:

    hatch test --randomize\n
    "},{"location":"blog/archive/2024/","title":"2024","text":""},{"location":"blog/archive/2023/","title":"2023","text":""},{"location":"blog/archive/2022/","title":"2022","text":""},{"location":"blog/category/release/","title":"Release","text":""}]} \ No newline at end of file diff --git a/1.13/sitemap.xml b/1.13/sitemap.xml new file mode 100644 index 000000000..d4ab5d2c4 --- /dev/null +++ b/1.13/sitemap.xml @@ -0,0 +1,307 @@ + + + + https://hatch.pypa.io/1.13/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/build/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/environment/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/install/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/intro/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/next-steps/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/publish/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/version/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/why/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/blog/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/blog/2024/05/02/hatch-v1100/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/blog/2022/10/08/hatch-v160/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/blog/2023/12/11/hatch-v180/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/blog/2023/12/18/hatch-v190/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/cli/about/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/cli/reference/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/community/contributing/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/community/highlights/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/community/users/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/build/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/context/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/dependency/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/hatch/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/metadata/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/project-templates/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/environment/advanced/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/environment/overview/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/internal/static-analysis/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/config/internal/testing/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/history/hatch/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/history/hatchling/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/config/dynamic-metadata/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/environment/dependency-resolution/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/environment/select-installer/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/integrate/vscode/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/meta/report-issues/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/plugins/testing-builds/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/publish/auth/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/publish/repo/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/python/custom/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/run/python-scripts/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/how-to/static-analysis/behavior/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/meta/authors/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/meta/faq/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/about/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/utilities/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/build-hook/custom/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/build-hook/reference/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/build-hook/version/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/builder/binary/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/builder/custom/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/builder/reference/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/builder/sdist/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/builder/wheel/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/environment/reference/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/environment/virtual/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/environment-collector/custom/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/environment-collector/default/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/environment-collector/reference/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/metadata-hook/custom/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/metadata-hook/reference/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/publisher/package-index/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/publisher/reference/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/version-scheme/reference/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/version-scheme/standard/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/version-source/code/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/version-source/env/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/version-source/reference/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/plugins/version-source/regex/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/tutorials/environment/basic-usage/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/tutorials/python/manage/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/tutorials/testing/overview/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/blog/archive/2024/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/blog/archive/2023/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/blog/archive/2022/ + 2020-02-02 + + + https://hatch.pypa.io/1.13/blog/category/release/ + 2020-02-02 + + \ No newline at end of file diff --git a/1.13/sitemap.xml.gz b/1.13/sitemap.xml.gz new file mode 100644 index 000000000..12d27dd07 Binary files /dev/null and b/1.13/sitemap.xml.gz differ diff --git a/1.13/tutorials/environment/basic-usage/index.html b/1.13/tutorials/environment/basic-usage/index.html new file mode 100644 index 000000000..16e2453f4 --- /dev/null +++ b/1.13/tutorials/environment/basic-usage/index.html @@ -0,0 +1,75 @@ + Managing environments - Hatch

    Managing environments


    Hatch environments are isolated workspaces that can be used for project tasks including running tests, building documentation and running code formatters and linters.

    The default environment

    When you start using Hatch, you can create the default environment. To do this use the env create command:

    hatch env create
    +

    This will not only create will the default environment for you to work in but will also install your project in dev mode in this default environment.

    Tip

    You never need to manually create environments as spawning a shell or running commands within one will automatically trigger creation.

    Using the default environment

    Hatch will always use the default environment if an environment is not chosen explicitly when running a command.

    For instance, the following shows how to get version information for the Python in use.

    $ hatch run python -V
    +Python 3.12.1
    +

    Configure the default environment

    You can customize the tools that are installed into the default environment by adding a table called tool.hatch.envs.default to your pyproject.toml file. Below is an example of adding the dependencies pydantic and numpy to the default environment.

    [tool.hatch.envs.default]
    +dependencies = [
    +  "pydantic",
    +  "numpy",
    +]
    +
    [envs.default]
    +dependencies = [
    +  "pydantic",
    +  "numpy",
    +]
    +

    You can declare versions for your dependencies as well within this configuration.

    [tool.hatch.envs.default]
    +dependencies = [
    +  "pydantic>=2.0",
    +  "numpy",
    +]
    +
    [envs.default]
    +dependencies = [
    +  "pydantic>=2.0",
    +  "numpy",
    +]
    +

    Create custom environment

    You can create custom environments in Hatch by adding a section to your pyproject.toml file [tool.hatch.envs.<ENV_NAME>]. Below you define an environment called test and you add the pytest and pytest-cov dependencies to that environment's configuration.

    [tool.hatch.envs.test]
    +dependencies = [
    +  "pytest",
    +  "pytest-cov"
    +]
    +
    [envs.test]
    +dependencies = [
    +  "pytest",
    +  "pytest-cov"
    +]
    +

    The first time that you call the test environment, Hatch will:

    1. Create the environment
    2. Install your project into that environment in dev mode (by default) along with its dependencies.
    3. Install the environment's dependencies

    Run commands within a specific environment

    Hatch offers a unique environment feature that allows you run a specific command within a specific environment rather than needing to activate the environment as you would using a tool such as Conda or venv.

    For instance, if you define an environment called test that contains the dependencies from the previous section, you can run the pytest command from the test environment using the syntax:

    hatch run <ENV_NAME>:command
    +

    To access the test environment and run pytest, you can run:

    $ hatch run test:pytest
    +============================== test session starts ===============================
    +platform darwin -- Python 3.12.1, pytest-7.4.4, pluggy-1.3.0
    +rootdir: /your/path/to/yourproject
    +collected 0 items
    +

    Note

    test:pytest represents the name of the environment to call (test) and the command to run (pytest).

    View current environments

    Above you defined and created a new test environment in your pyproject.toml file. You can now use the env show command to see both the currently created environments and the dependencies in each environment.

    $ hatch env show
    +             Standalone
    +┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┓
    +┃ Name    ┃ Type    ┃ Dependencies ┃
    +┡━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━┩
    +│ default │ virtual │              │
    +├─────────┼─────────┼──────────────┤
    +│ test    │ virtual │ pytest       │
    +│         │         │ pytest-cov   │
    +└─────────┴─────────┴──────────────┘
    +

    Note

    The output may have more columns depending on your environment configuration.

    Locating environments

    To see where your current environment is located you can use the env find command.

    $ hatch env find test
    +/your/path/Application Support/hatch/env/virtual/yourproject/twO2iQR3/test
    +

    Note

    That path is what you would see on macOS but differs for each platform, and is configurable.

    Launching a shell within a specific environment

    If you wish to launch a shell for a specific environment that you have created, like the previous test environment, you can use:

    hatch -e test shell
    +

    Once the environment is active, you can run commands like you would in any Python environment.

    Notice below that when running pip list in the test environment, you can see:

    1. That you package is installed in editable mode.
    2. That the environment contains both pytest and pytest-cov as specified above in the pyproject.toml file.
    $ pip list
    +Package     Version Editable project location
    +----------- ------- ----------------------------------------------------
    +coverage    7.4.1
    +iniconfig   2.0.0
    +packaging   23.2
    +pip         23.3.1
    +pluggy      1.4.0
    +pytest      8.0.0
    +pytest-cov  4.1.0
    +yourproject 0.1.0  /your/path/to/yourproject
    +

    Conda environments

    If you prefer to use Conda environments with Hatch, you can check out the hatch-conda plugin.

    \ No newline at end of file diff --git a/1.13/tutorials/python/manage/index.html b/1.13/tutorials/python/manage/index.html new file mode 100644 index 000000000..6488f0581 --- /dev/null +++ b/1.13/tutorials/python/manage/index.html @@ -0,0 +1,53 @@ + Managing Python distributions - Hatch

    Managing Python distributions


    The python command group provides a set of commands to manage Python distributions that may be used by other tools.

    Note

    When using environments, manual management is not necessary since by default Hatch will automatically download and manage Python distributions internally when a requested version cannot be found.

    Location

    There are two ways to control where Python distributions are installed. Both methods make it so that each installed distribution is placed in a subdirectory of the configured location named after the distribution.

    1. The globally configured default directory for Python installations.
    2. The -d/--dir option of every python subcommand, which takes precedence over the default directory.

    Installation

    To install a Python distribution, use the python install command. For example:

    hatch python install 3.12
    +

    This will:

    1. Download the 3.12 Python distribution
    2. Unpack it into a directory named 3.12 within the configured default directory for Python installations
    3. Add the installation to the user PATH

    Now its python executable can be used by you or other tools.

    Note

    For PATH changes to take effect in the current shell, you will need to restart it.

    Multiple

    You can install multiple Python distributions at once by providing multiple distribution names. For example:

    hatch python install 3.12 3.11 pypy3.10
    +

    If you would like to install all available Python distributions that are compatible with your system, use all as the distribution name:

    hatch python install all
    +

    Tip

    The commands for updating and removing also support this functionality.

    Private

    By default, installing Python distributions will add them to the user PATH. To disable this behavior, use the --private flag like so:

    hatch python install 3.12 --private
    +

    This when combined with the directory option can be used to create private, isolated installations.

    Listing distributions

    You can see all of the available and installed Python distributions by using the python show command. For example, if you already installed the 3.12 distribution you may see something like this:

    $ hatch python show
    +    Installed
    +┏━━━━━━┳━━━━━━━━━┓
    +┃ Name ┃ Version ┃
    +┡━━━━━━╇━━━━━━━━━┩
    +│ 3.12 │ 3.12.7  │
    +└──────┴─────────┘
    +      Available
    +┏━━━━━━━━━━┳━━━━━━━━━┓
    +┃ Name     ┃ Version ┃
    +┡━━━━━━━━━━╇━━━━━━━━━┩
    +│ 3.7      │ 3.7.9   │
    +├──────────┼─────────┤
    +│ 3.8      │ 3.8.20  │
    +├──────────┼─────────┤
    +│ 3.9      │ 3.9.20  │
    +├──────────┼─────────┤
    +│ 3.10     │ 3.10.15 │
    +├──────────┼─────────┤
    +│ 3.11     │ 3.11.10 │
    +├──────────┼─────────┤
    +│ 3.13     │ 3.13.0  │
    +├──────────┼─────────┤
    +│ pypy2.7  │ 7.3.15  │
    +├──────────┼─────────┤
    +│ pypy3.9  │ 7.3.15  │
    +├──────────┼─────────┤
    +│ pypy3.10 │ 7.3.15  │
    +└──────────┴─────────┘
    +

    Finding installations

    The Python executable of an installed distribution can be found by using the python find command. For example:

    $ hatch python find 3.12
    +/home/.local/share/hatch/pythons/3.12/python/bin/python3
    +

    You can instead output its parent directory by using the -p/--parent flag:

    $ hatch python find 3.12 --parent
    +/home/.local/share/hatch/pythons/3.12/python/bin
    +

    This is useful when other tools do not need to use the executable directly but require knowing the directory containing it.

    Updates

    To update installed Python distributions, use the python update command. For example:

    hatch python update 3.12 3.11 pypy3.10
    +

    When there are no updates available for a distribution, a warning will be displayed:

    $ hatch python update 3.12
    +The latest version is already installed: 3.12.3
    +

    Removal

    To remove installed Python distributions, use the python remove command. For example:

    hatch python remove 3.12 3.11 pypy3.10
    +
    \ No newline at end of file diff --git a/1.13/tutorials/testing/overview/index.html b/1.13/tutorials/testing/overview/index.html new file mode 100644 index 000000000..066cd7145 --- /dev/null +++ b/1.13/tutorials/testing/overview/index.html @@ -0,0 +1,76 @@ + Testing projects - Hatch

    Testing projects


    The test command (by default) uses pytest with select plugins and coverage.py. View the testing configuration for more information.

    The majority of projects can be fully tested this way without the need for custom environments.

    Passing arguments

    When you run the test command without any arguments, tests is passed as the default argument to pytest (this assumes that you have a tests directory). For example, the following command invocation:

    hatch test
    +

    would be translated roughly to:

    pytest tests
    +

    You can pass arguments to pytest by appending them to the test command. For example, the following command invocation:

    hatch test -vv tests/test_foo.py::test_bar
    +

    would be translated roughly to:

    pytest -vv tests/test_foo.py::test_bar
    +

    You can force the treatment of arguments as positional by using the -- separator, especially useful when built-in flags of the test command conflict with those of pytest, such as the --help flag. For example, the following command invocation:

    hatch test -r -- -r fE -- tests
    +

    would be translated roughly to:

    pytest -r fE -- tests
    +

    Note

    It's important to ensure that pytest receives an argument instructing what to run/where to locate tests. It's default behavior is . meaning that it will exhaustively search for tests in the current directory. This can not just be slow but also lead to unexpected behavior.

    Environment selection

    Single environment

    If no environment options are selected, the test command will only run tests in the first defined environment that either already exists or is compatible. Additionally, the checking order will prioritize environments that define a version of Python that matches the interpreter that Hatch is running on.

    For example, if you overrode the default matrix as follows:

    [[tool.hatch.envs.hatch-test.matrix]]
    +python = ["3.12", "3.11"]
    +
    +[[tool.hatch.envs.hatch-test.matrix]]
    +python = ["3.11"]
    +feature = ["foo", "bar"]
    +
    [[envs.hatch-test.matrix]]
    +python = ["3.12", "3.11"]
    +
    +[[envs.hatch-test.matrix]]
    +python = ["3.11"]
    +feature = ["foo", "bar"]
    +

    the expanded environments would normally be:

    hatch-test.py3.12
    +hatch-test.py3.11
    +hatch-test.py3.11-foo
    +hatch-test.py3.11-bar
    +

    If you install Hatch on Python 3.11, the checking order would be:

    hatch-test.py3.11
    +hatch-test.py3.11-foo
    +hatch-test.py3.11-bar
    +hatch-test.py3.12
    +

    Note

    If you installed Hatch with an official installer or are using one of the standalone binaries, the version of Python that Hatch runs on is out of your control. If you are relying on the single environment resolution behavior, consider explicitly selecting environments based on the Python version instead.

    All environments

    You can run tests in all compatible environments by using the --all flag. For example, say you defined the matrix and overrides as follows:

    [[tool.hatch.envs.hatch-test.matrix]]
    +python = ["3.12", "3.11"]
    +feature = ["foo", "bar"]
    +
    +[tool.hatch.envs.hatch-test.overrides]
    +matrix.feature.platforms = [
    +  { value = "linux", if = ["foo", "bar"] },
    +  { value = "windows", if = ["foo"] },
    +  { value = "macos", if = ["bar"] },
    +]
    +
    [[envs.hatch-test.matrix]]
    +python = ["3.12", "3.11"]
    +feature = ["foo", "bar"]
    +
    +[envs.hatch-test.overrides]
    +matrix.feature.platforms = [
    +  { value = "linux", if = ["foo", "bar"] },
    +  { value = "windows", if = ["foo"] },
    +  { value = "macos", if = ["bar"] },
    +]
    +

    The following table shows the environments in which tests would be run:

    Environment Linux Windows macOS
    hatch-test.py3.12-foo ✅ ✅ ❌
    hatch-test.py3.12-bar ✅ ❌ ✅
    hatch-test.py3.11-foo ✅ ✅ ❌
    hatch-test.py3.11-bar ✅ ❌ ✅

    Specific environments

    You can select subsets of environments by using the --include/-i and --exclude/-x options. These options may be used to include or exclude certain matrix variables, optionally followed by specific comma-separated values, and may be selected multiple times.

    For example, say you defined the matrix as follows:

    [[tool.hatch.envs.hatch-test.matrix]]
    +python = ["3.12", "3.11"]
    +feature = ["foo", "bar", "baz"]
    +
    [[envs.hatch-test.matrix]]
    +python = ["3.12", "3.11"]
    +feature = ["foo", "bar", "baz"]
    +

    If you wanted to run tests in all environments that have Python 3.12 and either the foo or bar feature, you could use the following command invocation:

    hatch test -i python=3.12 -i feature=foo,bar
    +

    Alternatively, we could exclude the baz feature to achieve the same result:

    hatch test -i python=3.12 -x feature=baz
    +

    Tip

    Since selecting the version of Python is a common use case, you can use the --python/-py option as a shorthand. For example, the previous commands could have been written as:

    hatch test -py 3.12 -i feature=foo,bar
    +hatch test -py 3.12 -x feature=baz
    +

    Measuring code coverage

    You can enable code coverage by using the --cover flag. For example, the following command invocation:

    hatch test --cover
    +

    would be translated roughly to:

    coverage run -m pytest tests
    +

    After tests run in all of the selected environments, the coverage data is combined and a report is shown. The --cover-quiet flag can be used to suppress the report and implicitly enables the --cover flag:

    hatch test --cover-quiet
    +

    Note

    Coverage data files are generated at the root of the project. Be sure to exclude them from version control with the following glob-style pattern:

    .coverage*
    +

    Retry failed tests

    You can retry failed tests with the --retries option:

    hatch test --retries 2
    +

    If a test fails every time and the number of retries is set to 2, the test will be run a total of three times.

    You can also set the number of seconds to wait between retries with the --retry-delay option:

    hatch test --retries 2 --retry-delay 1
    +

    Parallelize test execution

    You can parallelize test execution with the --parallel/-p flag:

    hatch test --parallel
    +

    This distributes tests within an environment across multiple workers. The number of workers corresponds to the number of logical rather than physical CPUs that are available.

    Randomize test order

    You can randomize the order of tests with the --randomize/-r flag:

    hatch test --randomize
    +
    \ No newline at end of file diff --git a/1.13/users/index.html b/1.13/users/index.html new file mode 100644 index 000000000..14a0324ea --- /dev/null +++ b/1.13/users/index.html @@ -0,0 +1,15 @@ + + + + + + Redirecting... + + + + + + +Redirecting... + + diff --git a/1.13/version/index.html b/1.13/version/index.html new file mode 100644 index 000000000..caa133f66 --- /dev/null +++ b/1.13/version/index.html @@ -0,0 +1,36 @@ + Versioning - Hatch

    Versioning


    Configuration

    When the version is not statically set, configuration is defined in the tool.hatch.version table. The source option determines the source to use for retrieving and updating the version. The regex source is used by default.

    The regex source requires an option path that represents a relative path to a file containing the project's version:

    [tool.hatch.version]
    +path = "src/hatch_demo/__about__.py"
    +
    [version]
    +path = "src/hatch_demo/__about__.py"
    +

    The default pattern looks for a variable named __version__ or VERSION that is set to a string containing the version, optionally prefixed with the lowercase letter v.

    If this doesn't reflect how you store the version, you can define a different regular expression using the pattern option:

    [tool.hatch.version]
    +path = "pkg/__init__.py"
    +pattern = "BUILD = 'b(?P<version>[^']+)'"
    +
    [version]
    +path = "pkg/__init__.py"
    +pattern = "BUILD = 'b(?P<version>[^']+)'"
    +

    The pattern must have a named group called version that represents the version.

    Display

    Invoking the version command without any arguments will display the current version of the project:

    $ hatch version
    +0.0.1
    +

    Updating

    You can update the version like so:

    $ hatch version "0.1.0"
    +Old: 0.0.1
    +New: 0.1.0
    +

    The scheme option determines the scheme to use for parsing both the existing and new versions. The standard scheme is used by default, which is based on PEP 440.

    Rather than setting the version explicitly, you can select the name of a segment used to increment the version:

    $ hatch version minor
    +Old: 0.1.0
    +New: 0.2.0
    +

    You can chain multiple segment updates with a comma. For example, if you wanted to release a preview of your project's first major version, you could do:

    $ hatch version major,rc
    +Old: 0.2.0
    +New: 1.0.0rc0
    +

    When you want to release the final version, you would do:

    $ hatch version release
    +Old: 1.0.0rc0
    +New: 1.0.0
    +

    Supported segments

    Here are the supported segments and how they would influence an existing version of 1.0.0:

    Segments New version
    release 1.0.0
    major 2.0.0
    minor 1.1.0
    micro
    patch
    fix
    1.0.1
    a
    alpha
    1.0.0a0
    b
    beta
    1.0.0b0
    c
    rc
    pre
    preview
    1.0.0rc0
    r
    rev
    post
    1.0.0.post0
    dev 1.0.0.dev0
    \ No newline at end of file diff --git a/1.13/why/index.html b/1.13/why/index.html new file mode 100644 index 000000000..69c909182 --- /dev/null +++ b/1.13/why/index.html @@ -0,0 +1,12 @@ + Why Hatch? - Hatch

    Why Hatch?


    The high level value proposition of Hatch is that if one adopts all functionality then many other tools become unnecessary since there is support for everything one might require. Further, if one chooses to use only specific features then there are still benefits compared to alternatives.

    Build backend

    Hatchling, the build backend sister project, has many benefits compared to setuptools. Here we only compare setuptools as that is the one most people are familiar with.

    • Better defaults: The default behavior for setuptools is often not desirable for the average user.
      • For source distributions, setuptools has a custom enumeration of files that get included and excluded by default. Hatchling takes the defaults from your version control system such as Git's .gitignore file.
      • For wheels, setuptools attempts to find every directory that looks like a Python package. This is often undesirable as you might ship files to the end-user unintentionally such as test or tooling directories. Hatchling defaults to very specific inclusion based on the project name and errors if no heuristic is satisfied.
    • Ease of configurability: Hatchling was designed based on a history of significant challenges when configuring setuptools.
      • Hatchling uses the same glob pattern syntax as Git itself for every option which is what most users are familiar with. On the other hand, setuptools uses shell-style glob patterns for source distributions while wheels use a mix of shell-style globs and Python package syntax.
      • Configuring what gets included in source distributions requires a separate MANIFEST.in file. The custom syntax and directives must be learned and it is difficult knowing which options in the main files like setup.py influence the behavior and under what conditions. For Hatchling, everything gets configured in a single file under dedicated sections for specific targets like [tool.hatch.build.targets.wheel].
      • By default, non-Python files are excluded from wheels. Including such files requires usually verbose rules for every nested package directory. Hatchling makes no such distinction between file types and acts more like a general build system one might already be familiar with.
    • Editable installations: The default behavior of Hatchling allows for proper static analysis by external tools such as IDEs. With setuptools, you must provide additional configuration which means that by default, for example, you would not get autocompletion in Visual Studio Code. This is marked as a legacy feature and may in fact be removed in future versions of setuptools.
    • Reproducibility: Hatchling builds reproducible wheels and source distributions by default. setuptools does not support this for source distributions and there is no guarantee that wheels are reproducible.
    • Extensibility: Although it is possible to extend setuptools, the API is quite low level. Hatchling has the concept of plugins that are separated into discrete types and only expose what is necessary, leading to an easier developer experience.

    Why not?:

    If building extension modules is required then it is recommended that you continue using setuptools, or even other backends that specialize in interfacing with compilers.

    Environment management

    Here we compare to both tox and nox. At a high level, there are a few common advantages:

    • Python management: Hatch is able to automatically download Python distributions on the fly when specific versions that environments request cannot be found. The alternatives will raise an error, with the option to ignore unknown distributions.
    • Philosophy: In the alternatives, environments are for the most part treated as executable units where a dependency set is associated with an action. If you are familiar with container ecosystems, this would be like defining a CMD at the end of a Dockerfile but without the ability to change the action at runtime. This involves significant wasted disk space usually because one often requires slight modifications to the actions and therefore will define entirely different environments inherited from a base config just to perform different logic. Additionally, this can be confusing to users not just configuration-wise but also for execution of the different environments.

      In Hatch, environments are treated as isolated areas where you can execute arbitrary commands at runtime. For example, you can define a single test environment with named scripts that runs unit vs non-unit tests, each command being potentially very long but named however you wish so you get to control the interface. Since environments are treated as places where work is performed, you can also spawn a shell into any which will execute a subprocess that automatically drops into your shell of choice. Your shell will be configured appropriately like python on PATH being updated and the prompt being changed to reflect the chosen environment.

    • Configuration:

      • nox config is defined in Python which often leads to increased verbosity and makes it challenging to onboard folks compared to a standardized format with known behaviors.
    • Extensibility:
      • tox allows for extending most aspects of its functionality however the API is so low-level and attached to internals that creating plugins may be challenging. For example, here is a tox plugin that was migrated to an equivalent Hatch environment collector plugin.
      • nox is configured with Python so for the local project you can do whatever you want, however there is no concept of third-party plugins per se. To achieve that, you must usually use a package that wraps nox and use that package's imports instead (example).

    Why not?:

    If you are using nox and you wish to migrate, and for some reason you notify sessions, then migration wouldn't be a straight translation but rather you might have to redesign that conditional step.

    Python management

    Here we compare Python management to that of pyenv.

    • Cross-platform: Hatch allows for the same experience no matter the system whereas pyenv does not support Windows so you must use an entirely different project that tries to emulate the functionality.
    • No build dependencies: Hatch guarantees that every available distribution is prebuilt whereas the alternative requires one to maintain a precise build environment which differs by platform and potentially Python version. Another benefit to this is extremely fast installations since the distributions are simply downloaded and unpacked.
    • Optimized by default: The CPython distributions are built with profile guided optimization and link-time optimization, resulting in a 10-30% performance improvement depending on the workload. These distributions have seen wide adoption throughout the industry and are even used by the build system Bazel.
    • Simplicity: Hatch treats Python installations as just another directory that one would add to PATH. It can do this for you or you can manage PATH yourself, even allowing for custom install locations. On the other hand, pyenv operates by adding shims which then act as wrappers around the actual underlying binaries. This has many unfortunate side effects:
      • It is incumbent upon the user to manage which specific Python comes first via the CLI, switch when necessary, and/or have a mental model of which versions are exposed globally and locally per-project. This can become confusing quite quickly. When working with Hatch, your global Python installations are only important insofar as they are on PATH somewhere since environments do not use them directly but rather create virtual environments from them, always using a version that is compatible with your project.
      • Configuration is required for each shell to properly set up pyenv on start, leading to inconsistencies when running processes that do not spawn a shell.
      • Debugging issues with Python search paths can be extremely difficult, especially for users of software. If you or users have ever ran into an issue where code was being executed that you did not anticipate, the issue is almost always pyenv influencing the python on PATH.

    Why not?:

    Currently, Hatch does not allow for the installation of specific patch release versions but rather only uses minor release granularity that tracks the latest patch release. If specific patch releases are important to you then it is best to use an alternative installation mechanism.

    \ No newline at end of file diff --git a/latest/404.html b/latest/404.html index 686290ad2..0a5e595b8 100644 --- a/latest/404.html +++ b/latest/404.html @@ -1 +1 @@ - Hatch

    404 - Not found

    \ No newline at end of file + Hatch

    404 - Not found

    \ No newline at end of file diff --git a/latest/blog/2022/10/08/hatch-v160/index.html b/latest/blog/2022/10/08/hatch-v160/index.html index 54a301786..0dd3e5916 100644 --- a/latest/blog/2022/10/08/hatch-v160/index.html +++ b/latest/blog/2022/10/08/hatch-v160/index.html @@ -1,4 +1,4 @@ - Hatch v1.6.0 - Hatch

    Hatch history


    All notable changes to Hatch will be documented in this file.

    The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

    Unreleased

    1.12.0 - 2024-05-28

    Changed:

    • The run/env run and test commands now treat inclusion variable options as an intersection rather than a union to allow for specific targeting of environments

    Added:

    • Add ability to control the source of Python distributions
    • Upgrade Ruff to 0.4.5
    • Upgrade PyApp to 0.22.0 for binary builds

    Fixed:

    • The fmt command no longer hides the commands that are being executed
    • Add default timeout for network requests, useful when installing Python distributions
    • Fix syntax highlighting contrast for the config show command

    1.11.1 - 2024-05-23

    Added:

    • Add official GitHub Action for installing Hatch

    Fixed:

    • Fix terminal.styles.spinner configuration
    • Fix entry points in the pre-built distributions that binaries use

    1.11.0 - 2024-05-14

    Added:

    • Upgrade PyApp to 0.21.1 for binary builds

    Fixed:

    • On Linux, install the highest compatible Python distribution variant based on CPU architecture rather than assuming recent hardware

    1.10.0 - 2024-05-02

    Changed:

    • The run/env run, fmt and shell commands now only change the current working directory to the project root if not already inside the project
    • The shell command now accepts a single argument to specify the environment to enter which overrides the standard choice mechanisms. The arguments determining shell options have been converted to flags.

    Added:

    • Add test command
    • The run command can now execute scripts that define inline metadata for dependencies and Python version constraints
    • The virtual environment type now supports the ability to use UV in place of pip & virtualenv
    • Add self report command for submitting pre-populated bug reports to GitHub
    • The reserved environment used for static analysis is now completely configurable
    • Add the following methods to the environment interface for complete control over output during life cycle management: app_status_creation, app_status_pre_installation, app_status_post_installation, app_status_project_installation, app_status_dependency_state_check, app_status_dependency_installation_check, app_status_dependency_synchronization
    • Add binaries for 32-bit versions of Windows
    • Read configuration from any ~/.pypirc file for the index publisher
    • Use the Git user as the default username for new project URL metadata
    • Add HATCH_DEBUG environment variable that when enabled will show local variables in the case of unhandled tracebacks
    • The env show command now outputs data about all internal environments when using the --json flag
    • Upgrade default CPython distributions to 20240415
    • Upgrade default PyPy distributions to 7.3.15
    • Upgrade Ruff to 0.4.2
    • Upgrade PyApp to 0.19.0 for binary builds
    • Bump the minimum supported version of Hatchling to 1.24.2
    • Bump the minimum supported version of virtualenv to 20.26.1

    Fixed:

    • Maintain consistent data paths for case insensitive file systems
    • When projects derive dependencies from metadata hooks, there is now by default a status indicator for when the hooks are executed for better responsiveness
    • Properly support projects with a pyproject.toml file but no project table e.g. applications
    • Fix the fmt command when automatically installing plugin dependencies
    • Fix dependency inheritance for the template of the types environment for new projects
    • Fix warnings related to tar file extraction on Python 3.12+ when unpacking Python distributions for installation
    • De-select Ruff rule E501 for the fmt command by default since it conflicts with the formatter
    • Fix colored output from build targets on the first run (build environment creation status indicator issue)
    • Set the packaging dependency version as >=23.2 to avoid its URL validation which can conflict with context formatting
    • Fix the exit code when there happens to be an unhandled exception
    • No longer capture both stdout and stderr streams when parsing metadata payloads from build environments
    • Fix the README.md file template for new projects to avoid Markdown linting issues

    1.9.7 - 2024-04-24

    Fixed:

    • Limit the maximum version of virtualenv due to a backward incompatible change
    • Upgrade PyApp to 0.12.0 for binary builds

    1.9.4 - 2024-03-12

    Fixed:

    • Limit the maximum version of Hatchling in anticipation of backward incompatible changes

    1.9.3 - 2024-01-25

    Fixed:

    • Fix loading of local plugins to account for newly released versions of a dependency

    1.9.2 - 2024-01-21

    Fixed:

    • Fix the default token variable name for publishing to PyPI

    1.9.1 - 2023-12-25

    Fixed:

    • Ensure that the dependency_hash method of the environment interface is called after sync_dependencies for cases where the hash is only known at that point, such as for dependency lockers
    • Only acknowledge the HATCH_PYTHON_VARIANT_* environment variables for Python resolution for supported platforms and architectures
    • Fix Python resolution when there are metadata hooks with unsatisfied dependencies

    1.9.0 - 2023-12-19

    Changed:

    • Environments prefixed by hatch- are now considered internal and used for special purposes such as configuration for static analysis

    Added:

    • Enable docstring formatting by default for static analysis
    • Allow for overriding config of internal environments
    • Concretely state the expected API contract for the environment interface methods find and check_compatibility
    • Upgrade Ruff to 0.1.8
    • Bump the minimum supported version of Hatchling to 1.21.0

    Fixed:

    • Ignore a project's Python requirement for environments where the project is not installed
    • When not persisting config for static analysis, properly manage internal settings when Ruff's top level table already exists
    • Ignore compatibility checks when environments have already been created, significantly improving performance of environment usage
    • Properly allow overriding of the path option for the virtual environment type
    • Fix nushell activation on non-Windows systems

    1.8.1 - 2023-12-14

    Fixed:

    • Fix regression in calling subprocesses with updated PATH
    • Fix automatic installation of environment plugins when running as a standalone binary
    • Change default location of Python installations

    1.8.0 - 2023-12-11

    Changed:

    • Drop support for Python 3.7
    • The get_build_process method of the environment interface has been removed; plugins should use the new run_builder method instead
    • Remove pyperclip dependency and the --copy flag of the config find command
    • When running the build command all output from builders is now displayed as-is in real time without the stripping of ANSI codes
    • Version information (for Hatch itself) is now derived from Git

    Added:

    • Support Python 3.12
    • Add installers and standalone binaries
    • Add the ability to manage Python installations
    • Add fmt command
    • The virtual environment type can now automatically download requested versions of Python that are not installed
    • Add dependency_hash method to the environment interface
    • The state of installed dependencies for environments is saved as metadata so if dependency definitions have not changed then no checking is performed, which can be computationally expensive
    • The build command now supports backends other than Hatchling
    • Allow the use of features for environments when skip-install is enabled
    • The default is now __token__ when prompting for a username for the publish command
    • Add a new run_builder method to the environment interface
    • Bump the minimum supported version of Hatchling to 1.19.0
    • Bump the minimum supported version of click to 8.0.6

    Fixed:

    • Fix nushell activation
    • Better handling of flat storage directory hierarchies for the virtual environment type
    • Display useful information when running the version command outside of a project rather than erroring
    • Fix the project metadata command by only capturing stdout from the backend
    • Properly support Google Artifact Registry
    • Fix parsing dependencies for environments when warnings are emitted

    1.7.0 - 2023-04-03

    Changed:

    • The src-layout project template option is now enabled by default
    • Non-critical output now goes to stderr

    Added:

    • Add tool.hatch.env.requires configuration to automatically install dependencies for environment and environment collector plugins
    • Add custom environment collector
    • Improve syncing of dependencies provided through Git direct references
    • Add isolated_data_directory attribute to the environment interface
    • Increase the timeout for and add retries to the index publisher
    • Expand home and environment variables in configured cache and data directories
    • Improve readability of exceptions
    • Update project templates
    • Bump the minimum supported version of Hatchling to 1.14.0

    Fixed:

    • Fix displaying the version with the version command when the version is static and build dependencies are unmet
    • Fix build environments for the virtual environment type when storing within a relative path
    • Work around System Integrity Protection on macOS when running commands
    • Allow setuptools metadata migration for projects without setup.py if setup.cfg is present
    • Handle additional edge cases for setuptools metadata migration
    • Support boolean values for the config set command

    1.6.3 - 2022-10-24

    Fixed:

    • Fix version command when the version is dynamic and build dependencies are unmet

    1.6.2 - 2022-10-20

    Fixed:

    • Fix getting dynamic metadata from hooks for environments when dependencies are not dynamic

    1.6.1 - 2022-10-16

    Fixed:

    • Computing the path to the user's home directory now gracefully falls back to ~ when it cannot be determined

    1.6.0 - 2022-10-08

    Changed:

    • The run_shell_command environment interface method now accepts arbitrary subprocess.Popen keyword arguments. This is not strictly breaking, but will be utilized in upcoming features.
    • The internal directory structure for storing virtual environments is now more nested. This is not breaking, but any local environments will be created anew.

    Added:

    • Add project command group to view details about the project like PEP 621 metadata
    • Better support for auto-detection of environments by tools like Visual Studio Code now that the storage directory of virtual environments will be flat if Hatch's configured virtual environment directory resides somewhere within the project root or if it is set to a .virtualenvs directory within the user's home directory
    • Build environments for the virtual environment type are now cached for improved performance
    • Add build_environment_exists method to the environment interface for implementations that cache the build environment
    • Add path option to the virtual environment type
    • Add --initialize-auth flag to the index publisher to allow for the saving of authentication information before publishing
    • Support Bash on Windows for the shell command
    • The setuptools migration script no longer modifies the formatting of existing pyproject.toml configuration
    • Bump the minimum supported version of Hatchling to 1.11.0

    Fixed:

    • Environments now respect dynamically defined project dependencies
    • The dep hash and all dep show commands now respect dynamically defined project dependencies
    • The env show, dep hash, and all dep show commands now honor context formatting
    • Fix matrix variable inclusion filtering of the run and env run commands when there are multiple possible variables
    • Build environment compatibility is now checked before use
    • Decreasing verbosity now has no affect on output that should always be displayed
    • Handle more edge cases in the setuptools migration script
    • Environments now respect user defined environment variables for context formatting
    • Update the scripts in the generated test environment template for new projects to reflect the documentation
    • Allow extra-dependencies in environment overrides
    • Depend on packaging explicitly rather than relying on it being a transitive dependency of Hatchling

    1.5.0 - 2022-08-28

    Added:

    • The index publisher now recognizes repository-specific options
    • Add the --ignore-compat flag to the env run command
    • Setting the HATCH_PYTHON environment variable to self will now force the use of the Python executable Hatch is running on for virtual environment creation

    Fixed:

    • Fix the --force-continue flag of the env run command
    • Handle more edge cases in the setuptools migration script

    1.4.2 - 2022-08-16

    Fixed:

    • Fix check for updating static versions with the version command when metadata hooks are in use

    1.4.1 - 2022-08-13

    Fixed:

    • Fix non-detached inheritance disabling for environments

    1.4.0 - 2022-08-06

    Added:

    • The default Python for virtual environments now checks PATH before using the one Hatch is running on
    • Values for environment env-vars now support context formatting
    • Add name override for environments to allow for regular expression matching
    • The index publisher now better supports non-PyPI indices
    • Add certificate options to the index publisher
    • Display waiting text when checking dependencies and removing environments
    • Display help text the first time the shell command is executed
    • Update project templates with Python 3.11 and the latest versions of various GitHub Actions
    • Add support for Almquist (ash) shells
    • Add hyperlink as a dependency for better handling of package index URLs
    • Bump the minimum supported version of virtualenv to 20.16.2
    • Bump the minimum supported version of tomlkit to 0.11.1

    Fixed:

    • Acknowledge extra-dependencies for the env show command
    • Fix locating executables within virtual environments on Debian
    • Fix managing the terminal size inside the shell command
    • Fix default code coverage file omission for the src-layout project template option

    1.3.1 - 2022-07-11

    Fixed:

    • Support -h/--help flag for the run command

    1.3.0 - 2022-07-10

    Changed:

    • Rename the default publishing plugin from pypi to the more generic index

    Added:

    • Support the absence of pyproject.toml files, as is the case for apps and non-Python projects
    • Hide scripts that start with an underscore for the env show command by default
    • Ignoring the exit codes of commands by prefixing with hyphens now works with entire named scripts
    • Add a way to require confirmation for publishing
    • Add --force-continue flag to the env run command
    • Make tracebacks colorful and less verbose
    • When shell configuration has not been defined, attempt to use the current shell based on parent processes before resorting to the defaults
    • The shell name pwsh is now an alias for powershell
    • Remove atomicwrites dependency
    • Relax constraint on userpath dependency
    • Bump the minimum supported version of Hatchling to 1.4.1

    Fixed:

    • Keep environments in sync with the dependencies of the selected features
    • Use utf-8 for all files generated for new projects
    • Escape special characters Git may return in the user name when writing generated files for new projects
    • Normalize the package name to lowercase in setuptools migration script
    • Fix parsing of source distributions during publishing

    1.2.1 - 2022-05-30

    Fixed:

    • Fix handling of top level data_files in setuptools migration script

    1.2.0 - 2022-05-22

    Changed:

    • The enter_shell environment plugin method now accepts an additional args parameter

    Added:

    • Allow context string formatting for environment dependencies
    • Add environment context string formatting fields env_name, env_type, matrix, verbosity, and args
    • Support overriding the default arguments used to spawn shells on non-Windows systems
    • Bump the minimum supported version of Hatchling to 1.3.0

    Fixed:

    • Improve setuptools migration script

    1.1.2 - 2022-05-20

    Fixed:

    • Bump the minimum supported version of Hatchling to 1.2.0
    • Update project metadata to reflect support for Python 3.11

    1.1.1 - 2022-05-12

    Fixed:

    • Fix setuptools migration script for non-Windows systems

    1.1.0 - 2022-05-12

    Changed:

    • In order to simplify the implementation of command execution for environment plugins, the run_shell_commands method has been replaced by the singular run_shell_command. A new command_context method has been added to more easily satisfy complex use cases.
    • The finalize_command environment plugin method has been removed in favor of the newly introduced context formatting functionality.

    Added:

    • Add context formatting functionality i.e. the ability to insert values into configuration like environment variables and command line arguments
    • Any verbosity for command execution will now always display headers, even for single environments
    • Every executed command is now displayed when running multiple commands or when verbosity is enabled
    • Similar to make, ignore the exit code of executed commands that start with - (a hyphen)
    • Add ability for the --init flag of the new command to automatically migrate setuptools configuration
    • Update project metadata to reflect the adoption by PyPA and production stability

    1.0.0 - 2022-04-28

    This is the first stable release of Hatch v1, a complete rewrite. Enjoy!

    Hatch history


    All notable changes to Hatch will be documented in this file.

    The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

    Unreleased

    1.13.0 - 2024-10-13

    Added:

    • Support managing Python 3.13 distributions

    1.12.0 - 2024-05-28

    Changed:

    • The run/env run and test commands now treat inclusion variable options as an intersection rather than a union to allow for specific targeting of environments

    Added:

    • Add ability to control the source of Python distributions
    • Upgrade Ruff to 0.4.5
    • Upgrade PyApp to 0.22.0 for binary builds

    Fixed:

    • The fmt command no longer hides the commands that are being executed
    • Add default timeout for network requests, useful when installing Python distributions
    • Fix syntax highlighting contrast for the config show command

    1.11.1 - 2024-05-23

    Added:

    • Add official GitHub Action for installing Hatch

    Fixed:

    • Fix terminal.styles.spinner configuration
    • Fix entry points in the pre-built distributions that binaries use

    1.11.0 - 2024-05-14

    Added:

    • Upgrade PyApp to 0.21.1 for binary builds

    Fixed:

    • On Linux, install the highest compatible Python distribution variant based on CPU architecture rather than assuming recent hardware

    1.10.0 - 2024-05-02

    Changed:

    • The run/env run, fmt and shell commands now only change the current working directory to the project root if not already inside the project
    • The shell command now accepts a single argument to specify the environment to enter which overrides the standard choice mechanisms. The arguments determining shell options have been converted to flags.

    Added:

    • Add test command
    • The run command can now execute scripts that define inline metadata for dependencies and Python version constraints
    • The virtual environment type now supports the ability to use UV in place of pip & virtualenv
    • Add self report command for submitting pre-populated bug reports to GitHub
    • The reserved environment used for static analysis is now completely configurable
    • Add the following methods to the environment interface for complete control over output during life cycle management: app_status_creation, app_status_pre_installation, app_status_post_installation, app_status_project_installation, app_status_dependency_state_check, app_status_dependency_installation_check, app_status_dependency_synchronization
    • Add binaries for 32-bit versions of Windows
    • Read configuration from any ~/.pypirc file for the index publisher
    • Use the Git user as the default username for new project URL metadata
    • Add HATCH_DEBUG environment variable that when enabled will show local variables in the case of unhandled tracebacks
    • The env show command now outputs data about all internal environments when using the --json flag
    • Upgrade default CPython distributions to 20240415
    • Upgrade default PyPy distributions to 7.3.15
    • Upgrade Ruff to 0.4.2
    • Upgrade PyApp to 0.19.0 for binary builds
    • Bump the minimum supported version of Hatchling to 1.24.2
    • Bump the minimum supported version of virtualenv to 20.26.1

    Fixed:

    • Maintain consistent data paths for case insensitive file systems
    • When projects derive dependencies from metadata hooks, there is now by default a status indicator for when the hooks are executed for better responsiveness
    • Properly support projects with a pyproject.toml file but no project table e.g. applications
    • Fix the fmt command when automatically installing plugin dependencies
    • Fix dependency inheritance for the template of the types environment for new projects
    • Fix warnings related to tar file extraction on Python 3.12+ when unpacking Python distributions for installation
    • De-select Ruff rule E501 for the fmt command by default since it conflicts with the formatter
    • Fix colored output from build targets on the first run (build environment creation status indicator issue)
    • Set the packaging dependency version as >=23.2 to avoid its URL validation which can conflict with context formatting
    • Fix the exit code when there happens to be an unhandled exception
    • No longer capture both stdout and stderr streams when parsing metadata payloads from build environments
    • Fix the README.md file template for new projects to avoid Markdown linting issues

    1.9.7 - 2024-04-24

    Fixed:

    • Limit the maximum version of virtualenv due to a backward incompatible change
    • Upgrade PyApp to 0.12.0 for binary builds

    1.9.4 - 2024-03-12

    Fixed:

    • Limit the maximum version of Hatchling in anticipation of backward incompatible changes

    1.9.3 - 2024-01-25

    Fixed:

    • Fix loading of local plugins to account for newly released versions of a dependency

    1.9.2 - 2024-01-21

    Fixed:

    • Fix the default token variable name for publishing to PyPI

    1.9.1 - 2023-12-25

    Fixed:

    • Ensure that the dependency_hash method of the environment interface is called after sync_dependencies for cases where the hash is only known at that point, such as for dependency lockers
    • Only acknowledge the HATCH_PYTHON_VARIANT_* environment variables for Python resolution for supported platforms and architectures
    • Fix Python resolution when there are metadata hooks with unsatisfied dependencies

    1.9.0 - 2023-12-19

    Changed:

    • Environments prefixed by hatch- are now considered internal and used for special purposes such as configuration for static analysis

    Added:

    • Enable docstring formatting by default for static analysis
    • Allow for overriding config of internal environments
    • Concretely state the expected API contract for the environment interface methods find and check_compatibility
    • Upgrade Ruff to 0.1.8
    • Bump the minimum supported version of Hatchling to 1.21.0

    Fixed:

    • Ignore a project's Python requirement for environments where the project is not installed
    • When not persisting config for static analysis, properly manage internal settings when Ruff's top level table already exists
    • Ignore compatibility checks when environments have already been created, significantly improving performance of environment usage
    • Properly allow overriding of the path option for the virtual environment type
    • Fix nushell activation on non-Windows systems

    1.8.1 - 2023-12-14

    Fixed:

    • Fix regression in calling subprocesses with updated PATH
    • Fix automatic installation of environment plugins when running as a standalone binary
    • Change default location of Python installations

    1.8.0 - 2023-12-11

    Changed:

    • Drop support for Python 3.7
    • The get_build_process method of the environment interface has been removed; plugins should use the new run_builder method instead
    • Remove pyperclip dependency and the --copy flag of the config find command
    • When running the build command all output from builders is now displayed as-is in real time without the stripping of ANSI codes
    • Version information (for Hatch itself) is now derived from Git

    Added:

    • Support Python 3.12
    • Add installers and standalone binaries
    • Add the ability to manage Python installations
    • Add fmt command
    • The virtual environment type can now automatically download requested versions of Python that are not installed
    • Add dependency_hash method to the environment interface
    • The state of installed dependencies for environments is saved as metadata so if dependency definitions have not changed then no checking is performed, which can be computationally expensive
    • The build command now supports backends other than Hatchling
    • Allow the use of features for environments when skip-install is enabled
    • The default is now __token__ when prompting for a username for the publish command
    • Add a new run_builder method to the environment interface
    • Bump the minimum supported version of Hatchling to 1.19.0
    • Bump the minimum supported version of click to 8.0.6

    Fixed:

    • Fix nushell activation
    • Better handling of flat storage directory hierarchies for the virtual environment type
    • Display useful information when running the version command outside of a project rather than erroring
    • Fix the project metadata command by only capturing stdout from the backend
    • Properly support Google Artifact Registry
    • Fix parsing dependencies for environments when warnings are emitted

    1.7.0 - 2023-04-03

    Changed:

    • The src-layout project template option is now enabled by default
    • Non-critical output now goes to stderr

    Added:

    • Add tool.hatch.env.requires configuration to automatically install dependencies for environment and environment collector plugins
    • Add custom environment collector
    • Improve syncing of dependencies provided through Git direct references
    • Add isolated_data_directory attribute to the environment interface
    • Increase the timeout for and add retries to the index publisher
    • Expand home and environment variables in configured cache and data directories
    • Improve readability of exceptions
    • Update project templates
    • Bump the minimum supported version of Hatchling to 1.14.0

    Fixed:

    • Fix displaying the version with the version command when the version is static and build dependencies are unmet
    • Fix build environments for the virtual environment type when storing within a relative path
    • Work around System Integrity Protection on macOS when running commands
    • Allow setuptools metadata migration for projects without setup.py if setup.cfg is present
    • Handle additional edge cases for setuptools metadata migration
    • Support boolean values for the config set command

    1.6.3 - 2022-10-24

    Fixed:

    • Fix version command when the version is dynamic and build dependencies are unmet

    1.6.2 - 2022-10-20

    Fixed:

    • Fix getting dynamic metadata from hooks for environments when dependencies are not dynamic

    1.6.1 - 2022-10-16

    Fixed:

    • Computing the path to the user's home directory now gracefully falls back to ~ when it cannot be determined

    1.6.0 - 2022-10-08

    Changed:

    • The run_shell_command environment interface method now accepts arbitrary subprocess.Popen keyword arguments. This is not strictly breaking, but will be utilized in upcoming features.
    • The internal directory structure for storing virtual environments is now more nested. This is not breaking, but any local environments will be created anew.

    Added:

    • Add project command group to view details about the project like PEP 621 metadata
    • Better support for auto-detection of environments by tools like Visual Studio Code now that the storage directory of virtual environments will be flat if Hatch's configured virtual environment directory resides somewhere within the project root or if it is set to a .virtualenvs directory within the user's home directory
    • Build environments for the virtual environment type are now cached for improved performance
    • Add build_environment_exists method to the environment interface for implementations that cache the build environment
    • Add path option to the virtual environment type
    • Add --initialize-auth flag to the index publisher to allow for the saving of authentication information before publishing
    • Support Bash on Windows for the shell command
    • The setuptools migration script no longer modifies the formatting of existing pyproject.toml configuration
    • Bump the minimum supported version of Hatchling to 1.11.0

    Fixed:

    • Environments now respect dynamically defined project dependencies
    • The dep hash and all dep show commands now respect dynamically defined project dependencies
    • The env show, dep hash, and all dep show commands now honor context formatting
    • Fix matrix variable inclusion filtering of the run and env run commands when there are multiple possible variables
    • Build environment compatibility is now checked before use
    • Decreasing verbosity now has no affect on output that should always be displayed
    • Handle more edge cases in the setuptools migration script
    • Environments now respect user defined environment variables for context formatting
    • Update the scripts in the generated test environment template for new projects to reflect the documentation
    • Allow extra-dependencies in environment overrides
    • Depend on packaging explicitly rather than relying on it being a transitive dependency of Hatchling

    1.5.0 - 2022-08-28

    Added:

    • The index publisher now recognizes repository-specific options
    • Add the --ignore-compat flag to the env run command
    • Setting the HATCH_PYTHON environment variable to self will now force the use of the Python executable Hatch is running on for virtual environment creation

    Fixed:

    • Fix the --force-continue flag of the env run command
    • Handle more edge cases in the setuptools migration script

    1.4.2 - 2022-08-16

    Fixed:

    • Fix check for updating static versions with the version command when metadata hooks are in use

    1.4.1 - 2022-08-13

    Fixed:

    • Fix non-detached inheritance disabling for environments

    1.4.0 - 2022-08-06

    Added:

    • The default Python for virtual environments now checks PATH before using the one Hatch is running on
    • Values for environment env-vars now support context formatting
    • Add name override for environments to allow for regular expression matching
    • The index publisher now better supports non-PyPI indices
    • Add certificate options to the index publisher
    • Display waiting text when checking dependencies and removing environments
    • Display help text the first time the shell command is executed
    • Update project templates with Python 3.11 and the latest versions of various GitHub Actions
    • Add support for Almquist (ash) shells
    • Add hyperlink as a dependency for better handling of package index URLs
    • Bump the minimum supported version of virtualenv to 20.16.2
    • Bump the minimum supported version of tomlkit to 0.11.1

    Fixed:

    • Acknowledge extra-dependencies for the env show command
    • Fix locating executables within virtual environments on Debian
    • Fix managing the terminal size inside the shell command
    • Fix default code coverage file omission for the src-layout project template option

    1.3.1 - 2022-07-11

    Fixed:

    • Support -h/--help flag for the run command

    1.3.0 - 2022-07-10

    Changed:

    • Rename the default publishing plugin from pypi to the more generic index

    Added:

    • Support the absence of pyproject.toml files, as is the case for apps and non-Python projects
    • Hide scripts that start with an underscore for the env show command by default
    • Ignoring the exit codes of commands by prefixing with hyphens now works with entire named scripts
    • Add a way to require confirmation for publishing
    • Add --force-continue flag to the env run command
    • Make tracebacks colorful and less verbose
    • When shell configuration has not been defined, attempt to use the current shell based on parent processes before resorting to the defaults
    • The shell name pwsh is now an alias for powershell
    • Remove atomicwrites dependency
    • Relax constraint on userpath dependency
    • Bump the minimum supported version of Hatchling to 1.4.1

    Fixed:

    • Keep environments in sync with the dependencies of the selected features
    • Use utf-8 for all files generated for new projects
    • Escape special characters Git may return in the user name when writing generated files for new projects
    • Normalize the package name to lowercase in setuptools migration script
    • Fix parsing of source distributions during publishing

    1.2.1 - 2022-05-30

    Fixed:

    • Fix handling of top level data_files in setuptools migration script

    1.2.0 - 2022-05-22

    Changed:

    • The enter_shell environment plugin method now accepts an additional args parameter

    Added:

    • Allow context string formatting for environment dependencies
    • Add environment context string formatting fields env_name, env_type, matrix, verbosity, and args
    • Support overriding the default arguments used to spawn shells on non-Windows systems
    • Bump the minimum supported version of Hatchling to 1.3.0

    Fixed:

    • Improve setuptools migration script

    1.1.2 - 2022-05-20

    Fixed:

    • Bump the minimum supported version of Hatchling to 1.2.0
    • Update project metadata to reflect support for Python 3.11

    1.1.1 - 2022-05-12

    Fixed:

    • Fix setuptools migration script for non-Windows systems

    1.1.0 - 2022-05-12

    Changed:

    • In order to simplify the implementation of command execution for environment plugins, the run_shell_commands method has been replaced by the singular run_shell_command. A new command_context method has been added to more easily satisfy complex use cases.
    • The finalize_command environment plugin method has been removed in favor of the newly introduced context formatting functionality.

    Added:

    • Add context formatting functionality i.e. the ability to insert values into configuration like environment variables and command line arguments
    • Any verbosity for command execution will now always display headers, even for single environments
    • Every executed command is now displayed when running multiple commands or when verbosity is enabled
    • Similar to make, ignore the exit code of executed commands that start with - (a hyphen)
    • Add ability for the --init flag of the new command to automatically migrate setuptools configuration
    • Update project metadata to reflect the adoption by PyPA and production stability

    1.0.0 - 2022-04-28

    This is the first stable release of Hatch v1, a complete rewrite. Enjoy!

    \ No newline at end of file diff --git a/latest/history/hatchling/index.html b/latest/history/hatchling/index.html index dfdbaffb9..6a5281f85 100644 --- a/latest/history/hatchling/index.html +++ b/latest/history/hatchling/index.html @@ -1,4 +1,4 @@ - Hatchling history - Hatch

    Hatchling history


    All notable changes to Hatchling will be documented in this file.

    The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

    Unreleased

    Fixed:

    • Ignore manylinux/musllinux tags for the wheel target artifact name when enabling the infer_tag build data

    1.24.2 - 2024-04-22

    Fixed:

    • Add .venv to the list of directories that cannot be traversed
    • Output from the core Application utility now writes to stderr

    1.24.1 - 2024-04-18

    Fixed:

    • Maintain file permissions for shared-scripts option/shared_scripts build data of the wheel target

    1.24.0 - 2024-04-16

    Added:

    • Add shared_data and shared_scripts build data for the wheel target

    1.23.0 - 2024-04-14

    Added:

    • Add shared-scripts option for the wheel target

    Fixed:

    • Support recursive optional dependencies
    • Set the packaging dependency version as >=23.2 to avoid its URL validation which can conflict with context formatting

    1.22.5 - 2024-04-04

    Fixed:

    • Fix reading metadata from source distributions when fields are dynamic but not part of core metadata like entry points

    1.22.4 - 2024-03-23

    Fixed:

    • Only read source distribution metadata for fields that are explicitly defined as dynamic

    1.22.3 - 2024-03-19

    Fixed:

    • Fix the custom build hook when using dynamic dependencies

    1.22.2 - 2024-03-16

    Fixed:

    • Fix regression when loading metadata from source distributions
    • Fix metadata hooks when building wheels from source distributions

    1.22.1 - 2024-03-16

    Fixed:

    • Update the default version of core metadata to 2.3

    1.22.0 - 2024-03-16

    Deprecated:

    • The app build target has been renamed to binary to reduce ambiguity with the name of an upcoming feature. The former name will still be usable for several minor releases.

    Added:

    • Metadata for the wheel target now defaults to the PKG-INFO metadata within source distributions
    • Add dependencies method to the build hook interface so that hooks can themselves dynamically define dependencies
    • Update the default version of core metadata to 2.2
    • Update SPDX license information to version 3.23
    • Improve error message for when the default heuristics for wheel file inclusion fail

    Fixed:

    • Properly support core metadata version 2.2
    • Remove editables as a direct dependency
    • Fix default wheel tag when the supported Python version declaration is strict
    • Load VCS ignore patterns first so that whitelisted patterns can be excluded by project configuration
    • Don't consider VCS ignore files that are outside of the VCS boundary
    • The sdist build target now gracefully ignores UNIX socket files
    • Begin ignoring certain files ubiquitously, like .DS_Store on macOS

    1.21.1 - 2024-01-25

    Fixed:

    • Fix loading of local plugins to account for newly released versions of a dependency

    1.21.0 - 2023-12-18

    Added:

    • Add parent context modifier for path fields

    1.20.0 - 2023-12-13

    Added:

    • Add bypass-selection option to the wheel build target to allow for empty (metadata-only) wheels

    Fixed:

    • Fix regression in 1.19.1 that allowed exclude to count toward inclusion selection, thus bypassing the default inclusion selection heuristics
    • Fix writing optional dependency core metadata in situations where there are multiple environment markers

    1.19.1 - 2023-12-12

    Fixed:

    • Add better error message when the wheel build target cannot determine what to ship
    • Consider forced inclusion patterns and build-time artifacts as file selection since some build hooks generate the entire wheel contents without user configuration

    1.19.0 - 2023-12-11

    Changed:

    • An error will now be raised if a force-included path does not exist
    • An error will now be raised for the wheel build target if no file selection options are defined

    Added:

    • Officially support Python 3.12
    • Allow using an empty string for the sources option to add a prefix to distribution paths

    Fixed:

    • Properly handle non-zero version epoch for the standard version scheme
    • Fix the wheel build target for case insensitive file systems when the project metadata name does not match the directory name on disk
    • The app build target no longer has suppressed output
    • Prevent duplicate paths when projects require the sources option while build hooks overwrite included paths
    • Properly escape spaces for URI context formatting

    1.18.0 - 2023-06-12

    Changed:

    • Drop support for Python 3.7

    Added:

    • Update the list of directories that are always excluded for builds

    1.17.1 - 2023-06-03

    Fixed:

    • Fix dev mode when the project has symlinks and file inclusion is defined with the packages or only-include options
    • Change the name of generated PTH files for dev mode so they come first lexicographically and therefore load first

    1.17.0 - 2023-05-12

    Added:

    • The app build target now embeds the project version in the name of binaries

    1.16.1 - 2023-05-11

    Fixed:

    • Fix determining the built executable path for the app build target option when using a local copy of PyApp when there is an explicit target triple set

    1.16.0 - 2023-05-11

    Added:

    • Add app build target option to build using a local copy of the PyApp repository

    1.15.0 - 2023-05-09

    Added:

    • Add app build target

    1.14.1 - 2023-04-23

    Fixed:

    • Fix internal archive root naming for the sdist target when strict-naming is disabled to match the file name in order to support the expectation of some frontends

    1.14.0 - 2023-04-02

    Added:

    • Add trove-classifiers as a dependency

    Fixed:

    • Properly normalize metadata descriptions that contain line breaks

    1.13.0 - 2023-02-09

    Added:

    • Update the set of known trove classifiers to version 2023.2.8

    1.12.2 - 2023-01-05

    Fixed:

    • Add macos-max-compat option to the wheel target that is enabled by default to support the latest version 22.0 of the packaging library

    1.12.1 - 2022-12-31

    Fixed:

    • Fix minor regression in the PEP 517/660 function signatures that was discovered by Fedora

    1.12.0 - 2022-12-30

    Added:

    • Improve readability of exceptions
    • Add extra_metadata build data to the wheel target
    • Retroactively support License-Expression core metadata starting at version 2.1
    • Add more type hints
    • Update the set of known trove classifiers to version 2022.12.22
    • Update SPDX license information to version 3.19
    • Store Hatchling's metadata in pyproject.toml

    Fixed:

    • Acknowledge the ARCHFLAGS environment variable on macOS for the wheel target when build hooks set the infer_tag build data to true
    • Fix dependency checking when encountering broken distributions
    • Fix the support-legacy option for the sdist target when using a src-layout project structure
    • Remove unnecessary encoding declaration in the default template for the version build hook

    1.11.1 - 2022-10-19

    Fixed:

    • Fix default file selection behavior of the wheel target when there is a single top-level module

    1.11.0 - 2022-10-08

    Added:

    • Add env version source to retrieve the version from an environment variable
    • Add validate-bump option to the standard version scheme

    Fixed:

    • Use proper CSV formatting for the RECORD metadata file of the wheel target to avoid warnings during installation by pip if, for example, file names contain commas
    • Fix installations with pip for build hooks that modify runtime dependencies
    • Decreasing verbosity now has no affect on output that should always be displayed

    1.10.0 - 2022-09-18

    Added:

    • Add the following to the list of directories that cannot be traversed: __pypackages__, .hg, .hatch, .tox, .nox
    • Add deprecated option to allow ambiguous features

    Fixed:

    • Improve tracking of dynamic metadata
    • Fix core metadata for entries in project.optional-dependencies that use direct references

    1.9.0 - 2022-09-09

    Changed:

    • File pattern matching now more closely resembles Git's behavior

    Added:

    • Implement a minimal version of prepare_metadata_for_build_wheel and prepare_metadata_for_build_editable for non-frontend tools that only need to inspect a project's metadata
    • Add metadata command to view PEP 621 project metadata
    • Improve error messages for SPDX license errors
    • Retroactively support License-File for core metadata starting at version 2.1
    • Bump the minimum supported version of pathspec to 0.10.1

    Fixed:

    • Allow the valid non-SPDX license values LicenseRef-Public-Domain and LicenseRef-Proprietary
    • Show the help text of the CLI when no subcommand is selected

    1.8.1 - 2022-08-25

    Fixed:

    • Fix default file inclusion for wheel build targets when both the project name and package directory name are not normalized

    1.8.0 - 2022-08-16

    Added:

    • Add get_known_classifiers method to metadata hooks

    Fixed:

    • Fix check for updating static versions with the version command when metadata hooks are in use

    1.7.1 - 2022-08-13

    Fixed:

    • Fix the value of the relative_path attribute of included files, that some build plugins may use, when selecting explicit paths

    1.7.0 - 2022-08-12

    Added:

    • Add require-runtime-features option for builders and build hooks
    • Check for unknown trove classifiers
    • Update SPDX license information to version 3.18

    Fixed:

    • Add better error message for wheel target dev mode installations that define path rewrites with the sources option
    • Note the allow-direct-references option in the relevant error messages

    1.6.0 - 2022-07-23

    Changed:

    • When no build targets are specified on the command line, now default to sdist and wheel targets rather than what happens to be defined in config
    • The code version source now only supports files with known extensions
    • Global build hooks now run before target-specific build hooks to better match expected behavior

    Added:

    • The code version source now supports loading extension modules
    • Add search-paths option for the code version source

    Fixed:

    • Fix removing sources using an empty string value in the mapping
    • The strict-naming option now also applies to the metadata directory of wheel targets

    1.5.0 - 2022-07-11

    Added:

    • Support the final draft of PEP 639
    • Add strict-naming option for sdist and wheel targets

    Fixed:

    • Project names are now stored in sdist and wheel target core metadata exactly as defined in pyproject.toml without normalization to allow control of how PyPI displays them

    1.4.1 - 2022-07-04

    Fixed:

    • Fix forced inclusion of important files like licenses for sdist targets when using the explicit selection options
    • Don't sort project URL metadata so that the rendered order on PyPI can be controlled

    1.4.0 - 2022-07-03

    Changed:

    • The packages option uses the new only-include option to provide targeted inclusion, since that is desired most of the time. You can retain the old behavior by using the include and sources options together.

    Added:

    • Support PEP 561 type hinting
    • Add version build hook
    • Add only-include option
    • The editable version of wheel targets now respects the force-include option by default
    • The force-include option now supports path rewriting with the sources option
    • The wheel target shared-data and extra-metadata options now respect file selection options
    • The wheel target now auto-detects single module layouts
    • Improve performance by never entering directories that are guaranteed to be undesirable like __pycache__ rather than excluding individual files within
    • Update SPDX license information to version 3.17

    Fixed:

    • Don't write empty entry points file for wheel targets if there are no entry points defined
    • Allow metadata hooks to set the version in all cases
    • Prevent duplicate file entries from inclusion when using the force-include option

    1.3.1 - 2022-05-30

    Fixed:

    • Better populate global variables for the code version source

    1.3.0 - 2022-05-22

    Removed:

    • Remove unused global args context string formatting field

    Added:

    • Improve error messages for the env context string formatting field

    Fixed:

    • Fix uri context string formatting modifier on Windows

    1.2.0 - 2022-05-20

    Added:

    • Allow context formatting for project.dependencies and project.optional-dependencies

    1.1.0 - 2022-05-19

    Added:

    • Add uri and real context string formatting modifiers for file system paths

    1.0.0 - 2022-05-17

    Changed:

    • Drop support for Python 2

    Added:

    • Improve error messaging for invalid versions
    • Update project metadata to reflect support for Python 3.11

    0.25.1 - 2022-06-14

    Fixed:

    • Fix support for Windows on Python 2 by removing its support for symlinks

    0.25.0 - 2022-05-15

    Added:

    • Add skip-excluded-dirs build option
    • Allow build data to add additional project dependencies for wheel and sdist build targets
    • Add force_include_editable build data for the wheel build target
    • Add build_hooks build data
    • Add support for Mercurial's .hgignore files when using glob syntax
    • Update project metadata to reflect the adoption by PyPA

    Fixed:

    • Properly use underscores for the name of force_include build data
    • No longer greedily skip excluded directories by default

    0.24.0 - 2022-04-28

    This is the initial public release of the Hatchling build system. Support for Python 2 will be dropped in version 1.

    Hatchling history


    All notable changes to Hatchling will be documented in this file.

    The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

    Unreleased

    Fixed:

    • Ignore manylinux/musllinux tags for the wheel target artifact name when enabling the infer_tag build data

    1.24.2 - 2024-04-22

    Fixed:

    • Add .venv to the list of directories that cannot be traversed
    • Output from the core Application utility now writes to stderr

    1.24.1 - 2024-04-18

    Fixed:

    • Maintain file permissions for shared-scripts option/shared_scripts build data of the wheel target

    1.24.0 - 2024-04-16

    Added:

    • Add shared_data and shared_scripts build data for the wheel target

    1.23.0 - 2024-04-14

    Added:

    • Add shared-scripts option for the wheel target

    Fixed:

    • Support recursive optional dependencies
    • Set the packaging dependency version as >=23.2 to avoid its URL validation which can conflict with context formatting

    1.22.5 - 2024-04-04

    Fixed:

    • Fix reading metadata from source distributions when fields are dynamic but not part of core metadata like entry points

    1.22.4 - 2024-03-23

    Fixed:

    • Only read source distribution metadata for fields that are explicitly defined as dynamic

    1.22.3 - 2024-03-19

    Fixed:

    • Fix the custom build hook when using dynamic dependencies

    1.22.2 - 2024-03-16

    Fixed:

    • Fix regression when loading metadata from source distributions
    • Fix metadata hooks when building wheels from source distributions

    1.22.1 - 2024-03-16

    Fixed:

    • Update the default version of core metadata to 2.3

    1.22.0 - 2024-03-16

    Deprecated:

    • The app build target has been renamed to binary to reduce ambiguity with the name of an upcoming feature. The former name will still be usable for several minor releases.

    Added:

    • Metadata for the wheel target now defaults to the PKG-INFO metadata within source distributions
    • Add dependencies method to the build hook interface so that hooks can themselves dynamically define dependencies
    • Update the default version of core metadata to 2.2
    • Update SPDX license information to version 3.23
    • Improve error message for when the default heuristics for wheel file inclusion fail

    Fixed:

    • Properly support core metadata version 2.2
    • Remove editables as a direct dependency
    • Fix default wheel tag when the supported Python version declaration is strict
    • Load VCS ignore patterns first so that whitelisted patterns can be excluded by project configuration
    • Don't consider VCS ignore files that are outside of the VCS boundary
    • The sdist build target now gracefully ignores UNIX socket files
    • Begin ignoring certain files ubiquitously, like .DS_Store on macOS

    1.21.1 - 2024-01-25

    Fixed:

    • Fix loading of local plugins to account for newly released versions of a dependency

    1.21.0 - 2023-12-18

    Added:

    • Add parent context modifier for path fields

    1.20.0 - 2023-12-13

    Added:

    • Add bypass-selection option to the wheel build target to allow for empty (metadata-only) wheels

    Fixed:

    • Fix regression in 1.19.1 that allowed exclude to count toward inclusion selection, thus bypassing the default inclusion selection heuristics
    • Fix writing optional dependency core metadata in situations where there are multiple environment markers

    1.19.1 - 2023-12-12

    Fixed:

    • Add better error message when the wheel build target cannot determine what to ship
    • Consider forced inclusion patterns and build-time artifacts as file selection since some build hooks generate the entire wheel contents without user configuration

    1.19.0 - 2023-12-11

    Changed:

    • An error will now be raised if a force-included path does not exist
    • An error will now be raised for the wheel build target if no file selection options are defined

    Added:

    • Officially support Python 3.12
    • Allow using an empty string for the sources option to add a prefix to distribution paths

    Fixed:

    • Properly handle non-zero version epoch for the standard version scheme
    • Fix the wheel build target for case insensitive file systems when the project metadata name does not match the directory name on disk
    • The app build target no longer has suppressed output
    • Prevent duplicate paths when projects require the sources option while build hooks overwrite included paths
    • Properly escape spaces for URI context formatting

    1.18.0 - 2023-06-12

    Changed:

    • Drop support for Python 3.7

    Added:

    • Update the list of directories that are always excluded for builds

    1.17.1 - 2023-06-03

    Fixed:

    • Fix dev mode when the project has symlinks and file inclusion is defined with the packages or only-include options
    • Change the name of generated PTH files for dev mode so they come first lexicographically and therefore load first

    1.17.0 - 2023-05-12

    Added:

    • The app build target now embeds the project version in the name of binaries

    1.16.1 - 2023-05-11

    Fixed:

    • Fix determining the built executable path for the app build target option when using a local copy of PyApp when there is an explicit target triple set

    1.16.0 - 2023-05-11

    Added:

    • Add app build target option to build using a local copy of the PyApp repository

    1.15.0 - 2023-05-09

    Added:

    • Add app build target

    1.14.1 - 2023-04-23

    Fixed:

    • Fix internal archive root naming for the sdist target when strict-naming is disabled to match the file name in order to support the expectation of some frontends

    1.14.0 - 2023-04-02

    Added:

    • Add trove-classifiers as a dependency

    Fixed:

    • Properly normalize metadata descriptions that contain line breaks

    1.13.0 - 2023-02-09

    Added:

    • Update the set of known trove classifiers to version 2023.2.8

    1.12.2 - 2023-01-05

    Fixed:

    • Add macos-max-compat option to the wheel target that is enabled by default to support the latest version 22.0 of the packaging library

    1.12.1 - 2022-12-31

    Fixed:

    • Fix minor regression in the PEP 517/660 function signatures that was discovered by Fedora

    1.12.0 - 2022-12-30

    Added:

    • Improve readability of exceptions
    • Add extra_metadata build data to the wheel target
    • Retroactively support License-Expression core metadata starting at version 2.1
    • Add more type hints
    • Update the set of known trove classifiers to version 2022.12.22
    • Update SPDX license information to version 3.19
    • Store Hatchling's metadata in pyproject.toml

    Fixed:

    • Acknowledge the ARCHFLAGS environment variable on macOS for the wheel target when build hooks set the infer_tag build data to true
    • Fix dependency checking when encountering broken distributions
    • Fix the support-legacy option for the sdist target when using a src-layout project structure
    • Remove unnecessary encoding declaration in the default template for the version build hook

    1.11.1 - 2022-10-19

    Fixed:

    • Fix default file selection behavior of the wheel target when there is a single top-level module

    1.11.0 - 2022-10-08

    Added:

    • Add env version source to retrieve the version from an environment variable
    • Add validate-bump option to the standard version scheme

    Fixed:

    • Use proper CSV formatting for the RECORD metadata file of the wheel target to avoid warnings during installation by pip if, for example, file names contain commas
    • Fix installations with pip for build hooks that modify runtime dependencies
    • Decreasing verbosity now has no affect on output that should always be displayed

    1.10.0 - 2022-09-18

    Added:

    • Add the following to the list of directories that cannot be traversed: __pypackages__, .hg, .hatch, .tox, .nox
    • Add deprecated option to allow ambiguous features

    Fixed:

    • Improve tracking of dynamic metadata
    • Fix core metadata for entries in project.optional-dependencies that use direct references

    1.9.0 - 2022-09-09

    Changed:

    • File pattern matching now more closely resembles Git's behavior

    Added:

    • Implement a minimal version of prepare_metadata_for_build_wheel and prepare_metadata_for_build_editable for non-frontend tools that only need to inspect a project's metadata
    • Add metadata command to view PEP 621 project metadata
    • Improve error messages for SPDX license errors
    • Retroactively support License-File for core metadata starting at version 2.1
    • Bump the minimum supported version of pathspec to 0.10.1

    Fixed:

    • Allow the valid non-SPDX license values LicenseRef-Public-Domain and LicenseRef-Proprietary
    • Show the help text of the CLI when no subcommand is selected

    1.8.1 - 2022-08-25

    Fixed:

    • Fix default file inclusion for wheel build targets when both the project name and package directory name are not normalized

    1.8.0 - 2022-08-16

    Added:

    • Add get_known_classifiers method to metadata hooks

    Fixed:

    • Fix check for updating static versions with the version command when metadata hooks are in use

    1.7.1 - 2022-08-13

    Fixed:

    • Fix the value of the relative_path attribute of included files, that some build plugins may use, when selecting explicit paths

    1.7.0 - 2022-08-12

    Added:

    • Add require-runtime-features option for builders and build hooks
    • Check for unknown trove classifiers
    • Update SPDX license information to version 3.18

    Fixed:

    • Add better error message for wheel target dev mode installations that define path rewrites with the sources option
    • Note the allow-direct-references option in the relevant error messages

    1.6.0 - 2022-07-23

    Changed:

    • When no build targets are specified on the command line, now default to sdist and wheel targets rather than what happens to be defined in config
    • The code version source now only supports files with known extensions
    • Global build hooks now run before target-specific build hooks to better match expected behavior

    Added:

    • The code version source now supports loading extension modules
    • Add search-paths option for the code version source

    Fixed:

    • Fix removing sources using an empty string value in the mapping
    • The strict-naming option now also applies to the metadata directory of wheel targets

    1.5.0 - 2022-07-11

    Added:

    • Support the final draft of PEP 639
    • Add strict-naming option for sdist and wheel targets

    Fixed:

    • Project names are now stored in sdist and wheel target core metadata exactly as defined in pyproject.toml without normalization to allow control of how PyPI displays them

    1.4.1 - 2022-07-04

    Fixed:

    • Fix forced inclusion of important files like licenses for sdist targets when using the explicit selection options
    • Don't sort project URL metadata so that the rendered order on PyPI can be controlled

    1.4.0 - 2022-07-03

    Changed:

    • The packages option uses the new only-include option to provide targeted inclusion, since that is desired most of the time. You can retain the old behavior by using the include and sources options together.

    Added:

    • Support PEP 561 type hinting
    • Add version build hook
    • Add only-include option
    • The editable version of wheel targets now respects the force-include option by default
    • The force-include option now supports path rewriting with the sources option
    • The wheel target shared-data and extra-metadata options now respect file selection options
    • The wheel target now auto-detects single module layouts
    • Improve performance by never entering directories that are guaranteed to be undesirable like __pycache__ rather than excluding individual files within
    • Update SPDX license information to version 3.17

    Fixed:

    • Don't write empty entry points file for wheel targets if there are no entry points defined
    • Allow metadata hooks to set the version in all cases
    • Prevent duplicate file entries from inclusion when using the force-include option

    1.3.1 - 2022-05-30

    Fixed:

    • Better populate global variables for the code version source

    1.3.0 - 2022-05-22

    Removed:

    • Remove unused global args context string formatting field

    Added:

    • Improve error messages for the env context string formatting field

    Fixed:

    • Fix uri context string formatting modifier on Windows

    1.2.0 - 2022-05-20

    Added:

    • Allow context formatting for project.dependencies and project.optional-dependencies

    1.1.0 - 2022-05-19

    Added:

    • Add uri and real context string formatting modifiers for file system paths

    1.0.0 - 2022-05-17

    Changed:

    • Drop support for Python 2

    Added:

    • Improve error messaging for invalid versions
    • Update project metadata to reflect support for Python 3.11

    0.25.1 - 2022-06-14

    Fixed:

    • Fix support for Windows on Python 2 by removing its support for symlinks

    0.25.0 - 2022-05-15

    Added:

    • Add skip-excluded-dirs build option
    • Allow build data to add additional project dependencies for wheel and sdist build targets
    • Add force_include_editable build data for the wheel build target
    • Add build_hooks build data
    • Add support for Mercurial's .hgignore files when using glob syntax
    • Update project metadata to reflect the adoption by PyPA

    Fixed:

    • Properly use underscores for the name of force_include build data
    • No longer greedily skip excluded directories by default

    0.24.0 - 2022-04-28

    This is the initial public release of the Hatchling build system. Support for Python 2 will be dropped in version 1.

    \ No newline at end of file diff --git a/latest/how-to/config/dynamic-metadata/index.html b/latest/how-to/config/dynamic-metadata/index.html index f963e8e94..0b9e94801 100644 --- a/latest/how-to/config/dynamic-metadata/index.html +++ b/latest/how-to/config/dynamic-metadata/index.html @@ -1,4 +1,4 @@ - How to configure custom dynamic metadata - Hatch

    Installation


    GitHub Actions

    - name: Install Hatch
       uses: pypa/hatch@install
     

    Refer to the official action for more information.

    Installers

    1. In your browser, download the .pkg file: hatch-universal.pkg
    2. Run your downloaded file and follow the on-screen instructions.
    3. Restart your terminal.
    4. To verify that the shell can find and run the hatch command in your PATH, use the following command.

      $ hatch --version
      -1.12.0
      +1.13.0
       
    1. Download the file using the curl command. The -o option specifies the file name that the downloaded package is written to. In this example, the file is written to hatch-universal.pkg in the current directory.

      curl -Lo hatch-universal.pkg https://github.com/pypa/hatch/releases/latest/download/hatch-universal.pkg
       
    2. Run the standard macOS installer program, specifying the downloaded .pkg file as the source. Use the -pkg parameter to specify the name of the package to install, and the -target / parameter for the drive in which to install the package. The files are installed to /usr/local/hatch, and an entry is created at /etc/paths.d/hatch that instructs shells to add the /usr/local/hatch directory to. You must include sudo on the command to grant write permissions to those folders.

      sudo installer -pkg ./hatch-universal.pkg -target /
       
    3. Restart your terminal.

    4. To verify that the shell can find and run the hatch command in your PATH, use the following command.

      $ hatch --version
      -1.12.0
      +1.13.0
       
    1. In your browser, download one the .msi files:
    2. Run your downloaded file and follow the on-screen instructions.
    3. Restart your terminal.
    4. To verify that the shell can find and run the hatch command in your PATH, use the following command.

      $ hatch --version
      -1.12.0
      +1.13.0
       
    1. Download and run the installer using the standard Windows msiexec program, specifying one of the .msi files as the source. Use the /passive and /i parameters to request an unattended, normal installation.

      msiexec /passive /i https://github.com/pypa/hatch/releases/latest/download/hatch-x64.msi
       
      msiexec /passive /i https://github.com/pypa/hatch/releases/latest/download/hatch-x86.msi
       
    2. Restart your terminal.

    3. To verify that the shell can find and run the hatch command in your PATH, use the following command.

      $ hatch --version
      -1.12.0
      +1.13.0
       

    Standalone binaries

    After downloading the archive corresponding to your platform and architecture, extract the binary to a directory that is on your PATH and rename to hatch.

    pip

    Hatch is available on PyPI and can be installed with pip.

    pip install hatch
     

    Warning

    This method modifies the Python environment in which you choose to install. Consider instead using pipx to avoid dependency conflicts.

    pipx

    pipx allows for the global installation of Python applications in isolated environments.

    pipx install hatch
     

    Homebrew

    See the formula for more details.

    brew install hatch
    diff --git a/latest/intro/index.html b/latest/intro/index.html
    index 6a7d8a7ab..d06ec9d52 100644
    --- a/latest/intro/index.html
    +++ b/latest/intro/index.html
    @@ -1,4 +1,4 @@
    - Introduction - Hatch      

    Why Hatch?


    The high level value proposition of Hatch is that if one adopts all functionality then many other tools become unnecessary since there is support for everything one might require. Further, if one chooses to use only specific features then there are still benefits compared to alternatives.

    Build backend

    Hatchling, the build backend sister project, has many benefits compared to setuptools. Here we only compare setuptools as that is the one most people are familiar with.

    • Better defaults: The default behavior for setuptools is often not desirable for the average user.
      • For source distributions, setuptools has a custom enumeration of files that get included and excluded by default. Hatchling takes the defaults from your version control system such as Git's .gitignore file.
      • For wheels, setuptools attempts to find every directory that looks like a Python package. This is often undesirable as you might ship files to the end-user unintentionally such as test or tooling directories. Hatchling defaults to very specific inclusion based on the project name and errors if no heuristic is satisfied.
    • Ease of configurability: Hatchling was designed based on a history of significant challenges when configuring setuptools.
      • Hatchling uses the same glob pattern syntax as Git itself for every option which is what most users are familiar with. On the other hand, setuptools uses shell-style glob patterns for source distributions while wheels use a mix of shell-style globs and Python package syntax.
      • Configuring what gets included in source distributions requires a separate MANIFEST.in file. The custom syntax and directives must be learned and it is difficult knowing which options in the main files like setup.py influence the behavior and under what conditions. For Hatchling, everything gets configured in a single file under dedicated sections for specific targets like [tool.hatch.build.targets.wheel].
      • By default, non-Python files are excluded from wheels. Including such files requires usually verbose rules for every nested package directory. Hatchling makes no such distinction between file types and acts more like a general build system one might already be familiar with.
    • Editable installations: The default behavior of Hatchling allows for proper static analysis by external tools such as IDEs. With setuptools, you must provide additional configuration which means that by default, for example, you would not get autocompletion in Visual Studio Code. This is marked as a legacy feature and may in fact be removed in future versions of setuptools.
    • Reproducibility: Hatchling builds reproducible wheels and source distributions by default. setuptools does not support this for source distributions and there is no guarantee that wheels are reproducible.
    • Extensibility: Although it is possible to extend setuptools, the API is quite low level. Hatchling has the concept of plugins that are separated into discrete types and only expose what is necessary, leading to an easier developer experience.

    Why not?:

    If building extension modules is required then it is recommended that you continue using setuptools, or even other backends that specialize in interfacing with compilers.

    Environment management

    Here we compare to both tox and nox. At a high level, there are a few common advantages:

    • Python management: Hatch is able to automatically download Python distributions on the fly when specific versions that environments request cannot be found. The alternatives will raise an error, with the option to ignore unknown distributions.
    • Philosophy: In the alternatives, environments are for the most part treated as executable units where a dependency set is associated with an action. If you are familiar with container ecosystems, this would be like defining a CMD at the end of a Dockerfile but without the ability to change the action at runtime. This involves significant wasted disk space usually because one often requires slight modifications to the actions and therefore will define entirely different environments inherited from a base config just to perform different logic. Additionally, this can be confusing to users not just configuration-wise but also for execution of the different environments.

      In Hatch, environments are treated as isolated areas where you can execute arbitrary commands at runtime. For example, you can define a single test environment with named scripts that runs unit vs non-unit tests, each command being potentially very long but named however you wish so you get to control the interface. Since environments are treated as places where work is performed, you can also spawn a shell into any which will execute a subprocess that automatically drops into your shell of choice. Your shell will be configured appropriately like python on PATH being updated and the prompt being changed to reflect the chosen environment.

    • Configuration:

      • tox only supports INI configuration and if one desires putting that in the standard pyproject.toml file then it must be a multi-line string containing the INI config which would preclude syntax highlighting. Hatch allows for TOML-based config just like most other tools in the Python ecosystem.
      • nox config is defined in Python which often leads to increased verbosity and makes it challenging to onboard folks compared to a standardized format with known behaviors.
    • Extensibility:
      • tox allows for extending most aspects of its functionality however the API is so low-level and attached to internals that creating plugins may be challenging. For example, here is a tox plugin that was migrated to an equivalent Hatch environment collector plugin.
      • nox is configured with Python so for the local project you can do whatever you want, however there is no concept of third-party plugins per se. To achieve that, you must usually use a package that wraps nox and use that package's imports instead (example).

    Why not?:

    If you are using nox and you wish to migrate, and for some reason you notify sessions, then migration wouldn't be a straight translation but rather you might have to redesign that conditional step.

    Python management

    Here we compare Python management to that of pyenv.

    • Cross-platform: Hatch allows for the same experience no matter the system whereas pyenv does not support Windows so you must use an entirely different project that tries to emulate the functionality.
    • No build dependencies: Hatch guarantees that every available distribution is prebuilt whereas the alternative requires one to maintain a precise build environment which differs by platform and potentially Python version. Another benefit to this is extremely fast installations since the distributions are simply downloaded and unpacked.
    • Optimized by default: The CPython distributions are built with profile guided optimization and link-time optimization, resulting in a 10-30% performance improvement depending on the workload. These distributions have seen wide adoption throughout the industry and are even used by the build system Bazel.
    • Simplicity: Hatch treats Python installations as just another directory that one would add to PATH. It can do this for you or you can manage PATH yourself, even allowing for custom install locations. On the other hand, pyenv operates by adding shims which then act as wrappers around the actual underlying binaries. This has many unfortunate side effects:
      • It is incumbent upon the user to manage which specific Python comes first via the CLI, switch when necessary, and/or have a mental model of which versions are exposed globally and locally per-project. This can become confusing quite quickly. When working with Hatch, your global Python installations are only important insofar as they are on PATH somewhere since environments do not use them directly but rather create virtual environments from them, always using a version that is compatible with your project.
      • Configuration is required for each shell to properly set up pyenv on start, leading to inconsistencies when running processes that do not spawn a shell.
      • Debugging issues with Python search paths can be extremely difficult, especially for users of software. If you or users have ever ran into an issue where code was being executed that you did not anticipate, the issue is almost always pyenv influencing the python on PATH.

    Why not?:

    Currently, Hatch does not allow for the installation of specific patch release versions but rather only uses minor release granularity that tracks the latest patch release. If specific patch releases are important to you then it is best to use an alternative installation mechanism.

    Why Hatch?


    The high level value proposition of Hatch is that if one adopts all functionality then many other tools become unnecessary since there is support for everything one might require. Further, if one chooses to use only specific features then there are still benefits compared to alternatives.

    Build backend

    Hatchling, the build backend sister project, has many benefits compared to setuptools. Here we only compare setuptools as that is the one most people are familiar with.

    • Better defaults: The default behavior for setuptools is often not desirable for the average user.
      • For source distributions, setuptools has a custom enumeration of files that get included and excluded by default. Hatchling takes the defaults from your version control system such as Git's .gitignore file.
      • For wheels, setuptools attempts to find every directory that looks like a Python package. This is often undesirable as you might ship files to the end-user unintentionally such as test or tooling directories. Hatchling defaults to very specific inclusion based on the project name and errors if no heuristic is satisfied.
    • Ease of configurability: Hatchling was designed based on a history of significant challenges when configuring setuptools.
      • Hatchling uses the same glob pattern syntax as Git itself for every option which is what most users are familiar with. On the other hand, setuptools uses shell-style glob patterns for source distributions while wheels use a mix of shell-style globs and Python package syntax.
      • Configuring what gets included in source distributions requires a separate MANIFEST.in file. The custom syntax and directives must be learned and it is difficult knowing which options in the main files like setup.py influence the behavior and under what conditions. For Hatchling, everything gets configured in a single file under dedicated sections for specific targets like [tool.hatch.build.targets.wheel].
      • By default, non-Python files are excluded from wheels. Including such files requires usually verbose rules for every nested package directory. Hatchling makes no such distinction between file types and acts more like a general build system one might already be familiar with.
    • Editable installations: The default behavior of Hatchling allows for proper static analysis by external tools such as IDEs. With setuptools, you must provide additional configuration which means that by default, for example, you would not get autocompletion in Visual Studio Code. This is marked as a legacy feature and may in fact be removed in future versions of setuptools.
    • Reproducibility: Hatchling builds reproducible wheels and source distributions by default. setuptools does not support this for source distributions and there is no guarantee that wheels are reproducible.
    • Extensibility: Although it is possible to extend setuptools, the API is quite low level. Hatchling has the concept of plugins that are separated into discrete types and only expose what is necessary, leading to an easier developer experience.

    Why not?:

    If building extension modules is required then it is recommended that you continue using setuptools, or even other backends that specialize in interfacing with compilers.

    Environment management

    Here we compare to both tox and nox. At a high level, there are a few common advantages:

    • Python management: Hatch is able to automatically download Python distributions on the fly when specific versions that environments request cannot be found. The alternatives will raise an error, with the option to ignore unknown distributions.
    • Philosophy: In the alternatives, environments are for the most part treated as executable units where a dependency set is associated with an action. If you are familiar with container ecosystems, this would be like defining a CMD at the end of a Dockerfile but without the ability to change the action at runtime. This involves significant wasted disk space usually because one often requires slight modifications to the actions and therefore will define entirely different environments inherited from a base config just to perform different logic. Additionally, this can be confusing to users not just configuration-wise but also for execution of the different environments.

      In Hatch, environments are treated as isolated areas where you can execute arbitrary commands at runtime. For example, you can define a single test environment with named scripts that runs unit vs non-unit tests, each command being potentially very long but named however you wish so you get to control the interface. Since environments are treated as places where work is performed, you can also spawn a shell into any which will execute a subprocess that automatically drops into your shell of choice. Your shell will be configured appropriately like python on PATH being updated and the prompt being changed to reflect the chosen environment.

    • Configuration:

      • nox config is defined in Python which often leads to increased verbosity and makes it challenging to onboard folks compared to a standardized format with known behaviors.
    • Extensibility:
      • tox allows for extending most aspects of its functionality however the API is so low-level and attached to internals that creating plugins may be challenging. For example, here is a tox plugin that was migrated to an equivalent Hatch environment collector plugin.
      • nox is configured with Python so for the local project you can do whatever you want, however there is no concept of third-party plugins per se. To achieve that, you must usually use a package that wraps nox and use that package's imports instead (example).

    Why not?:

    If you are using nox and you wish to migrate, and for some reason you notify sessions, then migration wouldn't be a straight translation but rather you might have to redesign that conditional step.

    Python management

    Here we compare Python management to that of pyenv.

    • Cross-platform: Hatch allows for the same experience no matter the system whereas pyenv does not support Windows so you must use an entirely different project that tries to emulate the functionality.
    • No build dependencies: Hatch guarantees that every available distribution is prebuilt whereas the alternative requires one to maintain a precise build environment which differs by platform and potentially Python version. Another benefit to this is extremely fast installations since the distributions are simply downloaded and unpacked.
    • Optimized by default: The CPython distributions are built with profile guided optimization and link-time optimization, resulting in a 10-30% performance improvement depending on the workload. These distributions have seen wide adoption throughout the industry and are even used by the build system Bazel.
    • Simplicity: Hatch treats Python installations as just another directory that one would add to PATH. It can do this for you or you can manage PATH yourself, even allowing for custom install locations. On the other hand, pyenv operates by adding shims which then act as wrappers around the actual underlying binaries. This has many unfortunate side effects:
      • It is incumbent upon the user to manage which specific Python comes first via the CLI, switch when necessary, and/or have a mental model of which versions are exposed globally and locally per-project. This can become confusing quite quickly. When working with Hatch, your global Python installations are only important insofar as they are on PATH somewhere since environments do not use them directly but rather create virtual environments from them, always using a version that is compatible with your project.
      • Configuration is required for each shell to properly set up pyenv on start, leading to inconsistencies when running processes that do not spawn a shell.
      • Debugging issues with Python search paths can be extremely difficult, especially for users of software. If you or users have ever ran into an issue where code was being executed that you did not anticipate, the issue is almost always pyenv influencing the python on PATH.

    Why not?:

    Currently, Hatch does not allow for the installation of specific patch release versions but rather only uses minor release granularity that tracks the latest patch release. If specific patch releases are important to you then it is best to use an alternative installation mechanism.

    \ No newline at end of file diff --git a/versions.json b/versions.json index 81fb01d5e..7a2a6c79e 100644 --- a/versions.json +++ b/versions.json @@ -5,12 +5,17 @@ "aliases": [] }, { - "version": "1.12", - "title": "1.12", + "version": "1.13", + "title": "1.13", "aliases": [ "latest" ] }, + { + "version": "1.12", + "title": "1.12", + "aliases": [] + }, { "version": "1.11", "title": "1.11",