shortcutxl 0.3.76 → 0.3.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BINARY-INVENTORY.json +813 -813
- package/CHANGELOG.md +14 -0
- package/dist/ai/models.d.ts +10 -6
- package/dist/ai/models.generated.d.ts +72 -0
- package/dist/ai/models.generated.js +33 -0
- package/dist/ai/models.js +36 -13
- package/dist/ai/providers/anthropic.d.ts +4 -2
- package/dist/ai/providers/anthropic.js +59 -29
- package/dist/ai/providers/azure-openai-responses.d.ts +2 -1
- package/dist/ai/providers/azure-openai-responses.js +4 -20
- package/dist/ai/providers/google-vertex.d.ts +8 -2
- package/dist/ai/providers/google-vertex.js +66 -54
- package/dist/ai/providers/google.js +15 -48
- package/dist/ai/providers/openai-completions.d.ts +4 -1
- package/dist/ai/providers/openai-completions.js +26 -10
- package/dist/ai/providers/openai-reasoning.d.ts +5 -0
- package/dist/ai/providers/openai-reasoning.js +13 -0
- package/dist/ai/providers/openai-responses-shared.js +1 -1
- package/dist/ai/providers/openai-responses.d.ts +6 -2
- package/dist/ai/providers/openai-responses.js +28 -23
- package/dist/ai/providers/simple-options.d.ts +2 -3
- package/dist/ai/providers/simple-options.js +4 -6
- package/dist/ai/types.d.ts +19 -2
- package/dist/app/agent-session-runtime-adapter.js +7 -6
- package/dist/app/agent-session.d.ts +0 -15
- package/dist/app/agent-session.js +0 -37
- package/dist/app/approvals/approval-errors.d.ts +15 -0
- package/dist/app/approvals/approval-errors.js +14 -0
- package/dist/app/approvals/runtime-approval-gates.d.ts +1 -2
- package/dist/app/approvals/tool-approval.d.ts +1 -0
- package/dist/app/approvals/tool-approval.js +11 -23
- package/dist/app/approvals/types.d.ts +0 -14
- package/dist/app/approvals/types.js +0 -2
- package/dist/app/background/tool-summaries.js +0 -2
- package/dist/app/extensions/slash-commands.js +1 -3
- package/dist/app/local/tools/execute-code/executor.d.ts +1 -1
- package/dist/app/local/tools/execute-code/executor.js +20 -10
- package/dist/app/local/tools/execute-code/tool.js +21 -2
- package/dist/app/modes/action/agent.js +4 -5
- package/dist/app/modes/ask/agent.js +4 -6
- package/dist/app/modes/index.js +20 -10
- package/dist/app/modes/installation/agent.js +4 -5
- package/dist/app/modes/manage/agent.js +3 -4
- package/dist/app/modes/manage/prompt.js +1 -2
- package/dist/app/modes/metadata.d.ts +31 -0
- package/dist/app/modes/metadata.js +35 -0
- package/dist/app/modes/plan/agent.js +5 -8
- package/dist/app/modes/plan/prompt.js +3 -3
- package/dist/app/permissions/runtime-approval-flow.d.ts +1 -5
- package/dist/app/permissions/runtime-approval-flow.js +0 -28
- package/dist/app/permissions/tool-gates.d.ts +2 -3
- package/dist/app/permissions/tool-gates.js +3 -81
- package/dist/app/prompts/com-api.js +1 -1
- package/dist/app/prompts/shared-guidelines.js +7 -3
- package/dist/app/providers/google-vertex-gateway.js +4 -51
- package/dist/app/providers/model-registry.d.ts +1 -0
- package/dist/app/providers/model-registry.js +39 -0
- package/dist/app/providers/model-resolver.js +10 -7
- package/dist/app/providers/register-shortcut-provider.js +6 -6
- package/dist/app/providers/shortcut-api-v2-transport.js +4 -0
- package/dist/app/providers/shortcut-llm-proxy-client.d.ts +2 -2
- package/dist/app/providers/shortcut-llm-proxy-client.js +1 -0
- package/dist/app/resources/package-manager.js +2 -123
- package/dist/app/resources/resource-patterns.d.ts +9 -0
- package/dist/app/resources/resource-patterns.js +120 -0
- package/dist/app/session/forked-agent.d.ts +2 -2
- package/dist/app/session/model-manager.js +3 -2
- package/dist/app/session/session-lifecycle.js +3 -2
- package/dist/app/session/session-models.d.ts +2 -0
- package/dist/app/session/session-models.js +14 -6
- package/dist/app/settings-manager.d.ts +3 -3
- package/dist/app/shared/tools/execute-code/mog.d.ts +3 -1
- package/dist/app/shared/tools/execute-code/mog.js +18 -2
- package/dist/app/tools/bash.js +3 -3
- package/dist/app/tools/execute-code/index.d.ts +1 -0
- package/dist/app/tools/execute-code/index.js +3 -1
- package/dist/app/tools/find-ignore-files.d.ts +3 -0
- package/dist/app/tools/find-ignore-files.js +33 -0
- package/dist/app/tools/find.js +2 -21
- package/dist/app/tools/llm-analysis.js +0 -2
- package/dist/app/tools/refresh-context.d.ts +1 -1
- package/dist/app/tools/session-settings/update-session-settings.js +2 -2
- package/dist/app/tools/switch-mode.js +2 -2
- package/dist/app/tools/take-screenshot.js +0 -2
- package/dist/app/tools/task/runner.js +1 -2
- package/dist/app/tools/task/task.d.ts +1 -3
- package/dist/app/tools/task/task.js +20 -40
- package/dist/app/tools/web-search.js +12 -2
- package/dist/autocomplete/core.d.ts +33 -0
- package/dist/autocomplete/core.js +113 -0
- package/dist/{tui → autocomplete}/fuzzy.d.ts +0 -1
- package/dist/{tui → autocomplete}/fuzzy.js +0 -1
- package/dist/{tui/autocomplete.d.ts → autocomplete/index.d.ts} +0 -1
- package/dist/{tui/autocomplete.js → autocomplete/index.js} +62 -158
- package/dist/cli/args.js +1 -1
- package/dist/cli/list-models.js +1 -1
- package/dist/cli.js +26227 -30480
- package/dist/constants.d.ts +0 -2
- package/dist/constants.js +0 -3
- package/dist/contracts/agent-session-store.d.ts +1 -1
- package/dist/contracts/agent-settings.d.ts +1 -0
- package/dist/contracts/agent-settings.js +2 -1
- package/dist/contracts/model-call.d.ts +1 -2
- package/dist/contracts/model-call.js +1 -2
- package/dist/contracts/model-stream.d.ts +1 -0
- package/dist/contracts/model-stream.js +1 -0
- package/dist/contracts/wire.d.ts +10 -7
- package/dist/contracts/wire.js +8 -0
- package/dist/core/agent-engine.js +1 -1
- package/dist/core/core-types.d.ts +1 -21
- package/dist/core/defaults.d.ts +1 -1
- package/dist/core/defaults.js +9 -1
- package/dist/core/prompts/agent-guidelines.d.ts +4 -5
- package/dist/core/prompts/agent-guidelines.js +28 -42
- package/dist/core/session-schema.d.ts +1 -1
- package/dist/embedded-agent/ai-invoke.d.ts +1 -2
- package/dist/embedded-agent/ai-invoke.js +2 -70
- package/dist/embedded-agent/anthropic-messages-transport.d.ts +4 -20
- package/dist/embedded-agent/anthropic-messages-transport.js +23 -786
- package/dist/embedded-agent/bootstrap.js +2 -2
- package/dist/embedded-agent/compose.js +8 -7
- package/dist/embedded-agent/gateway-base-url.d.ts +3 -0
- package/dist/embedded-agent/gateway-base-url.js +35 -0
- package/dist/embedded-agent/google-vertex-transport.d.ts +2 -11
- package/dist/embedded-agent/google-vertex-transport.js +20 -117
- package/dist/embedded-agent/host-runtime-options.d.ts +0 -8
- package/dist/embedded-agent/host-runtime-options.js +10 -2
- package/dist/embedded-agent/host-tools/invoke-llm/contract.d.ts +2 -2
- package/dist/embedded-agent/host-tools/invoke-llm/contract.js +4 -2
- package/dist/embedded-agent/host-tools/sandbox-llm/contract.d.ts +8 -3
- package/dist/embedded-agent/host-tools/sandbox-llm/contract.js +12 -8
- package/dist/embedded-agent/host-tools/sandbox-llm/index.d.ts +1 -1
- package/dist/embedded-agent/host-tools/sandbox-llm/index.js +1 -1
- package/dist/embedded-agent/host-tools/shared/index.d.ts +1 -1
- package/dist/embedded-agent/host-tools/shared/index.js +1 -1
- package/dist/embedded-agent/host-tools/shared/llm-stream-error.d.ts +7 -0
- package/dist/embedded-agent/host-tools/shared/llm-stream-error.js +10 -0
- package/dist/embedded-agent/host-tools/take-screenshot/contract.d.ts +0 -2
- package/dist/embedded-agent/host-tools/take-screenshot/contract.js +1 -3
- package/dist/embedded-agent/host-tools/take-screenshot/index.d.ts +1 -1
- package/dist/embedded-agent/host-tools/take-screenshot/index.js +1 -1
- package/dist/embedded-agent/host-tools/task/agents/clone.js +1 -2
- package/dist/embedded-agent/host-tools/task/contract.js +1 -1
- package/dist/embedded-agent/index.d.ts +3 -4
- package/dist/embedded-agent/index.js +2 -3
- package/dist/embedded-agent/model-selection.d.ts +0 -6
- package/dist/embedded-agent/model-selection.js +15 -8
- package/dist/embedded-agent/openai-completions-transport.d.ts +2 -11
- package/dist/embedded-agent/openai-completions-transport.js +20 -120
- package/dist/embedded-agent/openai-responses-transport.d.ts +2 -11
- package/dist/embedded-agent/openai-responses-transport.js +15 -170
- package/dist/embedded-agent/prompt/build.js +1 -2
- package/dist/embedded-agent/prompt/sections.d.ts +1 -1
- package/dist/embedded-agent/prompt/sections.js +2 -0
- package/dist/embedded-agent/provider-native-request.d.ts +29 -0
- package/dist/embedded-agent/provider-native-request.js +65 -0
- package/dist/embedded-agent/run-stats.d.ts +1 -1
- package/dist/embedded-agent/stream.d.ts +10 -96
- package/dist/embedded-agent/stream.js +31 -556
- package/dist/embedded-agent/suggestions.d.ts +1 -1
- package/dist/embedded-agent/suggestions.js +1 -1
- package/dist/embedded-agent/worker-bridge/host-client.d.ts +7 -0
- package/dist/embedded-agent/worker-bridge/host-client.js +15 -0
- package/dist/embedded-agent/worker-bridge/worker-port.js +17 -1
- package/dist/main.js +18 -14
- package/dist/rpc/index.d.ts +1 -1
- package/dist/rpc/rpc-approval-gates.js +1 -2
- package/dist/rpc/rpc-host.d.ts +4 -0
- package/dist/rpc/rpc-host.js +13 -24
- package/dist/rpc/rpc-types.d.ts +6 -17
- package/dist/shared/platform/open.d.ts +4 -1
- package/dist/shared/platform/open.js +14 -2
- package/dist/shell/approvals/runtime-approval-gates.js +1 -3
- package/dist/shell/components/selectors/model-selector.js +2 -1
- package/dist/shell/components/selectors/session-selector-search.js +1 -1
- package/dist/shell/components/selectors/thinking-selector.js +7 -6
- package/dist/shell/index.d.ts +0 -1
- package/dist/shell/index.js +0 -1
- package/dist/shell/interactive/interactive-mode-options.d.ts +10 -0
- package/dist/shell/interactive/interactive-mode.d.ts +6 -12
- package/dist/shell/interactive/interactive-mode.js +39 -158
- package/dist/shell/interactive/slash-commands.d.ts +0 -34
- package/dist/shell/interactive/slash-commands.js +0 -2
- package/dist/shell/links/local-file-link-input.d.ts +15 -0
- package/dist/shell/links/local-file-link-input.js +38 -0
- package/dist/shell/links/local-file-link.d.ts +7 -0
- package/dist/shell/links/local-file-link.js +35 -0
- package/dist/shell/links/local-file-opener.d.ts +16 -0
- package/dist/shell/links/local-file-opener.js +90 -0
- package/dist/shell/session-client.d.ts +0 -1
- package/dist/shell/session-client.js +0 -6
- package/dist/shell/status/update-check-scheduler.d.ts +30 -0
- package/dist/shell/status/update-check-scheduler.js +71 -0
- package/dist/shell/status/update-reminder-controller.d.ts +22 -0
- package/dist/shell/status/update-reminder-controller.js +40 -0
- package/dist/shell/status/update-reminder.d.ts +6 -0
- package/dist/shell/status/update-reminder.js +4 -0
- package/dist/shell/theme/dark.json +1 -2
- package/dist/shell/theme/light.json +1 -2
- package/dist/shell/theme/runtime.d.ts +2 -3
- package/dist/shell/theme/runtime.js +2 -6
- package/dist/shell/theme/theme-schema.json +1 -6
- package/dist/shortcut-model-catalog.d.ts +7 -2
- package/dist/shortcut-model-catalog.js +134 -10
- package/dist/startup/update-manager.d.ts +6 -6
- package/dist/startup/update-manager.js +23 -38
- package/dist/startup/update-prompt.d.ts +1 -0
- package/dist/startup/update-prompt.js +2 -2
- package/dist/tui/components/editor.d.ts +1 -1
- package/dist/tui/components/editor.js +1 -1
- package/dist/tui/components/markdown.js +15 -6
- package/dist/tui/components/settings-list.js +1 -1
- package/dist/tui/editor-component.d.ts +1 -1
- package/dist/tui/index.d.ts +7 -8
- package/dist/tui/index.js +7 -6
- package/dist/tui/tui.d.ts +2 -0
- package/dist/tui/tui.js +16 -1
- package/dist/tui/utils.d.ts +7 -0
- package/dist/tui/utils.js +58 -8
- package/native-app/main/index.js +3200 -48
- package/native-app/main/{photon_rs-SoVDgheu.js → photon_rs-XkYyYTVA.js} +2 -2
- package/native-app/package.json +1 -1
- package/native-app/preload/index.cjs +2 -0
- package/native-app/renderer/assets/{index-CFc-oZuS.js → index-B4jz6epR.js} +825 -155
- package/native-app/renderer/assets/{index-OhGE0UY4.css → index-C__g36ft.css} +412 -162
- package/native-app/renderer/assets/shortcutagent-DxFsGSkw.png +0 -0
- package/native-app/renderer/index.html +2 -2
- package/package.json +17 -3
- package/skills/add-custom-model/SKILL.md +52 -0
- package/user-docs/dist/index.html +1 -1
- package/user-docs/dist/shortcutxl-docs.pdf +0 -0
- package/xll/ShortcutXL.xll +0 -0
- package/xll/modules/shortcut_xl/_managed.py +26 -7
- package/xll/modules/shortcut_xl/_tracking.py +141 -251
- package/xll/modules/shortcut_xl/api/__init__.py +60 -0
- package/xll/modules/shortcut_xl/api/workbook.py +9 -1
- package/xll/modules/shortcut_xl/api/worksheet.py +4 -1
- package/xll/python/Lib/site-packages/httpx-0.28.1.dist-info/RECORD +1 -1
- package/xll/python/Lib/site-packages/idna-3.18.dist-info/RECORD +1 -1
- package/xll/python/Lib/site-packages/pip/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/build_env/__init__.py +25 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/base.py +103 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/installer.py +333 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/noop.py +42 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/venv.py +145 -0
- package/xll/python/Lib/site-packages/pip/_internal/build_env/virtual.py +139 -0
- package/xll/python/Lib/site-packages/pip/_internal/cache.py +4 -1
- package/xll/python/Lib/site-packages/pip/_internal/cli/autocompletion.py +4 -1
- package/xll/python/Lib/site-packages/pip/_internal/cli/base_command.py +11 -14
- package/xll/python/Lib/site-packages/pip/_internal/cli/cmdoptions.py +133 -22
- package/xll/python/Lib/site-packages/pip/_internal/cli/index_command.py +11 -6
- package/xll/python/Lib/site-packages/pip/_internal/cli/main.py +2 -1
- package/xll/python/Lib/site-packages/pip/_internal/cli/main_parser.py +1 -2
- package/xll/python/Lib/site-packages/pip/_internal/cli/parser.py +10 -2
- package/xll/python/Lib/site-packages/pip/_internal/cli/progress_bars.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/cli/req_command.py +57 -25
- package/xll/python/Lib/site-packages/pip/_internal/cli/status_codes.py +1 -0
- package/xll/python/Lib/site-packages/pip/_internal/commands/cache.py +7 -6
- package/xll/python/Lib/site-packages/pip/_internal/commands/configuration.py +2 -1
- package/xll/python/Lib/site-packages/pip/_internal/commands/debug.py +4 -5
- package/xll/python/Lib/site-packages/pip/_internal/commands/download.py +4 -0
- package/xll/python/Lib/site-packages/pip/_internal/commands/freeze.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/commands/index.py +10 -3
- package/xll/python/Lib/site-packages/pip/_internal/commands/inspect.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/commands/install.py +6 -6
- package/xll/python/Lib/site-packages/pip/_internal/commands/list.py +11 -6
- package/xll/python/Lib/site-packages/pip/_internal/commands/lock.py +4 -6
- package/xll/python/Lib/site-packages/pip/_internal/commands/show.py +14 -8
- package/xll/python/Lib/site-packages/pip/_internal/commands/wheel.py +7 -1
- package/xll/python/Lib/site-packages/pip/_internal/configuration.py +2 -3
- package/xll/python/Lib/site-packages/pip/_internal/distributions/base.py +5 -3
- package/xll/python/Lib/site-packages/pip/_internal/distributions/installed.py +3 -2
- package/xll/python/Lib/site-packages/pip/_internal/distributions/sdist.py +45 -20
- package/xll/python/Lib/site-packages/pip/_internal/distributions/wheel.py +3 -2
- package/xll/python/Lib/site-packages/pip/_internal/exceptions.py +174 -0
- package/xll/python/Lib/site-packages/pip/_internal/index/collector.py +70 -48
- package/xll/python/Lib/site-packages/pip/_internal/index/package_finder.py +46 -7
- package/xll/python/Lib/site-packages/pip/_internal/index/sources.py +1 -2
- package/xll/python/Lib/site-packages/pip/_internal/locations/_sysconfig.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/locations/base.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/metadata/base.py +10 -5
- package/xll/python/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py +8 -3
- package/xll/python/Lib/site-packages/pip/_internal/models/candidate.py +5 -1
- package/xll/python/Lib/site-packages/pip/_internal/models/link.py +53 -13
- package/xll/python/Lib/site-packages/pip/_internal/network/auth.py +38 -21
- package/xll/python/Lib/site-packages/pip/_internal/network/cache.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/network/download.py +58 -11
- package/xll/python/Lib/site-packages/pip/_internal/network/session.py +35 -40
- package/xll/python/Lib/site-packages/pip/_internal/network/utils.py +109 -1
- package/xll/python/Lib/site-packages/pip/_internal/operations/check.py +2 -3
- package/xll/python/Lib/site-packages/pip/_internal/operations/install/wheel.py +23 -18
- package/xll/python/Lib/site-packages/pip/_internal/operations/prepare.py +152 -7
- package/xll/python/Lib/site-packages/pip/_internal/req/__init__.py +2 -0
- package/xll/python/Lib/site-packages/pip/_internal/req/constructors.py +54 -69
- package/xll/python/Lib/site-packages/pip/_internal/req/req_file.py +6 -6
- package/xll/python/Lib/site-packages/pip/_internal/req/req_install.py +25 -21
- package/xll/python/Lib/site-packages/pip/_internal/req/req_uninstall.py +13 -8
- package/xll/python/Lib/site-packages/pip/_internal/resolution/base.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py +1 -1
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py +0 -1
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py +39 -52
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py +3 -3
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py +3 -0
- package/xll/python/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py +9 -0
- package/xll/python/Lib/site-packages/pip/_internal/utils/compat.py +15 -9
- package/xll/python/Lib/site-packages/pip/_internal/utils/deprecation.py +6 -1
- package/xll/python/Lib/site-packages/pip/_internal/utils/filesystem.py +2 -2
- package/xll/python/Lib/site-packages/pip/_internal/utils/logging.py +11 -3
- package/xll/python/Lib/site-packages/pip/_internal/utils/misc.py +48 -4
- package/xll/python/Lib/site-packages/pip/_internal/utils/pylock.py +18 -2
- package/xll/python/Lib/site-packages/pip/_internal/utils/retry.py +2 -1
- package/xll/python/Lib/site-packages/pip/_internal/utils/subprocess.py +4 -3
- package/xll/python/Lib/site-packages/pip/_internal/utils/temp_dir.py +1 -2
- package/xll/python/Lib/site-packages/pip/_internal/utils/unpacking.py +30 -4
- package/xll/python/Lib/site-packages/pip/_internal/utils/urls.py +5 -2
- package/xll/python/Lib/site-packages/pip/_internal/utils/virtualenv.py +2 -36
- package/xll/python/Lib/site-packages/pip/_internal/vcs/git.py +8 -5
- package/xll/python/Lib/site-packages/pip/_internal/vcs/versioncontrol.py +1 -2
- package/xll/python/Lib/site-packages/pip/_internal/wheel_builder.py +5 -1
- package/xll/python/Lib/site-packages/pip/_vendor/bom.cdx.json +231 -0
- package/xll/python/Lib/site-packages/pip/_vendor/certifi/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/certifi/cacert.pem +0 -631
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/compat.py +34 -64
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/resources.py +28 -14
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/scripts.py +7 -3
- package/xll/python/Lib/site-packages/pip/_vendor/distlib/util.py +48 -11
- package/xll/python/Lib/site-packages/pip/_vendor/idna/LICENSE.md +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/idna/__main__.py +6 -0
- package/xll/python/Lib/site-packages/pip/_vendor/idna/cli.py +128 -0
- package/xll/python/Lib/site-packages/pip/_vendor/idna/codec.py +50 -13
- package/xll/python/Lib/site-packages/pip/_vendor/idna/compat.py +26 -0
- package/xll/python/Lib/site-packages/pip/_vendor/idna/core.py +352 -141
- package/xll/python/Lib/site-packages/pip/_vendor/idna/idnadata.py +571 -2983
- package/xll/python/Lib/site-packages/pip/_vendor/idna/intranges.py +5 -7
- package/xll/python/Lib/site-packages/pip/_vendor/idna/package_data.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/idna/uts46data.py +16887 -8832
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/__init__.py +352 -66
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/__main__.py +11 -0
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/_xdg.py +171 -0
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/android.py +92 -41
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/api.py +213 -49
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/macos.py +128 -51
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/unix.py +176 -127
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/version.py +8 -18
- package/xll/python/Lib/site-packages/pip/_vendor/platformdirs/windows.py +185 -68
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/__init__.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/__main__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/console.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/filter.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py +10 -8
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/formatter.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/lexer.py +7 -5
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py +9 -8
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/lexers/python.py +35 -32
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/modeline.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/plugin.py +3 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/regexopt.py +13 -2
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/scanner.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/sphinxext.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/style.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/token.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/unistring.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/pygments/util.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/requests/__init__.py +52 -16
- package/xll/python/Lib/site-packages/pip/_vendor/requests/__version__.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/requests/_internal_utils.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/requests/_types.py +183 -0
- package/xll/python/Lib/site-packages/pip/_vendor/requests/adapters.py +101 -50
- package/xll/python/Lib/site-packages/pip/_vendor/requests/api.py +31 -8
- package/xll/python/Lib/site-packages/pip/_vendor/requests/auth.py +80 -40
- package/xll/python/Lib/site-packages/pip/_vendor/requests/compat.py +9 -3
- package/xll/python/Lib/site-packages/pip/_vendor/requests/cookies.py +143 -79
- package/xll/python/Lib/site-packages/pip/_vendor/requests/exceptions.py +15 -5
- package/xll/python/Lib/site-packages/pip/_vendor/requests/help.py +13 -10
- package/xll/python/Lib/site-packages/pip/_vendor/requests/hooks.py +23 -9
- package/xll/python/Lib/site-packages/pip/_vendor/requests/models.py +265 -126
- package/xll/python/Lib/site-packages/pip/_vendor/requests/py.typed +0 -0
- package/xll/python/Lib/site-packages/pip/_vendor/requests/sessions.py +164 -78
- package/xll/python/Lib/site-packages/pip/_vendor/requests/status_codes.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/requests/structures.py +51 -20
- package/xll/python/Lib/site-packages/pip/_vendor/requests/utils.py +161 -89
- package/xll/python/Lib/site-packages/pip/_vendor/tomli/__init__.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/tomli/_parser.py +9 -4
- package/xll/python/Lib/site-packages/pip/_vendor/tomli/_re.py +13 -9
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/_base_connection.py +3 -1
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/_collections.py +0 -1
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/_version.py +8 -18
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/connection.py +4 -4
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py +23 -10
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/contrib/emscripten/response.py +5 -1
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py +7 -8
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py +1 -1
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/exceptions.py +2 -2
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/fields.py +14 -14
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py +8 -6
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/response.py +35 -22
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/util/retry.py +8 -0
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py +11 -61
- package/xll/python/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py +5 -11
- package/xll/python/Lib/site-packages/pip/_vendor/vendor.txt +8 -8
- package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/METADATA +3 -2
- package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/RECORD +208 -188
- package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/AUTHORS.txt +20 -0
- package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/idna/LICENSE.md +1 -1
- package/xll/python/Lib/site-packages/pywin32-311.dist-info/RECORD +2 -2
- package/xll/python/Scripts/httpx.exe +0 -0
- package/xll/python/Scripts/idna.exe +0 -0
- package/xll/python/Scripts/pip.exe +0 -0
- package/xll/python/Scripts/pip3.13.exe +0 -0
- package/xll/python/Scripts/pip3.exe +0 -0
- package/xll/python/Scripts/pywin32_postinstall.exe +0 -0
- package/xll/python/Scripts/pywin32_testall.exe +0 -0
- package/dist/app/collab/awareness.d.ts +0 -32
- package/dist/app/collab/awareness.js +0 -52
- package/dist/app/collab/collab-client.d.ts +0 -37
- package/dist/app/collab/collab-client.js +0 -208
- package/dist/app/collab/collab-manager.d.ts +0 -91
- package/dist/app/collab/collab-manager.js +0 -218
- package/dist/app/collab/collab-sync.d.ts +0 -62
- package/dist/app/collab/collab-sync.js +0 -215
- package/dist/app/collab/index.d.ts +0 -9
- package/dist/app/collab/index.js +0 -6
- package/dist/app/collab/super-fight.d.ts +0 -90
- package/dist/app/collab/super-fight.js +0 -310
- package/dist/app/collab/sync-bridge.d.ts +0 -35
- package/dist/app/collab/sync-bridge.js +0 -109
- package/dist/app/collab/types.d.ts +0 -75
- package/dist/app/collab/types.js +0 -5
- package/dist/embedded-agent/ai-content.d.ts +0 -52
- package/dist/embedded-agent/ai-content.js +0 -101
- package/dist/embedded-agent/host-tools/shared/llm-stream.d.ts +0 -31
- package/dist/embedded-agent/host-tools/shared/llm-stream.js +0 -136
- package/dist/embedded-agent/model-call-orchestrator.d.ts +0 -22
- package/dist/embedded-agent/model-call-orchestrator.js +0 -22
- package/dist/embedded-agent/stream-errors.d.ts +0 -10
- package/dist/embedded-agent/stream-errors.js +0 -73
- package/dist/embedded-agent/stream-message-state.d.ts +0 -14
- package/dist/embedded-agent/stream-message-state.js +0 -271
- package/dist/embedded-agent/stream-sse.d.ts +0 -78
- package/dist/embedded-agent/stream-sse.js +0 -73
- package/dist/shell/approvals/task-spawn-approval.d.ts +0 -20
- package/dist/shell/approvals/task-spawn-approval.js +0 -93
- package/dist/shell/interactive/collab-command.d.ts +0 -9
- package/dist/shell/interactive/collab-command.js +0 -115
- package/dist/shell/interactive/super-fight-ui.d.ts +0 -80
- package/dist/shell/interactive/super-fight-ui.js +0 -484
- package/dist/shell/status/collab-status.d.ts +0 -18
- package/dist/shell/status/collab-status.js +0 -46
- package/xll/python/Lib/site-packages/pip/_internal/build_env.py +0 -606
- /package/dist/{tui → autocomplete}/skill-autocomplete.js +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/INSTALLER +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/REQUESTED +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/WHEEL +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/entry_points.txt +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/LICENSE.txt +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/certifi/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/distlib/LICENSE.txt +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/distro/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/msgpack/COPYING +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.BSD +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/pkg_resources/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/platformdirs/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/pygments/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/requests/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/resolvelib/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/rich/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/tomli/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/tomli_w/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/truststore/LICENSE +0 -0
- /package/xll/python/Lib/site-packages/{pip-26.1.2.dist-info → pip-26.2.dist-info}/licenses/src/pip/_vendor/urllib3/LICENSE.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import bisect
|
|
2
2
|
import re
|
|
3
3
|
import unicodedata
|
|
4
|
+
import warnings
|
|
4
5
|
from typing import Optional, Union
|
|
5
6
|
|
|
6
7
|
from . import idnadata
|
|
@@ -8,38 +9,49 @@ from .intranges import intranges_contain
|
|
|
8
9
|
|
|
9
10
|
_virama_combining_class = 9
|
|
10
11
|
_alabel_prefix = b"xn--"
|
|
12
|
+
_max_input_length = 1024
|
|
11
13
|
_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]")
|
|
12
14
|
|
|
13
15
|
|
|
16
|
+
# Bidi category sets from RFC 5893, hoisted out of the per-codepoint loop
|
|
17
|
+
_bidi_rtl_first = frozenset({"R", "AL"})
|
|
18
|
+
_bidi_rtl_categories = frozenset({"R", "AL", "AN"})
|
|
19
|
+
_bidi_rtl_allowed = frozenset({"R", "AL", "AN", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"})
|
|
20
|
+
_bidi_rtl_valid_ending = frozenset({"R", "AL", "EN", "AN"})
|
|
21
|
+
_bidi_rtl_numeric = frozenset({"AN", "EN"})
|
|
22
|
+
_bidi_ltr_allowed = frozenset({"L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"})
|
|
23
|
+
_bidi_ltr_valid_ending = frozenset({"L", "EN"})
|
|
24
|
+
_bidi_joiner_l_or_d = frozenset({"L", "D"})
|
|
25
|
+
_bidi_joiner_r_or_d = frozenset({"R", "D"})
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _joining_type(cp: int) -> Optional[str]:
|
|
29
|
+
for jt, ranges in idnadata.joining_types.items():
|
|
30
|
+
if intranges_contain(cp, ranges):
|
|
31
|
+
return jt
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
|
|
14
35
|
class IDNAError(UnicodeError):
|
|
15
36
|
"""Base exception for all IDNA-encoding related problems"""
|
|
16
37
|
|
|
17
|
-
pass
|
|
18
|
-
|
|
19
38
|
|
|
20
39
|
class IDNABidiError(IDNAError):
|
|
21
40
|
"""Exception when bidirectional requirements are not satisfied"""
|
|
22
41
|
|
|
23
|
-
pass
|
|
24
|
-
|
|
25
42
|
|
|
26
43
|
class InvalidCodepoint(IDNAError):
|
|
27
44
|
"""Exception when a disallowed or unallocated codepoint is used"""
|
|
28
45
|
|
|
29
|
-
pass
|
|
30
|
-
|
|
31
46
|
|
|
32
47
|
class InvalidCodepointContext(IDNAError):
|
|
33
48
|
"""Exception when the codepoint is not valid in the context it is used"""
|
|
34
49
|
|
|
35
|
-
pass
|
|
36
|
-
|
|
37
50
|
|
|
38
51
|
def _combining_class(cp: int) -> int:
|
|
39
52
|
v = unicodedata.combining(chr(cp))
|
|
40
|
-
if v == 0:
|
|
41
|
-
|
|
42
|
-
raise ValueError("Unknown character in unicodedata")
|
|
53
|
+
if v == 0 and not unicodedata.name(chr(cp)):
|
|
54
|
+
raise ValueError("Unknown character in unicodedata")
|
|
43
55
|
return v
|
|
44
56
|
|
|
45
57
|
|
|
@@ -52,42 +64,76 @@ def _punycode(s: str) -> bytes:
|
|
|
52
64
|
|
|
53
65
|
|
|
54
66
|
def _unot(s: int) -> str:
|
|
55
|
-
return "U+{:04X}"
|
|
67
|
+
return f"U+{s:04X}"
|
|
56
68
|
|
|
57
69
|
|
|
58
70
|
def valid_label_length(label: Union[bytes, str]) -> bool:
|
|
59
|
-
|
|
60
|
-
return False
|
|
61
|
-
return True
|
|
71
|
+
"""Check that a label does not exceed the maximum permitted length.
|
|
62
72
|
|
|
73
|
+
Per :rfc:`1035` (and :rfc:`5891` §4.2.4) a DNS label must not exceed
|
|
74
|
+
63 octets. The argument may be either a :class:`str` (a U-label, where
|
|
75
|
+
length is measured in characters) or :class:`bytes` (an A-label, where
|
|
76
|
+
length is measured in octets).
|
|
63
77
|
|
|
64
|
-
|
|
65
|
-
if
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
:param label: The label to check.
|
|
79
|
+
:returns: ``True`` if the label is within the length limit, otherwise
|
|
80
|
+
``False``.
|
|
81
|
+
"""
|
|
82
|
+
return len(label) <= 63
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def valid_string_length(domain: Union[bytes, str], trailing_dot: bool) -> bool:
|
|
86
|
+
"""Check that a full domain name does not exceed the maximum length.
|
|
87
|
+
|
|
88
|
+
Per :rfc:`1035`, a domain name is limited to 253 octets when no trailing
|
|
89
|
+
dot is present, or 254 octets when one is included.
|
|
90
|
+
|
|
91
|
+
:param domain: The full (possibly multi-label) domain name.
|
|
92
|
+
:param trailing_dot: ``True`` if ``domain`` includes a trailing ``.``.
|
|
93
|
+
:returns: ``True`` if the domain is within the length limit, otherwise
|
|
94
|
+
``False``.
|
|
95
|
+
"""
|
|
96
|
+
return len(domain) <= (254 if trailing_dot else 253)
|
|
68
97
|
|
|
69
98
|
|
|
70
99
|
def check_bidi(label: str, check_ltr: bool = False) -> bool:
|
|
100
|
+
"""Validate the Bidi Rule from :rfc:`5893` for a single label.
|
|
101
|
+
|
|
102
|
+
The Bidi Rule constrains how bidirectional characters (Hebrew, Arabic,
|
|
103
|
+
etc.) may appear within a label. By default the check is only applied
|
|
104
|
+
when the label contains at least one right-to-left character (Unicode
|
|
105
|
+
bidirectional categories ``R``, ``AL``, or ``AN``); set ``check_ltr``
|
|
106
|
+
to ``True`` to apply it to LTR-only labels as well.
|
|
107
|
+
|
|
108
|
+
:param label: The label to validate, as a Unicode string.
|
|
109
|
+
:param check_ltr: If ``True``, apply the rules even when the label
|
|
110
|
+
contains no RTL characters.
|
|
111
|
+
:returns: ``True`` if the label satisfies the Bidi Rule.
|
|
112
|
+
:raises IDNABidiError: If any of Bidi Rule conditions 1-6 are violated,
|
|
113
|
+
or if the directional category of a codepoint cannot be determined.
|
|
114
|
+
"""
|
|
115
|
+
if len(label) > _max_input_length:
|
|
116
|
+
raise IDNAError("Label too long")
|
|
71
117
|
# Bidi rules should only be applied if string contains RTL characters
|
|
72
118
|
bidi_label = False
|
|
73
119
|
for idx, cp in enumerate(label, 1):
|
|
74
120
|
direction = unicodedata.bidirectional(cp)
|
|
75
121
|
if direction == "":
|
|
76
122
|
# String likely comes from a newer version of Unicode
|
|
77
|
-
raise IDNABidiError("Unknown directionality in label {} at position {}"
|
|
78
|
-
if direction in
|
|
123
|
+
raise IDNABidiError(f"Unknown directionality in label {label!r} at position {idx}")
|
|
124
|
+
if direction in _bidi_rtl_categories:
|
|
79
125
|
bidi_label = True
|
|
80
126
|
if not bidi_label and not check_ltr:
|
|
81
127
|
return True
|
|
82
128
|
|
|
83
129
|
# Bidi rule 1
|
|
84
130
|
direction = unicodedata.bidirectional(label[0])
|
|
85
|
-
if direction in
|
|
131
|
+
if direction in _bidi_rtl_first:
|
|
86
132
|
rtl = True
|
|
87
133
|
elif direction == "L":
|
|
88
134
|
rtl = False
|
|
89
135
|
else:
|
|
90
|
-
raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL"
|
|
136
|
+
raise IDNABidiError(f"First codepoint in label {label!r} must be directionality L, R or AL")
|
|
91
137
|
|
|
92
138
|
valid_ending = False
|
|
93
139
|
number_type: Optional[str] = None
|
|
@@ -96,37 +142,25 @@ def check_bidi(label: str, check_ltr: bool = False) -> bool:
|
|
|
96
142
|
|
|
97
143
|
if rtl:
|
|
98
144
|
# Bidi rule 2
|
|
99
|
-
if direction not in
|
|
100
|
-
"
|
|
101
|
-
"AL",
|
|
102
|
-
"AN",
|
|
103
|
-
"EN",
|
|
104
|
-
"ES",
|
|
105
|
-
"CS",
|
|
106
|
-
"ET",
|
|
107
|
-
"ON",
|
|
108
|
-
"BN",
|
|
109
|
-
"NSM",
|
|
110
|
-
]:
|
|
111
|
-
raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx))
|
|
145
|
+
if direction not in _bidi_rtl_allowed:
|
|
146
|
+
raise IDNABidiError(f"Invalid direction for codepoint at position {idx} in a right-to-left label")
|
|
112
147
|
# Bidi rule 3
|
|
113
|
-
if direction in
|
|
148
|
+
if direction in _bidi_rtl_valid_ending:
|
|
114
149
|
valid_ending = True
|
|
115
150
|
elif direction != "NSM":
|
|
116
151
|
valid_ending = False
|
|
117
152
|
# Bidi rule 4
|
|
118
|
-
if direction in
|
|
153
|
+
if direction in _bidi_rtl_numeric:
|
|
119
154
|
if not number_type:
|
|
120
155
|
number_type = direction
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
raise IDNABidiError("Can not mix numeral types in a right-to-left label")
|
|
156
|
+
elif number_type != direction:
|
|
157
|
+
raise IDNABidiError("Can not mix numeral types in a right-to-left label")
|
|
124
158
|
else:
|
|
125
159
|
# Bidi rule 5
|
|
126
|
-
if direction not in
|
|
127
|
-
raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label"
|
|
160
|
+
if direction not in _bidi_ltr_allowed:
|
|
161
|
+
raise IDNABidiError(f"Invalid direction for codepoint at position {idx} in a left-to-right label")
|
|
128
162
|
# Bidi rule 6
|
|
129
|
-
if direction in
|
|
163
|
+
if direction in _bidi_ltr_valid_ending:
|
|
130
164
|
valid_ending = True
|
|
131
165
|
elif direction != "NSM":
|
|
132
166
|
valid_ending = False
|
|
@@ -138,12 +172,31 @@ def check_bidi(label: str, check_ltr: bool = False) -> bool:
|
|
|
138
172
|
|
|
139
173
|
|
|
140
174
|
def check_initial_combiner(label: str) -> bool:
|
|
175
|
+
"""Reject labels that begin with a combining mark.
|
|
176
|
+
|
|
177
|
+
Per :rfc:`5891` §4.2.3.2 a label must not start with a character of
|
|
178
|
+
Unicode general category ``M`` (Mark).
|
|
179
|
+
|
|
180
|
+
:param label: The label to check.
|
|
181
|
+
:returns: ``True`` if the first character is not a combining mark.
|
|
182
|
+
:raises IDNAError: If the label begins with a combining character.
|
|
183
|
+
"""
|
|
141
184
|
if unicodedata.category(label[0])[0] == "M":
|
|
142
185
|
raise IDNAError("Label begins with an illegal combining character")
|
|
143
186
|
return True
|
|
144
187
|
|
|
145
188
|
|
|
146
189
|
def check_hyphen_ok(label: str) -> bool:
|
|
190
|
+
"""Validate the hyphen restrictions for a label.
|
|
191
|
+
|
|
192
|
+
Per :rfc:`5891` §4.2.3.1 a label must not start or end with a hyphen
|
|
193
|
+
(``U+002D``), and must not have hyphens in both the third and fourth
|
|
194
|
+
positions (the prefix reserved for A-labels).
|
|
195
|
+
|
|
196
|
+
:param label: The label to check.
|
|
197
|
+
:returns: ``True`` if the hyphen restrictions are satisfied.
|
|
198
|
+
:raises IDNAError: If any of the hyphen restrictions are violated.
|
|
199
|
+
"""
|
|
147
200
|
if label[2:4] == "--":
|
|
148
201
|
raise IDNAError("Label has disallowed hyphens in 3rd and 4th position")
|
|
149
202
|
if label[0] == "-" or label[-1] == "-":
|
|
@@ -152,74 +205,104 @@ def check_hyphen_ok(label: str) -> bool:
|
|
|
152
205
|
|
|
153
206
|
|
|
154
207
|
def check_nfc(label: str) -> None:
|
|
208
|
+
"""Require that a label is in Unicode Normalization Form C.
|
|
209
|
+
|
|
210
|
+
:param label: The label to check.
|
|
211
|
+
:raises IDNAError: If ``label`` differs from its NFC normalisation.
|
|
212
|
+
"""
|
|
213
|
+
if len(label) > _max_input_length:
|
|
214
|
+
raise IDNAError("Label too long")
|
|
155
215
|
if unicodedata.normalize("NFC", label) != label:
|
|
156
216
|
raise IDNAError("Label must be in Normalization Form C")
|
|
157
217
|
|
|
158
218
|
|
|
159
219
|
def valid_contextj(label: str, pos: int) -> bool:
|
|
220
|
+
"""Validate the CONTEXTJ rules from :rfc:`5892` Appendix A.
|
|
221
|
+
|
|
222
|
+
These rules govern the contextual use of the joiner codepoints
|
|
223
|
+
``U+200C`` (ZERO WIDTH NON-JOINER, Appendix A.1) and ``U+200D``
|
|
224
|
+
(ZERO WIDTH JOINER, Appendix A.2) within a label.
|
|
225
|
+
|
|
226
|
+
:param label: The label containing the codepoint.
|
|
227
|
+
:param pos: Index of the joiner codepoint within ``label``.
|
|
228
|
+
:returns: ``True`` if the codepoint at ``pos`` satisfies its CONTEXTJ
|
|
229
|
+
rule, ``False`` otherwise (including when the codepoint at
|
|
230
|
+
``pos`` is not a recognised joiner).
|
|
231
|
+
:raises ValueError: If an adjacent codepoint has no Unicode name when
|
|
232
|
+
determining its combining class.
|
|
233
|
+
:raises IDNAError: If ``label`` exceeds the defensive input length limit.
|
|
234
|
+
"""
|
|
235
|
+
if len(label) > _max_input_length:
|
|
236
|
+
raise IDNAError("Label too long")
|
|
160
237
|
cp_value = ord(label[pos])
|
|
161
238
|
|
|
162
239
|
if cp_value == 0x200C:
|
|
163
|
-
if pos > 0:
|
|
164
|
-
|
|
165
|
-
return True
|
|
240
|
+
if pos > 0 and _combining_class(ord(label[pos - 1])) == _virama_combining_class:
|
|
241
|
+
return True
|
|
166
242
|
|
|
167
243
|
ok = False
|
|
168
244
|
for i in range(pos - 1, -1, -1):
|
|
169
|
-
joining_type =
|
|
170
|
-
if joining_type ==
|
|
245
|
+
joining_type = _joining_type(ord(label[i]))
|
|
246
|
+
if joining_type == "T":
|
|
171
247
|
continue
|
|
172
|
-
|
|
248
|
+
if joining_type in _bidi_joiner_l_or_d:
|
|
173
249
|
ok = True
|
|
174
250
|
break
|
|
175
|
-
|
|
176
|
-
break
|
|
251
|
+
break
|
|
177
252
|
|
|
178
253
|
if not ok:
|
|
179
254
|
return False
|
|
180
255
|
|
|
181
256
|
ok = False
|
|
182
257
|
for i in range(pos + 1, len(label)):
|
|
183
|
-
joining_type =
|
|
184
|
-
if joining_type ==
|
|
258
|
+
joining_type = _joining_type(ord(label[i]))
|
|
259
|
+
if joining_type == "T":
|
|
185
260
|
continue
|
|
186
|
-
|
|
261
|
+
if joining_type in _bidi_joiner_r_or_d:
|
|
187
262
|
ok = True
|
|
188
263
|
break
|
|
189
|
-
|
|
190
|
-
break
|
|
264
|
+
break
|
|
191
265
|
return ok
|
|
192
266
|
|
|
193
267
|
if cp_value == 0x200D:
|
|
194
|
-
|
|
195
|
-
if _combining_class(ord(label[pos - 1])) == _virama_combining_class:
|
|
196
|
-
return True
|
|
197
|
-
return False
|
|
268
|
+
return pos > 0 and _combining_class(ord(label[pos - 1])) == _virama_combining_class
|
|
198
269
|
|
|
199
|
-
|
|
200
|
-
return False
|
|
270
|
+
return False
|
|
201
271
|
|
|
202
272
|
|
|
203
273
|
def valid_contexto(label: str, pos: int, exception: bool = False) -> bool:
|
|
274
|
+
"""Validate the CONTEXTO rules from :rfc:`5892` Appendix A.
|
|
275
|
+
|
|
276
|
+
Covers the contextual rules for codepoints such as MIDDLE DOT
|
|
277
|
+
(``U+00B7``), Greek lower numeral sign, Hebrew punctuation, Katakana
|
|
278
|
+
middle dot, and the Arabic-Indic / Extended Arabic-Indic digit ranges.
|
|
279
|
+
|
|
280
|
+
:param label: The label containing the codepoint.
|
|
281
|
+
:param pos: Index of the codepoint within ``label``.
|
|
282
|
+
:param exception: Reserved for forward compatibility; currently unused.
|
|
283
|
+
:returns: ``True`` if the codepoint at ``pos`` satisfies its CONTEXTO
|
|
284
|
+
rule, ``False`` otherwise (including when the codepoint is not a
|
|
285
|
+
recognised CONTEXTO codepoint).
|
|
286
|
+
:raises IDNAError: If ``label`` exceeds the defensive input length limit.
|
|
287
|
+
"""
|
|
288
|
+
if len(label) > _max_input_length:
|
|
289
|
+
raise IDNAError("Label too long")
|
|
204
290
|
cp_value = ord(label[pos])
|
|
205
291
|
|
|
206
292
|
if cp_value == 0x00B7:
|
|
207
|
-
|
|
208
|
-
if ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C:
|
|
209
|
-
return True
|
|
210
|
-
return False
|
|
293
|
+
return 0 < pos < len(label) - 1 and ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C
|
|
211
294
|
|
|
212
|
-
|
|
295
|
+
if cp_value == 0x0375:
|
|
213
296
|
if pos < len(label) - 1 and len(label) > 1:
|
|
214
297
|
return _is_script(label[pos + 1], "Greek")
|
|
215
298
|
return False
|
|
216
299
|
|
|
217
|
-
|
|
300
|
+
if cp_value in {0x05F3, 0x05F4}:
|
|
218
301
|
if pos > 0:
|
|
219
302
|
return _is_script(label[pos - 1], "Hebrew")
|
|
220
303
|
return False
|
|
221
304
|
|
|
222
|
-
|
|
305
|
+
if cp_value == 0x30FB:
|
|
223
306
|
for cp in label:
|
|
224
307
|
if cp == "\u30fb":
|
|
225
308
|
continue
|
|
@@ -227,27 +310,45 @@ def valid_contexto(label: str, pos: int, exception: bool = False) -> bool:
|
|
|
227
310
|
return True
|
|
228
311
|
return False
|
|
229
312
|
|
|
230
|
-
|
|
231
|
-
for cp in label
|
|
232
|
-
if 0x6F0 <= ord(cp) <= 0x06F9:
|
|
233
|
-
return False
|
|
234
|
-
return True
|
|
313
|
+
if 0x660 <= cp_value <= 0x669:
|
|
314
|
+
return not any(0x6F0 <= ord(cp) <= 0x06F9 for cp in label)
|
|
235
315
|
|
|
236
|
-
|
|
237
|
-
for cp in label
|
|
238
|
-
if 0x660 <= ord(cp) <= 0x0669:
|
|
239
|
-
return False
|
|
240
|
-
return True
|
|
316
|
+
if 0x6F0 <= cp_value <= 0x6F9:
|
|
317
|
+
return not any(0x660 <= ord(cp) <= 0x0669 for cp in label)
|
|
241
318
|
|
|
242
319
|
return False
|
|
243
320
|
|
|
244
321
|
|
|
245
322
|
def check_label(label: Union[str, bytes, bytearray]) -> None:
|
|
323
|
+
"""Run the full set of IDNA 2008 validity checks on a single label.
|
|
324
|
+
|
|
325
|
+
Applies, in order: NFC normalisation (:func:`check_nfc`), hyphen
|
|
326
|
+
restrictions (:func:`check_hyphen_ok`), the no-leading-combiner rule
|
|
327
|
+
(:func:`check_initial_combiner`), per-codepoint validity (PVALID,
|
|
328
|
+
CONTEXTJ, CONTEXTO classes from :rfc:`5892`), and the Bidi Rule
|
|
329
|
+
(:func:`check_bidi`).
|
|
330
|
+
|
|
331
|
+
:param label: The label to validate. ``bytes`` or ``bytearray`` input
|
|
332
|
+
is decoded as UTF-8 first.
|
|
333
|
+
:raises IDNAError: If the label is empty or fails a structural rule.
|
|
334
|
+
:raises InvalidCodepoint: If the label contains a DISALLOWED or
|
|
335
|
+
UNASSIGNED codepoint.
|
|
336
|
+
:raises InvalidCodepointContext: If a CONTEXTJ or CONTEXTO codepoint
|
|
337
|
+
is not valid in its context.
|
|
338
|
+
:raises IDNABidiError: If the Bidi Rule is violated.
|
|
339
|
+
"""
|
|
340
|
+
if len(label) > _max_input_length:
|
|
341
|
+
raise IDNAError("Label too long")
|
|
246
342
|
if isinstance(label, (bytes, bytearray)):
|
|
247
343
|
label = label.decode("utf-8")
|
|
248
344
|
if len(label) == 0:
|
|
249
345
|
raise IDNAError("Empty Label")
|
|
250
346
|
|
|
347
|
+
# Reject on domain length rather than label length so support some UTS 46
|
|
348
|
+
# use cases, still reducing processing of label contextual rules
|
|
349
|
+
if not valid_string_length(label, trailing_dot=True):
|
|
350
|
+
raise IDNAError("Label too long")
|
|
351
|
+
|
|
251
352
|
check_nfc(label)
|
|
252
353
|
check_hyphen_ok(label)
|
|
253
354
|
check_initial_combiner(label)
|
|
@@ -256,40 +357,47 @@ def check_label(label: Union[str, bytes, bytearray]) -> None:
|
|
|
256
357
|
cp_value = ord(cp)
|
|
257
358
|
if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]):
|
|
258
359
|
continue
|
|
259
|
-
|
|
360
|
+
if intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]):
|
|
260
361
|
try:
|
|
261
362
|
if not valid_contextj(label, pos):
|
|
262
|
-
raise InvalidCodepointContext(
|
|
263
|
-
|
|
264
|
-
)
|
|
265
|
-
except ValueError:
|
|
363
|
+
raise InvalidCodepointContext(f"Joiner {_unot(cp_value)} not allowed at position {pos + 1} in {label!r}")
|
|
364
|
+
except ValueError as err:
|
|
266
365
|
raise IDNAError(
|
|
267
|
-
"Unknown codepoint adjacent to joiner {} at position {} in {}"
|
|
268
|
-
|
|
269
|
-
)
|
|
270
|
-
)
|
|
366
|
+
f"Unknown codepoint adjacent to joiner {_unot(cp_value)} at position {pos + 1} in {label!r}"
|
|
367
|
+
) from err
|
|
271
368
|
elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]):
|
|
272
369
|
if not valid_contexto(label, pos):
|
|
273
|
-
raise InvalidCodepointContext(
|
|
274
|
-
"Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label))
|
|
275
|
-
)
|
|
370
|
+
raise InvalidCodepointContext(f"Codepoint {_unot(cp_value)} not allowed at position {pos + 1} in {label!r}")
|
|
276
371
|
else:
|
|
277
|
-
raise InvalidCodepoint(
|
|
278
|
-
"Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label))
|
|
279
|
-
)
|
|
372
|
+
raise InvalidCodepoint(f"Codepoint {_unot(cp_value)} at position {pos + 1} of {label!r} not allowed")
|
|
280
373
|
|
|
281
374
|
check_bidi(label)
|
|
282
375
|
|
|
283
376
|
|
|
284
377
|
def alabel(label: str) -> bytes:
|
|
378
|
+
"""Convert a single U-label into its A-label form.
|
|
379
|
+
|
|
380
|
+
The result is the ASCII-Compatible Encoding (ACE) form per :rfc:`5891`
|
|
381
|
+
§4: the label is validated, Punycode-encoded, and prefixed with
|
|
382
|
+
``xn--``. Pure ASCII labels that are already valid IDNA labels are
|
|
383
|
+
returned unchanged (as :class:`bytes`).
|
|
384
|
+
|
|
385
|
+
:param label: The label to convert, as a Unicode string.
|
|
386
|
+
:returns: The A-label as ASCII-encoded :class:`bytes`.
|
|
387
|
+
:raises IDNAError: If the label is invalid or the resulting A-label
|
|
388
|
+
exceeds 63 octets.
|
|
389
|
+
"""
|
|
390
|
+
if len(label) > _max_input_length:
|
|
391
|
+
raise IDNAError("Label too long")
|
|
285
392
|
try:
|
|
286
393
|
label_bytes = label.encode("ascii")
|
|
394
|
+
except UnicodeEncodeError:
|
|
395
|
+
pass
|
|
396
|
+
else:
|
|
287
397
|
ulabel(label_bytes)
|
|
288
398
|
if not valid_label_length(label_bytes):
|
|
289
399
|
raise IDNAError("Label too long")
|
|
290
400
|
return label_bytes
|
|
291
|
-
except UnicodeEncodeError:
|
|
292
|
-
pass
|
|
293
401
|
|
|
294
402
|
check_label(label)
|
|
295
403
|
label_bytes = _alabel_prefix + _punycode(label)
|
|
@@ -301,6 +409,20 @@ def alabel(label: str) -> bytes:
|
|
|
301
409
|
|
|
302
410
|
|
|
303
411
|
def ulabel(label: Union[str, bytes, bytearray]) -> str:
|
|
412
|
+
"""Convert a single A-label into its U-label form.
|
|
413
|
+
|
|
414
|
+
Performs the inverse of :func:`alabel`: an ``xn--``-prefixed label is
|
|
415
|
+
Punycode-decoded and validated. Labels that are already Unicode (or
|
|
416
|
+
plain ASCII without the ACE prefix) are validated and returned as a
|
|
417
|
+
Unicode string.
|
|
418
|
+
|
|
419
|
+
:param label: The label to convert. ``bytes`` or ``bytearray`` input
|
|
420
|
+
is treated as ASCII.
|
|
421
|
+
:returns: The U-label as a Unicode string.
|
|
422
|
+
:raises IDNAError: If the label is malformed or fails validation.
|
|
423
|
+
"""
|
|
424
|
+
if len(label) > _max_input_length:
|
|
425
|
+
raise IDNAError("Label too long")
|
|
304
426
|
if not isinstance(label, (bytes, bytearray)):
|
|
305
427
|
try:
|
|
306
428
|
label_bytes = label.encode("ascii")
|
|
@@ -315,7 +437,7 @@ def ulabel(label: Union[str, bytes, bytearray]) -> str:
|
|
|
315
437
|
label_bytes = label_bytes[len(_alabel_prefix) :]
|
|
316
438
|
if not label_bytes:
|
|
317
439
|
raise IDNAError("Malformed A-label, no Punycode eligible content found")
|
|
318
|
-
if label_bytes.
|
|
440
|
+
if label_bytes.endswith(b"-"):
|
|
319
441
|
raise IDNAError("A-label must not end with a hyphen")
|
|
320
442
|
else:
|
|
321
443
|
check_label(label_bytes)
|
|
@@ -323,42 +445,64 @@ def ulabel(label: Union[str, bytes, bytearray]) -> str:
|
|
|
323
445
|
|
|
324
446
|
try:
|
|
325
447
|
label = label_bytes.decode("punycode")
|
|
326
|
-
except UnicodeError:
|
|
327
|
-
raise IDNAError("Invalid A-label")
|
|
448
|
+
except UnicodeError as err:
|
|
449
|
+
raise IDNAError("Invalid A-label") from err
|
|
328
450
|
check_label(label)
|
|
329
451
|
return label
|
|
330
452
|
|
|
331
453
|
|
|
332
454
|
def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str:
|
|
333
|
-
"""
|
|
334
|
-
|
|
455
|
+
"""Apply the UTS #46 character mapping to a domain string.
|
|
456
|
+
|
|
457
|
+
Implements the mapping table from `UTS #46 §4
|
|
458
|
+
<https://www.unicode.org/reports/tr46/>`_: each character is kept,
|
|
459
|
+
replaced, or rejected based on its status (``V``, ``M``, ``D``, ``3``,
|
|
460
|
+
``I``). The result is returned in Normalisation Form C.
|
|
461
|
+
|
|
462
|
+
:param domain: The full domain name to remap.
|
|
463
|
+
:param std3_rules: If ``True``, apply the stricter STD3 ASCII rules
|
|
464
|
+
(status ``3`` codepoints raise instead of being kept or mapped).
|
|
465
|
+
:param transitional: If ``True``, use transitional processing (status
|
|
466
|
+
``D`` codepoints are mapped instead of kept). Transitional
|
|
467
|
+
processing has been removed from UTS #46 and this option is
|
|
468
|
+
retained only for backwards compatibility.
|
|
469
|
+
:returns: The remapped domain, in Normalisation Form C.
|
|
470
|
+
:raises InvalidCodepoint: If the domain contains a disallowed
|
|
471
|
+
codepoint under the chosen rules.
|
|
472
|
+
:raises IDNAError: If ``domain`` exceeds the defensive input length limit.
|
|
473
|
+
"""
|
|
474
|
+
if len(domain) > _max_input_length:
|
|
475
|
+
raise IDNAError("Domain too long")
|
|
476
|
+
from .uts46data import uts46_replacements, uts46_starts, uts46_statuses
|
|
335
477
|
|
|
336
478
|
output = ""
|
|
337
479
|
|
|
338
480
|
for pos, char in enumerate(domain):
|
|
339
481
|
code_point = ord(char)
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
482
|
+
i = code_point if code_point < 256 else bisect.bisect_right(uts46_starts, code_point) - 1
|
|
483
|
+
status = chr(uts46_statuses[i])
|
|
484
|
+
replacement: Optional[str] = uts46_replacements[i]
|
|
485
|
+
|
|
486
|
+
# UTS #46 §4: V is always valid, D is deviation (kept unless transitional),
|
|
487
|
+
# 3 is disallowed-STD3 (kept unmapped if std3_rules is off and no mapping).
|
|
488
|
+
keep_as_is = (
|
|
489
|
+
status == "V" or (status == "D" and not transitional) or (status == "3" and not std3_rules and replacement is None)
|
|
490
|
+
)
|
|
491
|
+
# M is mapped, 3-with-replacement and transitional D fall through to the
|
|
492
|
+
# same replacement output path.
|
|
493
|
+
use_replacement = replacement is not None and (
|
|
494
|
+
status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional)
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
if keep_as_is:
|
|
498
|
+
output += char
|
|
499
|
+
elif use_replacement:
|
|
500
|
+
assert replacement is not None # narrowed by use_replacement
|
|
501
|
+
output += replacement
|
|
502
|
+
elif status == "I":
|
|
503
|
+
continue
|
|
504
|
+
else:
|
|
505
|
+
raise InvalidCodepoint(f"Codepoint {_unot(code_point)} not allowed at position {pos + 1} in {domain!r}")
|
|
362
506
|
|
|
363
507
|
return unicodedata.normalize("NFC", output)
|
|
364
508
|
|
|
@@ -370,19 +514,52 @@ def encode(
|
|
|
370
514
|
std3_rules: bool = False,
|
|
371
515
|
transitional: bool = False,
|
|
372
516
|
) -> bytes:
|
|
517
|
+
"""Encode a Unicode domain name into its ASCII (A-label) form.
|
|
518
|
+
|
|
519
|
+
Splits the input on label separators (only ``U+002E`` if ``strict`` is
|
|
520
|
+
set; otherwise also IDEOGRAPHIC FULL STOP ``U+3002``, FULLWIDTH FULL
|
|
521
|
+
STOP ``U+FF0E``, and HALFWIDTH IDEOGRAPHIC FULL STOP ``U+FF61``),
|
|
522
|
+
encodes each label with :func:`alabel`, and rejoins them with ``.``.
|
|
523
|
+
Optionally pre-processes the input through :func:`uts46_remap`.
|
|
524
|
+
|
|
525
|
+
:param s: The domain name to encode.
|
|
526
|
+
:param strict: If ``True``, only ``U+002E`` is recognised as a label
|
|
527
|
+
separator.
|
|
528
|
+
:param uts46: If ``True``, apply UTS #46 mapping before encoding.
|
|
529
|
+
:param std3_rules: Forwarded to :func:`uts46_remap` when ``uts46`` is
|
|
530
|
+
``True``.
|
|
531
|
+
:param transitional: Forwarded to :func:`uts46_remap` when ``uts46``
|
|
532
|
+
is ``True``. Deprecated: emits a :class:`DeprecationWarning` and
|
|
533
|
+
will be removed in a future version.
|
|
534
|
+
:returns: The encoded domain as ASCII :class:`bytes`.
|
|
535
|
+
:raises IDNAError: If the domain is empty, contains an invalid label,
|
|
536
|
+
or exceeds the maximum domain length.
|
|
537
|
+
"""
|
|
538
|
+
if transitional:
|
|
539
|
+
warnings.warn(
|
|
540
|
+
"Transitional processing has been removed from UTS #46. "
|
|
541
|
+
"The transitional argument will be removed in a future version.",
|
|
542
|
+
DeprecationWarning,
|
|
543
|
+
stacklevel=2,
|
|
544
|
+
)
|
|
373
545
|
if not isinstance(s, str):
|
|
374
546
|
try:
|
|
375
547
|
s = str(s, "ascii")
|
|
376
|
-
except UnicodeDecodeError:
|
|
377
|
-
raise IDNAError("should pass a unicode string to the function rather than a byte string.")
|
|
548
|
+
except (UnicodeDecodeError, TypeError) as err:
|
|
549
|
+
raise IDNAError("should pass a unicode string to the function rather than a byte string.") from err
|
|
550
|
+
if len(s) > _max_input_length:
|
|
551
|
+
raise IDNAError("Domain too long")
|
|
378
552
|
if uts46:
|
|
379
553
|
s = uts46_remap(s, std3_rules, transitional)
|
|
554
|
+
|
|
555
|
+
# Reject inputs that exceed the maximum DNS domain length up-front
|
|
556
|
+
# to avoid expensive computation on long inputs.
|
|
557
|
+
if not valid_string_length(s, trailing_dot=True):
|
|
558
|
+
raise IDNAError("Domain too long")
|
|
559
|
+
|
|
380
560
|
trailing_dot = False
|
|
381
561
|
result = []
|
|
382
|
-
if strict
|
|
383
|
-
labels = s.split(".")
|
|
384
|
-
else:
|
|
385
|
-
labels = _unicode_dots_re.split(s)
|
|
562
|
+
labels = s.split(".") if strict else _unicode_dots_re.split(s)
|
|
386
563
|
if not labels or labels == [""]:
|
|
387
564
|
raise IDNAError("Empty domain")
|
|
388
565
|
if labels[-1] == "":
|
|
@@ -407,29 +584,63 @@ def decode(
|
|
|
407
584
|
strict: bool = False,
|
|
408
585
|
uts46: bool = False,
|
|
409
586
|
std3_rules: bool = False,
|
|
587
|
+
display: bool = False,
|
|
410
588
|
) -> str:
|
|
411
|
-
|
|
412
|
-
|
|
589
|
+
"""Decode an A-label-encoded domain name back to Unicode.
|
|
590
|
+
|
|
591
|
+
Splits the input on label separators (see :func:`encode` for the
|
|
592
|
+
rules), decodes each label with :func:`ulabel`, and rejoins them
|
|
593
|
+
with ``.``. Optionally pre-processes the input through
|
|
594
|
+
:func:`uts46_remap`.
|
|
595
|
+
|
|
596
|
+
:param s: The domain name to decode.
|
|
597
|
+
:param strict: If ``True``, only ``U+002E`` is recognised as a label
|
|
598
|
+
separator.
|
|
599
|
+
:param uts46: If ``True``, apply UTS #46 mapping before decoding.
|
|
600
|
+
:param std3_rules: Forwarded to :func:`uts46_remap` when ``uts46`` is
|
|
601
|
+
``True``.
|
|
602
|
+
:param display: If ``True``, any ``xn--`` label that fails IDNA
|
|
603
|
+
validation is passed through unchanged (lowercased) rather than
|
|
604
|
+
aborting the whole call. Intended for "decode for display"
|
|
605
|
+
consumers (e.g. URL libraries, HTTP clients) that want to show
|
|
606
|
+
the user the label as it appears on the wire when it cannot be
|
|
607
|
+
rendered as Unicode. Matches the per-label recovery prescribed
|
|
608
|
+
by UTS #46 §4 and the WHATWG URL "domain to Unicode" algorithm.
|
|
609
|
+
:returns: The decoded domain as a Unicode string.
|
|
610
|
+
:raises IDNAError: If the input is not valid ASCII, contains an
|
|
611
|
+
invalid label, or is empty.
|
|
612
|
+
"""
|
|
613
|
+
if not isinstance(s, str):
|
|
614
|
+
try:
|
|
413
615
|
s = str(s, "ascii")
|
|
414
|
-
|
|
415
|
-
|
|
616
|
+
except (UnicodeDecodeError, TypeError) as err:
|
|
617
|
+
raise IDNAError("Invalid ASCII in A-label") from err
|
|
618
|
+
if len(s) > _max_input_length:
|
|
619
|
+
raise IDNAError("Domain too long")
|
|
416
620
|
if uts46:
|
|
417
621
|
s = uts46_remap(s, std3_rules, False)
|
|
622
|
+
# Reject inputs that exceed the maximum DNS domain length up-front
|
|
623
|
+
# to avoid expensive computation on long inputs.
|
|
624
|
+
if not valid_string_length(s, trailing_dot=True):
|
|
625
|
+
raise IDNAError("Domain too long")
|
|
418
626
|
trailing_dot = False
|
|
419
627
|
result = []
|
|
420
|
-
if
|
|
421
|
-
labels = _unicode_dots_re.split(s)
|
|
422
|
-
else:
|
|
423
|
-
labels = s.split(".")
|
|
628
|
+
labels = s.split(".") if strict else _unicode_dots_re.split(s)
|
|
424
629
|
if not labels or labels == [""]:
|
|
425
630
|
raise IDNAError("Empty domain")
|
|
426
631
|
if not labels[-1]:
|
|
427
632
|
del labels[-1]
|
|
428
633
|
trailing_dot = True
|
|
429
634
|
for label in labels:
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
635
|
+
try:
|
|
636
|
+
u = ulabel(label)
|
|
637
|
+
except IDNAError:
|
|
638
|
+
if display and label[:4].lower() == "xn--":
|
|
639
|
+
u = label.lower()
|
|
640
|
+
else:
|
|
641
|
+
raise
|
|
642
|
+
if u:
|
|
643
|
+
result.append(u)
|
|
433
644
|
else:
|
|
434
645
|
raise IDNAError("Empty label")
|
|
435
646
|
if trailing_dot:
|